3 * Copyright 2002-2004 The Ant-Contrib project
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 package net
.sf
.antcontrib
.cpptasks
;
18 import java
.io
.BufferedReader
;
20 import java
.io
.FileReader
;
21 import java
.io
.IOException
;
22 import java
.lang
.reflect
.Method
;
23 import java
.util
.Vector
;
24 import net
.sf
.antcontrib
.cpptasks
.compiler
.LinkType
;
25 import net
.sf
.antcontrib
.cpptasks
.compiler
.Processor
;
26 import net
.sf
.antcontrib
.cpptasks
.compiler
.ProcessorConfiguration
;
27 import net
.sf
.antcontrib
.cpptasks
.types
.CommandLineArgument
;
28 import net
.sf
.antcontrib
.cpptasks
.types
.ConditionalFileSet
;
29 import org
.apache
.tools
.ant
.BuildException
;
30 import org
.apache
.tools
.ant
.DirectoryScanner
;
31 import org
.apache
.tools
.ant
.Project
;
32 import org
.apache
.tools
.ant
.types
.DataType
;
33 import org
.apache
.tools
.ant
.types
.Environment
;
34 import org
.apache
.tools
.ant
.types
.Reference
;
36 * An abstract compiler/linker definition.
40 public abstract class ProcessorDef
extends DataType
{
42 * Returns the equivalent Boolean object for the specified value
44 * Equivalent to Boolean.valueOf in JDK 1.4
48 * @return Boolean.TRUE or Boolean.FALSE
50 protected static Boolean
booleanValueOf(boolean val
) {
57 * if true, targets will be built for debugging
59 private Boolean debug
;
60 private Environment env
= null;
62 * Reference for "extends" processor definition
64 private Reference extendsRef
= null;
66 * Name of property that must be present or definition will be ignored. May
69 private String ifProp
;
71 * if true, processor definition inherits values from containing <cc>
74 private boolean inherit
;
75 private Boolean libtool
= null;
76 protected boolean newEnvironment
= false;
80 private Processor processor
;
82 * Collection of <compilerarg>or <linkerarg>contained by definition
84 private final Vector processorArgs
= new Vector();
86 * Collection of <compilerparam>or <linkerparam>contained by definition
88 private final Vector processorParams
= new Vector();
90 * if true, all targets will be unconditionally rebuilt
92 private Boolean rebuild
;
94 * Collection of <fileset>contained by definition
96 private final Vector srcSets
= new Vector();
98 * Name of property that if present will cause definition to be ignored.
101 private String unlessProp
;
106 protected ProcessorDef() throws NullPointerException
{
110 * Adds a <compilerarg>or <linkerarg>
113 * command line argument, must not be null
114 * @throws NullPointerException
116 * @throws BuildException
117 * if this definition is a reference
119 protected void addConfiguredProcessorArg(CommandLineArgument arg
)
120 throws NullPointerException
, BuildException
{
122 throw new NullPointerException("arg");
125 throw noChildrenAllowed();
127 if(arg
.getFile() == null ) {
128 processorArgs
.addElement(arg
);
131 loadFile(arg
.getFile());
135 * Add a <compilerarg>or <linkerarg> if specify the file attribute
138 * command line argument, must not be null
139 * @throws BuildException
140 * if the specify file not exist
142 protected void loadFile(File file
)
143 throws BuildException
{
144 FileReader fileReader
;
147 if (! file
.exists()){
148 throw new BuildException("The file " + file
+ " is not existed");
151 fileReader
= new FileReader(file
);
152 in
= new BufferedReader(fileReader
);
153 while ( (str
= in
.readLine()) != null ){
154 if(str
.trim() == ""){
157 str
= getProject().replaceProperties(str
);
158 CommandLineArgument newarg
= new CommandLineArgument();
159 newarg
.setValue(str
.trim());
160 processorArgs
.addElement(newarg
);
164 throw new BuildException(e
.getMessage());
168 * Adds a <compilerarg>or <linkerarg>
171 * command line argument, must not be null
172 * @throws NullPointerException
174 * @throws BuildException
175 * if this definition is a reference
177 protected void addConfiguredProcessorParam(ProcessorParam param
)
178 throws NullPointerException
, BuildException
{
180 throw new NullPointerException("param");
183 throw noChildrenAllowed();
185 processorParams
.addElement(param
);
188 * Add an environment variable to the launched process.
190 public void addEnv(Environment
.Variable var
) {
192 env
= new Environment();
194 env
.addVariable(var
);
197 * Adds a source file set.
199 * Files in these set will be processed by this configuration and will not
200 * participate in the auction.
203 * Fileset identifying files that should be processed by this
205 * @throws BuildException
206 * if processor definition is a reference
208 public void addFileset(ConditionalFileSet srcSet
) throws BuildException
{
210 throw noChildrenAllowed();
212 srcSet
.setProject(getProject());
213 srcSets
.addElement(srcSet
);
216 * Creates a configuration
219 * reference to def from containing <cc>element, may be null
220 * @return configuration
223 public ProcessorConfiguration
createConfiguration(CCTask task
,
224 LinkType linkType
, ProcessorDef baseDef
, TargetDef targetPlatform
) {
226 return ((ProcessorDef
) getCheckedRef(ProcessorDef
.class,
227 "ProcessorDef")).createConfiguration(task
, linkType
,
228 baseDef
, targetPlatform
);
230 ProcessorDef
[] defaultProviders
= getDefaultProviders(baseDef
);
231 Processor proc
= getProcessor();
232 return proc
.createConfiguration(task
, linkType
, defaultProviders
, this, targetPlatform
);
235 * Prepares list of processor arguments ( <compilerarg>, <linkerarg>) that
236 * are active for the current project settings.
238 * @return active compiler arguments
240 public CommandLineArgument
[] getActiveProcessorArgs() {
241 Project p
= getProject();
243 throw new java
.lang
.IllegalStateException("project must be set");
246 return ((ProcessorDef
) getCheckedRef(ProcessorDef
.class,
247 "ProcessorDef")).getActiveProcessorArgs();
249 Vector activeArgs
= new Vector(processorArgs
.size());
250 for (int i
= 0; i
< processorArgs
.size(); i
++) {
251 CommandLineArgument arg
= (CommandLineArgument
) processorArgs
253 if (arg
.isActive(p
)) {
254 activeArgs
.addElement(arg
);
257 CommandLineArgument
[] array
= new CommandLineArgument
[activeArgs
.size()];
258 activeArgs
.copyInto(array
);
262 * Prepares list of processor arguments ( <compilerarg>, <linkerarg>) that
263 * are active for the current project settings.
265 * @return active compiler arguments
267 public ProcessorParam
[] getActiveProcessorParams() {
268 Project p
= getProject();
270 throw new java
.lang
.IllegalStateException("project must be set");
273 return ((ProcessorDef
) getCheckedRef(ProcessorDef
.class,
274 "ProcessorDef")).getActiveProcessorParams();
276 Vector activeParams
= new Vector(processorParams
.size());
277 for (int i
= 0; i
< processorParams
.size(); i
++) {
278 ProcessorParam param
= (ProcessorParam
) processorParams
280 if (param
.isActive(p
)) {
281 activeParams
.addElement(param
);
284 ProcessorParam
[] array
= new ProcessorParam
[activeParams
.size()];
285 activeParams
.copyInto(array
);
289 * Gets boolean indicating debug build
291 * @param defaultProviders
292 * array of ProcessorDef's in descending priority
294 * index to first element in array that should be considered
295 * @return if true, built targets for debugging
297 public boolean getDebug(ProcessorDef
[] defaultProviders
, int index
) {
299 return ((ProcessorDef
) getCheckedRef(ProcessorDef
.class,
300 "ProcessorDef")).getDebug(defaultProviders
, index
);
303 return debug
.booleanValue();
305 if (defaultProviders
!= null && index
< defaultProviders
.length
) {
306 return defaultProviders
[index
].getDebug(defaultProviders
,
313 * Creates an chain of objects which provide default values in descending
314 * order of significance.
317 * corresponding ProcessorDef from CCTask, will be last element
318 * in array unless inherit = false
319 * @return default provider array
322 protected final ProcessorDef
[] getDefaultProviders(ProcessorDef baseDef
) {
323 ProcessorDef extendsDef
= getExtends();
324 Vector chain
= new Vector();
325 while (extendsDef
!= null && !chain
.contains(extendsDef
)) {
326 chain
.addElement(extendsDef
);
327 extendsDef
= extendsDef
.getExtends();
329 if (baseDef
!= null && getInherit()) {
330 chain
.addElement(baseDef
);
332 ProcessorDef
[] defaultProviders
= new ProcessorDef
[chain
.size()];
333 chain
.copyInto(defaultProviders
);
334 return defaultProviders
;
337 * Gets the ProcessorDef specified by the extends attribute
339 * @return Base ProcessorDef, null if extends is not specified
340 * @throws BuildException
341 * if reference is not same type object
343 public ProcessorDef
getExtends() throws BuildException
{
344 if (extendsRef
!= null) {
345 Object obj
= extendsRef
.getReferencedObject(getProject());
346 if (!getClass().isInstance(obj
)) {
347 throw new BuildException("Referenced object "
348 + extendsRef
.getRefId() + " not correct type, is "
349 + obj
.getClass().getName() + " should be "
350 + getClass().getName());
352 return (ProcessorDef
) obj
;
357 * Gets the inherit attribute. If the inherit value is true, this processor
358 * definition will inherit default values from the containing <cc>element.
360 * @return if true then properties from the containing <cc>element are
363 public final boolean getInherit() {
366 public boolean getLibtool() {
367 if (libtool
!= null) {
368 return libtool
.booleanValue();
371 return ((ProcessorDef
) getCheckedRef(ProcessorDef
.class,
372 "ProcessorDef")).getLibtool();
374 ProcessorDef extendsDef
= getExtends();
375 if (extendsDef
!= null) {
376 return extendsDef
.getLibtool();
381 * Obtains the appropriate processor (compiler, linker)
385 protected Processor
getProcessor() {
387 return ((ProcessorDef
) getCheckedRef(ProcessorDef
.class,
388 "ProcessorDef")).getProcessor();
391 // if a processor has not been explicitly set
392 // then may be set by an extended definition
393 if (processor
== null) {
394 ProcessorDef extendsDef
= getExtends();
395 if (extendsDef
!= null) {
396 return extendsDef
.getProcessor();
402 * Gets a boolean value indicating whether all targets must be rebuilt
403 * regardless of dependency analysis.
405 * @param defaultProviders
406 * array of ProcessorDef's in descending priority
408 * index to first element in array that should be considered
409 * @return true if all targets should be rebuilt.
411 public boolean getRebuild(ProcessorDef
[] defaultProviders
, int index
) {
413 return ((ProcessorDef
) getCheckedRef(ProcessorDef
.class,
414 "ProcessorDef")).getRebuild(defaultProviders
, index
);
416 if (rebuild
!= null) {
417 return rebuild
.booleanValue();
419 if (defaultProviders
!= null && index
< defaultProviders
.length
) {
420 return defaultProviders
[index
].getRebuild(defaultProviders
,
427 * Returns true if the processor definition contains embedded file set
430 * @return true if processor definition contains embedded filesets
432 public boolean hasFileSets() {
434 return ((ProcessorDef
) getCheckedRef(ProcessorDef
.class,
435 "ProcessorDef")).hasFileSets();
437 return srcSets
.size() > 0;
440 * Determine if this def should be used.
442 * Definition will be active if the "if" variable (if specified) is set and
443 * the "unless" variable (if specified) is not set and that all reference
444 * or extended definitions are active
446 * @return true if processor is active
447 * @throws IllegalStateException
448 * if not properly initialized
449 * @throws BuildException
450 * if "if" or "unless" variable contains suspicious values
451 * "false" or "no" which indicates possible confusion
453 public boolean isActive() throws BuildException
, IllegalStateException
{
454 Project project
= getProject();
455 if (!CUtil
.isActive(project
, ifProp
, unlessProp
)) {
459 if (!((ProcessorDef
) getCheckedRef(ProcessorDef
.class,
460 "ProcessorDef")).isActive()) {
465 // walk through any extended definitions
467 ProcessorDef
[] defaultProviders
= getDefaultProviders(null);
468 for (int i
= 0; i
< defaultProviders
.length
; i
++) {
469 if (!defaultProviders
[i
].isActive()) {
476 * Sets the class name for the adapter. Use the "name" attribute when the
483 public void setClassname(String className
) throws BuildException
{
486 Class implClass
= ProcessorDef
.class.getClassLoader().loadClass(
489 Method getInstance
= implClass
.getMethod("getInstance",
491 proc
= getInstance
.invoke(null, new Object
[0]);
492 } catch (Exception ex
) {
493 proc
= implClass
.newInstance();
495 } catch (Exception ex
) {
496 throw new BuildException(ex
);
498 setProcessor((Processor
) proc
);
501 * If set true, all targets will be built for debugging.
504 * true if targets should be built for debugging
505 * @throws BuildException
506 * if processor definition is a reference
508 public void setDebug(boolean debug
) throws BuildException
{
510 throw tooManyAttributes();
512 this.debug
= booleanValueOf(debug
);
515 * Sets a description of the current data type.
517 public void setDescription(String desc
) {
518 super.setDescription(desc
);
521 * Specifies that this element extends the element with id attribute with a
522 * matching value. The configuration will be constructed from the settings
523 * of this element, element referenced by extends, and the containing cc
527 * Reference to the extended processor definition.
528 * @throws BuildException
529 * if this processor definition is a reference
531 public void setExtends(Reference extendsRef
) throws BuildException
{
533 throw tooManyAttributes();
535 this.extendsRef
= extendsRef
;
538 * Sets an id that can be used to reference this element.
543 public void setId(String id
) {
545 // this is actually accomplished by a different
546 // mechanism, but we can document it
550 * Sets the property name for the 'if' condition.
552 * The configuration will be ignored unless the property is defined.
554 * The value of the property is insignificant, but values that would imply
555 * misinterpretation ("false", "no") will throw an exception when
561 public void setIf(String propName
) {
565 * If inherit has the default value of true, defines, includes and other
566 * settings from the containing <cc>element will be inherited.
570 * @throws BuildException
571 * if processor definition is a reference
573 public void setInherit(boolean inherit
) throws BuildException
{
575 throw super.tooManyAttributes();
577 this.inherit
= inherit
;
580 * Set use of libtool.
582 * If set to true, the "libtool " will be prepended to the command line
585 * If true, use libtool.
587 public void setLibtool(boolean libtool
) {
589 throw tooManyAttributes();
591 this.libtool
= booleanValueOf(libtool
);
594 * Do not propagate old environment when new environment variables are
597 public void setNewenvironment(boolean newenv
) {
598 newEnvironment
= newenv
;
604 * processor, may not be null.
605 * @throws BuildException
606 * if ProcessorDef is a reference
607 * @throws NullPointerException
608 * if processor is null
610 protected void setProcessor(Processor processor
) throws BuildException
,
611 NullPointerException
{
612 if (processor
== null) {
613 throw new NullPointerException("processor");
616 throw super.tooManyAttributes();
618 if (env
== null && !newEnvironment
) {
619 this.processor
= processor
;
621 this.processor
= processor
.changeEnvironment(newEnvironment
, env
);
625 * If set true, all targets will be unconditionally rebuilt.
628 * if true, rebuild all targets.
629 * @throws BuildException
630 * if processor definition is a reference
632 public void setRebuild(boolean rebuild
) throws BuildException
{
634 throw tooManyAttributes();
636 this.rebuild
= booleanValueOf(rebuild
);
639 * Specifies that this element should behave as if the content of the
640 * element with the matching id attribute was inserted at this location. If
641 * specified, no other attributes or child content should be specified,
642 * other than "if", "unless" and "description".
645 * Reference to other element
648 public void setRefid(org
.apache
.tools
.ant
.types
.Reference ref
) {
652 * Set the property name for the 'unless' condition.
654 * If named property is set, the configuration will be ignored.
656 * The value of the property is insignificant, but values that would imply
657 * misinterpretation ("false", "no") of the behavior will throw an
658 * exception when evaluated.
663 public void setUnless(String propName
) {
664 unlessProp
= propName
;
667 * This method calls the FileVistor's visit function for every file in the
668 * processors definition
671 * object whose visit method is called for every file
673 public void visitFiles(FileVisitor visitor
) {
674 Project p
= getProject();
676 throw new java
.lang
.IllegalStateException(
677 "project must be set before this call");
680 ((ProcessorDef
) getCheckedRef(ProcessorDef
.class, "ProcessorDef"))
681 .visitFiles(visitor
);
684 // if this processor extends another,
685 // visit its files first
687 ProcessorDef extendsDef
= getExtends();
688 if (extendsDef
!= null) {
689 extendsDef
.visitFiles(visitor
);
691 for (int i
= 0; i
< srcSets
.size(); i
++) {
692 ConditionalFileSet srcSet
= (ConditionalFileSet
) srcSets
694 if (srcSet
.isActive()) {
695 // Find matching source files
696 DirectoryScanner scanner
= srcSet
.getDirectoryScanner(p
);
697 // Check each source file - see if it needs compilation
698 String
[] fileNames
= scanner
.getIncludedFiles();
699 File parentDir
= scanner
.getBasedir();
700 for (int j
= 0; j
< fileNames
.length
; j
++) {
701 String currentFile
= fileNames
[j
];
702 visitor
.visit(parentDir
, currentFile
);
707 public Vector
getSrcSets() {
709 return ((ProcessorDef
) getCheckedRef(ProcessorDef
.class,
710 "ProcessorDef")).getSrcSets();