View Javadoc

1   /*
2    * #%L
3    * Native ARchive plugin for Maven
4    * %%
5    * Copyright (C) 2002 - 2014 NAR Maven Plugin developers.
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   * 
11   * http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package com.github.maven_nar.cpptasks.compiler;
21  
22  import java.io.File;
23  
24  import org.apache.tools.ant.BuildException;
25  
26  import com.github.maven_nar.cpptasks.CCTask;
27  import com.github.maven_nar.cpptasks.CompilerParam;
28  import com.github.maven_nar.cpptasks.DependencyInfo;
29  import com.github.maven_nar.cpptasks.ProcessorParam;
30  import com.github.maven_nar.cpptasks.VersionInfo;
31  
32  /**
33   * A configuration for a C++ compiler
34   *
35   * @author Curt Arnold
36   */
37  public final class CommandLineCompilerConfiguration implements CompilerConfiguration {
38    private boolean useCcache;
39    private/* final */String[] args;
40    private final/* final */CommandLineCompiler compiler;
41    private final String[] endArgs;
42    //
43    // include path from environment variable not
44    // explicitly stated in Ant script
45    private/* final */File[] envIncludePath;
46    private String[] exceptFiles;
47    private final/* final */String identifier;
48    private/* final */File[] includePath;
49    private final/* final */String includePathIdentifier;
50    private final boolean isPrecompiledHeaderGeneration;
51    private/* final */ProcessorParam[] params;
52    private final/* final */boolean rebuild;
53    private/* final */File[] sysIncludePath;
54    private/* final */String commandPath;
55  
56    public CommandLineCompilerConfiguration(final CommandLineCompiler compiler, final String identifier,
57        final File[] includePath, final File[] sysIncludePath, final File[] envIncludePath,
58        final String includePathIdentifier, final String[] args, final ProcessorParam[] params, final boolean rebuild,
59        final String[] endArgs) {
60      this(compiler, identifier, includePath, sysIncludePath, envIncludePath, includePathIdentifier, args, params,
61          rebuild, endArgs, null);
62    }
63  
64    public CommandLineCompilerConfiguration(final CommandLineCompiler compiler, final String identifier,
65        final File[] includePath, final File[] sysIncludePath, final File[] envIncludePath,
66        final String includePathIdentifier, final String[] args, final ProcessorParam[] params, final boolean rebuild,
67        final String[] endArgs, final String commandPath) {
68      this(compiler, identifier, includePath, sysIncludePath, envIncludePath, includePathIdentifier, args, params,
69          rebuild, endArgs, commandPath, false);
70    }
71  
72    public CommandLineCompilerConfiguration(final CommandLineCompiler compiler, final String identifier,
73        final File[] includePath, final File[] sysIncludePath, final File[] envIncludePath,
74        final String includePathIdentifier, final String[] args, final ProcessorParam[] params, final boolean rebuild,
75        final String[] endArgs, final String commandPath, final boolean useCcache) {
76      if (compiler == null) {
77        throw new NullPointerException("compiler");
78      }
79      if (identifier == null) {
80        throw new NullPointerException("identifier");
81      }
82      if (includePathIdentifier == null) {
83        throw new NullPointerException("includePathIdentifier");
84      }
85      if (args == null) {
86        this.args = new String[0];
87      } else {
88        this.args = args.clone();
89      }
90      if (includePath == null) {
91        this.includePath = new File[0];
92      } else {
93        this.includePath = includePath.clone();
94      }
95      if (sysIncludePath == null) {
96        this.sysIncludePath = new File[0];
97      } else {
98        this.sysIncludePath = sysIncludePath.clone();
99      }
100     if (envIncludePath == null) {
101       this.envIncludePath = new File[0];
102     } else {
103       this.envIncludePath = envIncludePath.clone();
104     }
105     this.useCcache = useCcache;
106     this.compiler = compiler;
107     this.params = params.clone();
108     this.rebuild = rebuild;
109     this.identifier = identifier;
110     this.includePathIdentifier = includePathIdentifier;
111     this.endArgs = endArgs.clone();
112     this.exceptFiles = null;
113     this.isPrecompiledHeaderGeneration = false;
114     this.commandPath = commandPath;
115   }
116 
117   public CommandLineCompilerConfiguration(final CommandLineCompilerConfiguration base, final String[] additionalArgs,
118       final String[] exceptFiles, final boolean isPrecompileHeaderGeneration) {
119     this.compiler = base.compiler;
120     this.identifier = base.identifier;
121     this.rebuild = base.rebuild;
122     this.includePath = base.includePath.clone();
123     this.sysIncludePath = base.sysIncludePath.clone();
124     this.endArgs = base.endArgs.clone();
125     this.envIncludePath = base.envIncludePath.clone();
126     this.includePathIdentifier = base.includePathIdentifier;
127     if (exceptFiles != null) {
128       this.exceptFiles = exceptFiles.clone();
129     }
130     this.isPrecompiledHeaderGeneration = isPrecompileHeaderGeneration;
131     if (additionalArgs != null) {
132       this.args = new String[base.args.length + additionalArgs.length];
133       System.arraycopy(base.args, 0, this.args, 0, base.args.length);
134       int index = base.args.length;
135       for (final String additionalArg : additionalArgs) {
136         this.args[index++] = additionalArg;
137       }
138     } else {
139       this.args = base.args.clone();
140     }
141     this.commandPath = base.commandPath;
142   }
143 
144   @Override
145   public int bid(final String inputFile) {
146     final int compilerBid = this.compiler.bid(inputFile);
147     if (compilerBid > 0 && this.exceptFiles != null) {
148       for (final String exceptFile : this.exceptFiles) {
149         if (inputFile.equals(exceptFile)) {
150           return 0;
151         }
152       }
153     }
154     return compilerBid;
155   }
156 
157   @Override
158   public void compile(final CCTask task, final File outputDir, final String[] sourceFiles, final boolean relentless,
159       final ProgressMonitor monitor) throws BuildException {
160     if (monitor != null) {
161       monitor.start(this);
162     }
163     try {
164       this.compiler.compile(task, outputDir, sourceFiles, this.args, this.endArgs, relentless, this, monitor);
165       if (monitor != null) {
166         monitor.finish(this, true);
167       }
168     } catch (final BuildException ex) {
169       if (monitor != null) {
170         monitor.finish(this, false);
171       }
172       throw ex;
173     }
174   }
175 
176   /**
177    * 
178    * This method may be used to get two distinct compiler configurations, one
179    * for compiling the specified file and producing a precompiled header
180    * file, and a second for compiling other files using the precompiled
181    * header file.
182    * 
183    * The last (preferrably only) include directive in the prototype file will
184    * be used to mark the boundary between pre-compiled and normally compiled
185    * headers.
186    * 
187    * @param prototype
188    *          A source file (for example, stdafx.cpp) that is used to build
189    *          the precompiled header file. @returns null if precompiled
190    *          headers are not supported or a two element array containing
191    *          the precompiled header generation configuration and the
192    *          consuming configuration
193    * 
194    */
195   @Override
196   public CompilerConfiguration[]
197       createPrecompileConfigurations(final File prototype, final String[] nonPrecompiledFiles) {
198     if (this.compiler instanceof PrecompilingCompiler) {
199       return ((PrecompilingCompiler) this.compiler)
200           .createPrecompileConfigurations(this, prototype, nonPrecompiledFiles);
201     }
202     return null;
203   }
204 
205   public String getCommand() {
206     return this.compiler.getCommand();
207   }
208 
209   public final String getCommandPath() {
210     return this.commandPath;
211   }
212 
213   public Compiler getCompiler() {
214     return this.compiler;
215   }
216 
217   public String[] getEndArguments() {
218     return this.endArgs.clone();
219   }
220 
221   /**
222    * Returns a string representation of this configuration. Should be
223    * canonical so that equivalent configurations will have equivalent string
224    * representations
225    */
226   @Override
227   public String getIdentifier() {
228     return this.identifier;
229   }
230 
231   public File[] getIncludePath() {
232     return this.includePath.clone();
233   }
234 
235   @Override
236   public String getIncludePathIdentifier() {
237     return this.includePathIdentifier;
238   }
239 
240   @Override
241   public String[] getOutputFileNames(final String inputFile, final VersionInfo versionInfo) {
242     return this.compiler.getOutputFileNames(inputFile, versionInfo);
243   }
244 
245   @Override
246   public CompilerParam getParam(final String name) {
247     for (final ProcessorParam param : this.params) {
248       if (name.equals(param.getName())) {
249         return (CompilerParam) param;
250       }
251     }
252     return null;
253   }
254 
255   @Override
256   public ProcessorParam[] getParams() {
257     return this.params;
258   }
259 
260   public String[] getPreArguments() {
261     return this.args.clone();
262   }
263 
264   @Override
265   public boolean getRebuild() {
266     return this.rebuild;
267   }
268 
269   @Override
270   public boolean isPrecompileGeneration() {
271     return this.isPrecompiledHeaderGeneration;
272   }
273 
274   public boolean isUseCcache() {
275     return this.useCcache;
276   }
277 
278   @Override
279   public DependencyInfo parseIncludes(final CCTask task, final File baseDir, final File source) {
280     return this.compiler.parseIncludes(task, source, this.includePath, this.sysIncludePath, this.envIncludePath,
281         baseDir, getIncludePathIdentifier());
282   }
283 
284   public final void setCommandPath(final String commandPath) {
285     this.commandPath = commandPath;
286   }
287 
288   @Override
289   public String toString() {
290     return this.identifier;
291   }
292 }