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.ide;
21  
22  import java.io.File;
23  import java.lang.reflect.Method;
24  import java.util.ArrayList;
25  import java.util.List;
26  import java.util.Map;
27  
28  import org.apache.tools.ant.BuildException;
29  import org.apache.tools.ant.Project;
30  import org.apache.tools.ant.types.DataType;
31  
32  import com.github.maven_nar.cpptasks.CCTask;
33  import com.github.maven_nar.cpptasks.CUtil;
34  import com.github.maven_nar.cpptasks.TargetInfo;
35  
36  /**
37   * Requests the creation of an IDE project file. Experimental.
38   *
39   * Implementation status: msdev5, msdev6 and cbuilderx
40   * generate reasonable project files for simple projects,
41   * xcode and msdev7 and msdev71 capture source file lists and
42   * a few settings.
43   *
44   * @author Curt Arnold
45   */
46  public final class ProjectDef extends DataType {
47    /**
48     * Name of property that must be present or definition will be ignored. May
49     * be null.
50     */
51    private String ifProp;
52  
53    /**
54     * Name of property that must be absent or definition will be ignored. May
55     * be null.
56     */
57    private String unlessProp;
58  
59    /**
60     * Project file name.
61     */
62    private File outFile;
63  
64    /**
65     * Project name.
66     */
67    private String name;
68  
69    /**
70     * Fail on error.
71     */
72    private boolean failOnError = true;
73  
74    /**
75     * Overwrite existing project file.
76     */
77    private boolean overwrite = true;
78  
79    /**
80     * Project writer.
81     */
82    private ProjectWriter projectWriter;
83  
84    /**
85     * Object directory.
86     *
87     */
88    private File objDir;
89  
90    /**
91     * List of dependency definitions.
92     */
93    private final List<DependencyDef> dependencies = new ArrayList<>();
94  
95    /**
96     * List of comments.
97     */
98    private final List<CommentDef> comments = new ArrayList<>();
99  
100   /**
101    * Constructor.
102    *
103    */
104   public ProjectDef() {
105   }
106 
107   /**
108    * Add comment for the generated project file.
109    * 
110    * @param comment
111    *          comment, may not be null.
112    */
113   public void addComment(final CommentDef comment) {
114     this.comments.add(comment);
115 
116   }
117 
118   /**
119    * Add a dependency definition to the project.
120    * 
121    * @param dependency
122    *          dependency.
123    */
124   public void addDependency(final DependencyDef dependency) {
125     this.dependencies.add(dependency);
126 
127   }
128 
129   /**
130    * Required by documentation generator.
131    */
132   public void execute() {
133     throw new org.apache.tools.ant.BuildException("Not an actual task, but looks like one for documentation purposes");
134   }
135 
136   /**
137    * Executes the task. Compiles the given files.
138    *
139    * @param task
140    *          cc task
141    * @param sources
142    *          source files (includes headers)
143    * @param targets
144    *          compilation targets
145    * @param linkTarget
146    *          link target
147    */
148   public void execute(final CCTask task, final List<File> sources, final Map<String, TargetInfo> targets,
149       final TargetInfo linkTarget) {
150     try {
151       this.projectWriter.writeProject(this.outFile, task, this, sources, targets, linkTarget);
152     } catch (final BuildException ex) {
153       if (this.failOnError) {
154         throw ex;
155       } else {
156         task.log(ex.toString());
157       }
158     } catch (final Exception ex) {
159       if (this.failOnError) {
160         throw new BuildException(ex);
161       } else {
162         task.log(ex.toString());
163       }
164     }
165   }
166 
167   public List<CommentDef> getComments() {
168     return new ArrayList<>(this.comments);
169   }
170 
171   public List<DependencyDef> getDependencies() {
172     return new ArrayList<>(this.dependencies);
173   }
174 
175   /**
176    * Get name.
177    * 
178    * @return String name
179    */
180   public String getName() {
181     return this.name;
182   }
183 
184   /**
185    * Gets the object files directory.
186    * 
187    * @return directory, may be null.
188    */
189   public File getObjdir() {
190     return this.objDir;
191   }
192 
193   /**
194    * Sets the directory used for object files. If not specified,
195    * the object files directory from cc task will be used.
196    * 
197    * @param oDir
198    *          object file directory.
199    */
200   public void getObjdir(final File oDir) {
201     this.objDir = oDir;
202   }
203 
204   /**
205    * Gets whether an existing project file should be overwritten,
206    * default is true. If false and the project file exists,
207    * the value of failonerror will determine if the task fails.
208    *
209    * @return value
210    */
211   public boolean getOverwrite() {
212     return this.overwrite;
213   }
214 
215   /**
216    * Determine if this def should be used.
217    *
218    * Definition will be active if the "if" variable (if specified) is set and
219    * the "unless" variable (if specified) is not set and that all reference
220    * or extended definitions are active
221    *
222    * @return true if processor is active
223    */
224   public boolean isActive() {
225     final Project project = getProject();
226     if (!CUtil.isActive(project, this.ifProp, this.unlessProp)) {
227       return false;
228     }
229     return true;
230   }
231 
232   /**
233    * Class name for a user-supplied project writer. Use the "type"
234    * attribute to specify built-in project writer implementations.
235    *
236    * @param className
237    *          full class name
238    *
239    */
240   public void setClassname(final String className) {
241     Object proc = null;
242     try {
243       final Class<?> implClass = ProjectDef.class.getClassLoader().loadClass(className);
244       try {
245         final Method getInstance = implClass.getMethod("getInstance");
246         proc = getInstance.invoke(null);
247       } catch (final Exception ex) {
248         proc = implClass.newInstance();
249       }
250     } catch (final Exception ex) {
251       throw new BuildException(ex);
252     }
253     this.projectWriter = (ProjectWriter) proc;
254   }
255 
256   /**
257    * Sets whether a failure to write the project file should cause the
258    * task to fail. Default is true.
259    *
260    * @param value
261    *          new value
262    */
263   public void setFailonerror(final boolean value) {
264     this.failOnError = value;
265   }
266 
267   /**
268    * Sets the property name for the 'if' condition.
269    *
270    * The configuration will be ignored unless the property is defined.
271    *
272    * The value of the property is insignificant, but values that would imply
273    * misinterpretation ("false", "no") will throw an exception when
274    * evaluated.
275    *
276    * @param propName
277    *          name of property
278    */
279   public void setIf(final String propName) {
280     this.ifProp = propName;
281   }
282 
283   /**
284    * Set name.
285    * 
286    * @param value
287    *          String name
288    */
289   public void setName(final String value) {
290     this.name = value;
291   }
292 
293   /**
294    * Sets the name for the generated project file.
295    *
296    * @param outfile
297    *          output file name
298    */
299   public void setOutfile(final File outfile) {
300     //
301     // if file name was empty, skip link step
302     //
303     if (outfile == null || outfile.toString().length() > 0) {
304       this.outFile = outfile;
305     }
306   }
307 
308   /**
309    * Sets whether an existing project file should be overwritten,
310    * default is true. If false and the project file exists,
311    * the value of failonerror will determine if the task fails.
312    *
313    * @param value
314    *          new value
315    */
316   public void setOverwrite(final boolean value) {
317     this.overwrite = value;
318   }
319 
320   /**
321    * Set project type.
322    *
323    *
324    * <table width="100%" border="1">
325    * <thead>Supported project formats </thead>
326    * <tr>
327    * <td>cbuilderx</td>
328    * <td>Borland C++BuilderX</td>
329    * </tr>
330    * <tr>
331    * <td>msvc5</td>
332    * <td>Microsoft Visual C++ 97</td>
333    * </tr>
334    * <tr>
335    * <td>msvc6</td>
336    * <td>Microsoft Visual C++ 6</td>
337    * </tr>
338    * <tr>
339    * <td>msvc7</td>
340    * <td>Microsoft Visual C++.NET</td>
341    * </tr>
342    * <tr>
343    * <td>msvc71</td>
344    * <td>Microsoft Visual C++.NET 2003</td>
345    * </tr>
346    * <tr>
347    * <td>msvc8</td>
348    * <td>Microsoft Visual C++ 2005</td>
349    * </tr>
350    * <tr>
351    * <td>msvc9</td>
352    * <td>Microsoft Visual C++ 2008</td>
353    * </tr>
354    * <tr>
355    * <td>xcode</td>
356    * <td>Apple Xcode</td>
357    * </tr>
358    * </table>
359    *
360    * @param value
361    *          new value
362    */
363   public void setType(final ProjectWriterEnum value) {
364     this.projectWriter = value.getProjectWriter();
365   }
366 
367   /**
368    * Set the property name for the 'unless' condition.
369    *
370    * If named property is set, the configuration will be ignored.
371    *
372    * The value of the property is insignificant, but values that would imply
373    * misinterpretation ("false", "no") of the behavior will throw an
374    * exception when evaluated.
375    *
376    * @param propName
377    *          name of property
378    */
379   public void setUnless(final String propName) {
380     this.unlessProp = propName;
381   }
382 
383 }