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 }