3 * Copyright 2001-2005 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
;
20 import java
.io
.IOException
;
21 import java
.util
.Enumeration
;
22 import java
.util
.Hashtable
;
23 import java
.util
.Iterator
;
24 import java
.util
.Vector
;
26 import net
.sf
.antcontrib
.cpptasks
.compiler
.AslcompilerConfiguration
;
27 import net
.sf
.antcontrib
.cpptasks
.compiler
.AssemblerConfiguration
;
28 import net
.sf
.antcontrib
.cpptasks
.compiler
.CompilerConfiguration
;
29 import net
.sf
.antcontrib
.cpptasks
.compiler
.LinkType
;
30 import net
.sf
.antcontrib
.cpptasks
.compiler
.Linker
;
31 import net
.sf
.antcontrib
.cpptasks
.compiler
.LinkerConfiguration
;
32 import net
.sf
.antcontrib
.cpptasks
.compiler
.Processor
;
33 import net
.sf
.antcontrib
.cpptasks
.compiler
.ProcessorConfiguration
;
34 import net
.sf
.antcontrib
.cpptasks
.types
.AslcompilerArgument
;
35 import net
.sf
.antcontrib
.cpptasks
.types
.AssemblerArgument
;
36 import net
.sf
.antcontrib
.cpptasks
.types
.CompilerArgument
;
37 import net
.sf
.antcontrib
.cpptasks
.types
.ConditionalFileSet
;
38 import net
.sf
.antcontrib
.cpptasks
.types
.DefineSet
;
39 import net
.sf
.antcontrib
.cpptasks
.types
.IncludePath
;
40 import net
.sf
.antcontrib
.cpptasks
.types
.LibrarySet
;
41 import net
.sf
.antcontrib
.cpptasks
.types
.LinkerArgument
;
42 import net
.sf
.antcontrib
.cpptasks
.types
.SystemIncludePath
;
43 import net
.sf
.antcontrib
.cpptasks
.types
.SystemLibrarySet
;
44 import net
.sf
.antcontrib
.cpptasks
.userdefine
.UserDefineCompiler
;
45 import net
.sf
.antcontrib
.cpptasks
.userdefine
.UserDefineDef
;
46 import net
.sf
.antcontrib
.cpptasks
.VersionInfo
;
48 import org
.apache
.tools
.ant
.BuildException
;
49 import org
.apache
.tools
.ant
.Project
;
50 import org
.apache
.tools
.ant
.Task
;
51 import org
.apache
.tools
.ant
.types
.Environment
;
54 * Compile, link, assembler and asl compile task.
57 * This task can compile various source languages and produce executables,
58 * shared libraries (aka DLL's) and static libraries. Compiler adaptors are
59 * currently available for several C/C++ compilers, FORTRAN, MIDL and Windows
60 * Resource files. Assembler adaptors are currently available for MASM and GAS.
61 * And aslcompiler support to ASL and IASL command.
66 * Copyright (c) 2001-2005, The Ant-Contrib project.
70 * Licensed under the Apache Software License 2.0,
71 * http://www.apache.org/licenses/LICENSE-2.0.
75 * For use with Apache Ant 1.5 or later. This software is not a product of the
76 * of the Apache Software Foundation and no endorsement is implied.
80 * THIS SOFTWARE IS PROVIDED 'AS-IS', See
81 * http://www.apache.org/licenses/LICENSE-2.0 for additional disclaimers.
86 * <li>Place cpptasks.jar into the lib directory of Ant 1.5 or later.</li>
87 * <li>Add <taskdef resource="cpptasks.tasks"/> and <typedef
88 * resource="cpptasks.types"/> to build.xml.</li>
89 * <li>Add <cc/>, <compiler/> <linker/> <assembler/>
90 * and <aslcompiler/> elements to project.</li>
91 * <li>Set path and environment variables to be able to run compiler from
93 * <li>Build project.</li>
96 * @author Adam Murdoch
99 public class CCTask
extends Task
{
100 private class SystemLibraryCollector
implements FileVisitor
{
101 private Hashtable libraries
;
103 private Linker linker
;
105 public SystemLibraryCollector (Linker linker
, Hashtable libraries
) {
106 this.linker
= linker
;
107 this.libraries
= libraries
;
110 public void visit(File basedir
, String filename
) {
111 if (linker
.bid(filename
) > 0) {
112 File libfile
= new File(basedir
, filename
);
113 String key
= linker
.getLibraryKey(libfile
);
114 libraries
.put(key
, libfile
);
119 private static final ProcessorConfiguration
[] EMPTY_CONFIG_ARRAY
= new ProcessorConfiguration
[0];
122 * Builds a Hashtable to targets needing to be rebuilt keyed by compiler
125 public static Hashtable
getTargetsToBuildByConfiguration(Hashtable targets
) {
126 Hashtable targetsByConfig
= new Hashtable();
127 Enumeration targetEnum
= targets
.elements();
128 while (targetEnum
.hasMoreElements()) {
129 TargetInfo target
= (TargetInfo
) targetEnum
.nextElement();
130 if (target
.getRebuild()) {
131 Vector targetsForSameConfig
= (Vector
) targetsByConfig
132 .get(target
.getConfiguration());
133 if (targetsForSameConfig
!= null) {
134 targetsForSameConfig
.addElement(target
);
136 targetsForSameConfig
= new Vector();
137 targetsForSameConfig
.addElement(target
);
138 targetsByConfig
.put(target
.getConfiguration(),
139 targetsForSameConfig
);
143 return targetsByConfig
;
146 /** The userdefine definitions. */
147 private Vector _userdefines
= new Vector();
149 /** The compiler definitions. */
150 private Vector _compilers
= new Vector();
152 /** The output file type. */
153 // private LinkType _linkType = LinkType.EXECUTABLE;
154 /** The library sets. */
155 private Vector _libsets
= new Vector();
157 /** The aslcompiler definitions. */
158 private Vector _aslcompiler
= new Vector();
160 /** The assembler definitions. */
161 private Vector _assemblers
= new Vector();
163 /** The linker definitions. */
164 private Vector _linkers
= new Vector();
166 /** The object directory. */
167 private File _objDir
;
169 /** The output file. */
170 private File _outfile
;
172 private boolean userdefine
= false;
175 private String vendor
;
177 /** the flag for assembler */
178 private boolean assembler
= true;
180 /** the flag for aslcompiler */
181 private boolean aslcompiler
= true;
183 /** The linker definitions. */
184 private final Vector targetPlatforms
= new Vector();
186 /** The distributer definitions. */
187 private Vector distributers
= new Vector();
190 * If true, stop build on compile failure.
192 protected boolean failOnError
= true;
195 * Content that appears in <cc>and also in <compiler>are maintained by a
196 * captive CompilerDef instance
198 private final CompilerDef compilerDef
= new CompilerDef();
201 * Content that appears in <cc>and also in <aslcompiler>are maintained by a
202 * captive AslcompilerDef instance
204 private final AslcompilerDef aslcompilerDef
= new AslcompilerDef();
206 /** The OS390 dataset to build to object to */
207 private String dataset
;
211 * Depth of dependency checking
213 * Values < 0 indicate full dependency checking Values >= 0 indicate partial
214 * dependency checking and for superficial compilation checks. Will throw
215 * BuildException before attempting link
217 private int dependencyDepth
= -1;
220 * Content that appears in <cc>and also in <assembler>are maintained by a
221 * captive AssemblerDef instance
223 private final AssemblerDef assemblerDef
= new AssemblerDef();
226 * Content that appears in <cc>and also in <linker>are maintained by a
227 * captive CompilerDef instance
229 private final LinkerDef linkerDef
= new LinkerDef();
232 * contains the subsystem, output type and
235 private final LinkType linkType
= new LinkType();
238 * The property name which will be set with the physical filename of the
239 * file that is generated by the linker
241 private String outputFileProperty
;
244 * if relentless = true, compilations should attempt to compile as many
245 * files as possible before throwing a BuildException
247 private boolean relentless
;
253 public void addConfiguredCommand(UserDefineDef userdefineDef
) {
254 if (userdefineDef
== null) {
255 throw new NullPointerException("UserDefineDef");
257 userdefineDef
.setProject(getProject());
258 _userdefines
.addElement(userdefineDef
);
261 * Adds a asl compiler definition or reference.
265 * @throws NullPointerException
266 * if aslcompiler is null
268 public void addConfiguredAslcompiler(AslcompilerDef aslcompier
) {
269 if (aslcompier
== null) {
270 throw new NullPointerException("aslcompier");
272 aslcompier
.setProject(getProject());
273 _aslcompiler
.addElement(aslcompier
);
277 * Adds a asl command-line arg. Argument will be inherited by all nested
278 * aslcompiler elements that do not have inherit="false".
281 public void addConfiguredAslcompilerArg(AslcompilerArgument arg
) {
282 aslcompilerDef
.addConfiguredAslcompilerArg(arg
);
286 * Adds a assembler definition or reference.
290 * @throws NullPointerException
291 * if assembler is null
293 public void addConfiguredAssembler(AssemblerDef assembler
) {
294 if (assembler
== null) {
295 throw new NullPointerException("assembler");
297 assembler
.setProject(getProject());
298 _assemblers
.addElement(assembler
);
302 * Adds a assembler command-line arg. Argument will be inherited by all
303 * nested assembler elements that do not have inherit="false".
306 public void addConfiguredAssemblerArg(AssemblerArgument arg
) {
307 assemblerDef
.addConfiguredAssemblerArg(arg
);
311 * Adds a compiler definition or reference.
315 * @throws NullPointerException
316 * if compiler is null
318 public void addConfiguredCompiler(CompilerDef compiler
) {
319 if (compiler
== null) {
320 throw new NullPointerException("compiler");
322 compiler
.setProject(getProject());
323 _compilers
.addElement(compiler
);
327 * Adds a compiler command-line arg. Argument will be inherited by all
328 * nested compiler elements that do not have inherit="false".
331 public void addConfiguredCompilerArg(CompilerArgument arg
) {
332 compilerDef
.addConfiguredCompilerArg(arg
);
336 * Adds a defineset. Will be inherited by all compiler elements that do not
337 * have inherit="false".
342 public void addConfiguredDefineset(DefineSet defs
) {
343 compilerDef
.addConfiguredDefineset(defs
);
347 * Adds a linker definition. The first linker that is not disqualified by
348 * its "if" and "unless" attributes will perform the link. If no child
349 * linker element is active, the linker implied by the cc elements name or
350 * classname attribute will be used.
354 * @throws NullPointerException
357 public void addConfiguredLinker(LinkerDef linker
) {
358 if (linker
== null) {
359 throw new NullPointerException("linker");
361 linker
.setProject(getProject());
362 _linkers
.addElement(linker
);
366 * Adds a linker command-line arg. Argument will be inherited by all nested
367 * linker elements that do not have inherit="false".
369 public void addConfiguredLinkerArg(LinkerArgument arg
) {
370 linkerDef
.addConfiguredLinkerArg(arg
);
374 * Add an environment variable to the launched process.
376 public void addEnv(Environment
.Variable var
) {
377 compilerDef
.addEnv(var
);
378 linkerDef
.addEnv(var
);
379 assemblerDef
.addEnv(var
);
380 aslcompilerDef
.addEnv(var
);
384 * Adds a source file set.
386 * Files in these filesets will be auctioned to the available compiler
387 * configurations, with the default compiler implied by the cc element
388 * bidding last. If no compiler is interested in the file, it will be passed
391 * To have a file be processed by a particular compiler configuration, add a
392 * fileset to the corresponding compiler element.
394 public void addFileset(ConditionalFileSet srcSet
) {
395 compilerDef
.addFileset(srcSet
);
399 * Adds a library set.
401 * Library sets will be inherited by all linker elements that do not have
406 * @throws NullPointerException
409 public void addLibset(LibrarySet libset
) {
410 if (libset
== null) {
411 throw new NullPointerException("libset");
413 linkerDef
.addLibset(libset
);
417 * Adds a system library set. Timestamps and locations of system library
418 * sets are not used in dependency analysis.
420 * Essential libraries (such as C Runtime libraries) should not be specified
421 * since the task will attempt to identify the correct libraries based on
422 * the multithread, debug and runtime attributes.
424 * System library sets will be inherited by all linker elements that do not
425 * have inherit="false".
429 * @throws NullPointerException
432 public void addSyslibset(SystemLibrarySet libset
) {
433 if (libset
== null) {
434 throw new NullPointerException("libset");
436 linkerDef
.addSyslibset(libset
);
440 * Checks all targets that are not forced to be rebuilt or are missing
441 * object files to be checked for modified include files
443 * @returns total number of targets to be rebuilt
446 protected int checkForChangedIncludeFiles(Hashtable targets
) {
447 int potentialTargets
= 0;
448 int definiteTargets
= 0;
449 Enumeration targetEnum
= targets
.elements();
450 while (targetEnum
.hasMoreElements()) {
451 TargetInfo target
= (TargetInfo
) targetEnum
.nextElement();
452 if (!target
.getRebuild()) {
459 // If there were remaining targets that
460 // might be out of date
462 if (potentialTargets
> 0) {
463 log("Starting dependency analysis for "
464 + Integer
.toString(potentialTargets
) + " files.");
465 DependencyTable dependencyTable
= new DependencyTable(_objDir
);
467 dependencyTable
.load();
468 } catch (Exception ex
) {
469 log("Problem reading dependencies.xml: " + ex
.toString());
471 targetEnum
= targets
.elements();
472 while (targetEnum
.hasMoreElements()) {
473 TargetInfo target
= (TargetInfo
) targetEnum
.nextElement();
474 if (!target
.getRebuild()) {
475 if (dependencyTable
.needsRebuild(this, target
,
477 target
.mustRebuild();
481 dependencyTable
.commit(this);
484 // count files being rebuilt now
486 int currentTargets
= 0;
487 targetEnum
= targets
.elements();
488 while (targetEnum
.hasMoreElements()) {
489 TargetInfo target
= (TargetInfo
) targetEnum
.nextElement();
490 if (target
.getRebuild()) {
494 if (potentialTargets
> 0) {
495 log(Integer
.toString(potentialTargets
- currentTargets
497 + " files are up to date.");
498 log(Integer
.toString(currentTargets
- definiteTargets
)
499 + " files to be recompiled from dependency analysis.");
501 log(Integer
.toString(currentTargets
) + " total files to be compiled.");
502 return currentTargets
;
505 protected LinkerConfiguration
collectExplicitObjectFiles(
506 Vector objectFiles
, Vector sysObjectFiles
) {
508 // find the first eligible linker
511 ProcessorConfiguration linkerConfig
= null;
512 LinkerDef selectedLinkerDef
= null;
513 Linker selectedLinker
= null;
514 Hashtable sysLibraries
= new Hashtable();
515 TargetDef targetPlatform
= getTargetPlatform();
516 FileVisitor objCollector
= null;
517 FileVisitor sysLibraryCollector
= null;
518 for (int i
= 0; i
< _linkers
.size(); i
++) {
519 LinkerDef currentLinkerDef
= (LinkerDef
) _linkers
.elementAt(i
);
520 if (currentLinkerDef
.isActive()) {
521 selectedLinkerDef
= currentLinkerDef
;
522 selectedLinker
= currentLinkerDef
.getProcessor().getLinker(
525 // skip the linker if it doesn't know how to
526 // produce the specified link type
527 if (selectedLinker
!= null) {
528 linkerConfig
= currentLinkerDef
.createConfiguration(this,
529 linkType
, linkerDef
, targetPlatform
);
530 if (linkerConfig
!= null) {
532 // create collectors for object files
533 // and system libraries
534 objCollector
= new ObjectFileCollector(selectedLinker
,
536 sysLibraryCollector
= new SystemLibraryCollector(
537 selectedLinker
, sysLibraries
);
539 // if the <linker> has embedded <fileset>'s
540 // (such as linker specific libraries)
541 // add them as object files.
543 if (currentLinkerDef
.hasFileSets()) {
544 currentLinkerDef
.visitFiles(objCollector
);
547 // user libraries are just a specialized form
548 // of an object fileset
549 selectedLinkerDef
.visitUserLibraries(selectedLinker
,
556 if (linkerConfig
== null) {
557 linkerConfig
= linkerDef
.createConfiguration(this, linkType
, null,
559 selectedLinker
= (Linker
) linkerDef
.getProcessor().getLinker(
561 objCollector
= new ObjectFileCollector(selectedLinker
, objectFiles
);
562 sysLibraryCollector
= new SystemLibraryCollector(selectedLinker
,
566 // unless there was a <linker> element that
567 // explicitly did not inherit files from
568 // containing <cc> element
569 if (selectedLinkerDef
== null || selectedLinkerDef
.getInherit()) {
570 linkerDef
.visitUserLibraries(selectedLinker
, objCollector
);
571 linkerDef
.visitSystemLibraries(selectedLinker
, sysLibraryCollector
);
574 // if there was a <syslibset> in a nested <linker>
575 // evaluate it last so it takes priority over
576 // identically named libs from <cc> element
578 if (selectedLinkerDef
!= null) {
580 // add any system libraries to the hashtable
581 // done in reverse order so the earliest
582 // on the classpath takes priority
583 selectedLinkerDef
.visitSystemLibraries(selectedLinker
,
584 sysLibraryCollector
);
587 // copy over any system libraries to the
588 // object files vector
590 Enumeration sysLibEnum
= sysLibraries
.elements();
591 while (sysLibEnum
.hasMoreElements()) {
592 sysObjectFiles
.addElement(sysLibEnum
.nextElement());
594 return (LinkerConfiguration
) linkerConfig
;
598 * Adds an include path.
600 * Include paths will be inherited by nested compiler elements that do not
601 * have inherit="false".
603 public IncludePath
createIncludePath() {
604 return compilerDef
.createIncludePath();
608 * Specifies precompilation prototype file and exclusions. Inherited by all
609 * compilers that do not have inherit="false".
612 public PrecompileDef
createPrecompile() throws BuildException
{
613 return compilerDef
.createPrecompile();
617 * Adds a system include path. Locations and timestamps of files located
618 * using the system include paths are not used in dependency analysis.
621 * Standard include locations should not be specified. The compiler adapters
622 * should recognized the settings from the appropriate environment variables
623 * or configuration files.
625 * System include paths will be inherited by nested compiler elements that
626 * do not have inherit="false".
628 public SystemIncludePath
createSysIncludePath() {
629 return compilerDef
.createSysIncludePath();
633 * Executes the task. Compiles the given files.
635 * @throws BuildException
636 * if someting goes wrong with the build
638 public void execute() throws BuildException
{
640 // if link type allowed objdir to be defaulted
641 // provide it from outfile
642 if (_objDir
== null) {
643 if (_outfile
!= null) {
644 _objDir
= new File(_outfile
.getParent());
646 _objDir
= new File(".");
651 // if the object directory does not exist
653 if (!_objDir
.exists()) {
654 throw new BuildException("Object directory does not exist");
658 // if userdefine is true, then run all user defined command
661 Iterator iter
= _userdefines
.iterator();
662 while( iter
.hasNext()) {
663 UserDefineDef userdefineDef
= (UserDefineDef
)iter
.next();
664 UserDefineCompiler userdefineCompiler
= new UserDefineCompiler(this, userdefineDef
);
665 userdefineCompiler
.command(this, userdefineDef
);
670 TargetHistoryTable objHistory
= new TargetHistoryTable(this, _objDir
);
672 // determine the eventual linker configuration
673 // (may be null) and collect any explicit
674 // object files or libraries
675 Vector objectFiles
= new Vector();
676 Vector sysObjectFiles
= new Vector();
677 LinkerConfiguration linkerConfig
= collectExplicitObjectFiles(
678 objectFiles
, sysObjectFiles
);
680 // Assembler hashtable of all files
681 // that we know how to compile (keyed by output file name)
683 Hashtable targets
= getTargets(linkerConfig
, objectFiles
);
684 Hashtable acpiTarget
= new Hashtable();
686 acpiTarget
= getAcpiTargets(linkerConfig
, new Vector());
688 Hashtable assemblerTarget
= new Hashtable();
690 assemblerTarget
= getAssemblerTargets(linkerConfig
, objectFiles
);
692 TargetInfo linkTarget
= null;
694 // if output file is not specified,
695 // then skip link step
697 if (_outfile
!= null) {
698 linkTarget
= getLinkTarget(linkerConfig
, objectFiles
,
699 sysObjectFiles
, targets
, assemblerTarget
);
702 // If specify the aslcompiler, then call asl compiler
705 BuildException acpiException
= null;
706 Hashtable targetsByConfig
= getTargetsToBuildByConfiguration(acpiTarget
);
707 Enumeration acpiTargetEnum
= targetsByConfig
.elements();
708 Vector
[] targetVectors
= new Vector
[targetsByConfig
.size()];
710 while (acpiTargetEnum
.hasMoreElements()) {
711 Vector targetsForConfig
= (Vector
) acpiTargetEnum
.nextElement();
712 targetVectors
[index
++] = targetsForConfig
;
714 for (int i
= 0; i
< targetVectors
.length
; i
++) {
716 // get the targets for this configuration
718 Vector targetsForConfig
= targetVectors
[i
];
720 // get the configuration from the first entry
722 AslcompilerConfiguration config
= (AslcompilerConfiguration
) ((TargetInfo
) targetsForConfig
723 .elementAt(0)).getConfiguration();
725 // prepare the list of source files
727 String
[] sourceFiles
= new String
[targetsForConfig
.size()];
728 Enumeration targetsEnum
= targetsForConfig
.elements();
730 while (targetsEnum
.hasMoreElements()) {
731 TargetInfo targetInfo
= ((TargetInfo
) targetsEnum
733 sourceFiles
[index
++] = targetInfo
.getSources()[0]
737 config
.aslcompiler(this, _objDir
, sourceFiles
);
738 log(sourceFiles
.length
739 + " total ACPI source files to be compiled.");
740 } catch (BuildException ex
) {
741 if (acpiException
== null) {
750 // If specify the assembler, then call assembler
753 BuildException assemblerException
= null;
754 Hashtable targetsByConfig
= getTargetsToBuildByConfiguration(assemblerTarget
);
755 Enumeration assembleTargetEnum
= targetsByConfig
.elements();
756 Vector
[] targetVectors
= new Vector
[targetsByConfig
.size()];
758 while (assembleTargetEnum
.hasMoreElements()) {
759 Vector targetsForConfig
= (Vector
) assembleTargetEnum
761 targetVectors
[index
++] = targetsForConfig
;
763 for (int i
= 0; i
< targetVectors
.length
; i
++) {
765 // get the targets for this configuration
767 Vector targetsForConfig
= targetVectors
[i
];
769 // get the configuration from the first entry
771 AssemblerConfiguration config
= (AssemblerConfiguration
) ((TargetInfo
) targetsForConfig
772 .elementAt(0)).getConfiguration();
774 // prepare the list of source files
776 String
[] sourceFiles
= new String
[targetsForConfig
.size()];
777 Enumeration targetsEnum
= targetsForConfig
.elements();
779 while (targetsEnum
.hasMoreElements()) {
780 TargetInfo targetInfo
= ((TargetInfo
) targetsEnum
782 sourceFiles
[index
++] = targetInfo
.getSources()[0]
786 config
.assembler(this, _objDir
, sourceFiles
);
787 log(sourceFiles
.length
+ " total files to be assembled.");
788 } catch (BuildException ex
) {
789 if (assemblerException
== null) {
790 assemblerException
= ex
;
797 // if we threw a assembler exception and
798 // didn't throw it at the time because
799 // we were relentless then
800 // save the history and
801 // throw the exception
803 if (assemblerException
!= null) {
805 throw assemblerException
;
807 log(assemblerException
.getMessage(), Project
.MSG_ERR
);
814 // mark targets that don't have a history record or
815 // whose source last modification time is not
816 // the same as the history to be rebuilt
818 objHistory
.markForRebuild(targets
);
819 CCTaskProgressMonitor monitor
= new CCTaskProgressMonitor(objHistory
);
821 // check for changed include files
823 int rebuildCount
= checkForChangedIncludeFiles(targets
);
824 if (rebuildCount
> 0) {
825 BuildException compileException
= null;
827 // compile all targets with getRebuild() == true
829 Hashtable targetsByConfig
= getTargetsToBuildByConfiguration(targets
);
831 // build array containing Vectors with precompiled generation
834 Vector
[] targetVectors
= new Vector
[targetsByConfig
.size()];
836 Enumeration targetVectorEnum
= targetsByConfig
.elements();
837 while (targetVectorEnum
.hasMoreElements()) {
838 Vector targetsForConfig
= (Vector
) targetVectorEnum
841 // get the configuration from the first entry
843 CompilerConfiguration config
= (CompilerConfiguration
) ((TargetInfo
) targetsForConfig
844 .elementAt(0)).getConfiguration();
845 if (config
.isPrecompileGeneration()) {
846 targetVectors
[index
++] = targetsForConfig
;
849 targetVectorEnum
= targetsByConfig
.elements();
850 while (targetVectorEnum
.hasMoreElements()) {
851 Vector targetsForConfig
= (Vector
) targetVectorEnum
853 for (int i
= 0; i
< targetVectors
.length
; i
++) {
854 if (targetVectors
[i
] == targetsForConfig
) {
857 if (targetVectors
[i
] == null) {
858 targetVectors
[i
] = targetsForConfig
;
863 for (int i
= 0; i
< targetVectors
.length
; i
++) {
865 // get the targets for this configuration
867 Vector targetsForConfig
= targetVectors
[i
];
869 // get the configuration from the first entry
871 CompilerConfiguration config
= (CompilerConfiguration
) ((TargetInfo
) targetsForConfig
872 .elementAt(0)).getConfiguration();
874 // prepare the list of source files
876 String
[] sourceFiles
= new String
[targetsForConfig
.size()];
877 Enumeration targetsEnum
= targetsForConfig
.elements();
879 while (targetsEnum
.hasMoreElements()) {
880 TargetInfo targetInfo
= ((TargetInfo
) targetsEnum
882 sourceFiles
[index
++] = targetInfo
.getSources()[0]
886 config
.compile(this, _objDir
, sourceFiles
, relentless
,
888 } catch (BuildException ex
) {
889 if (compileException
== null) {
890 compileException
= ex
;
897 // save the details of the object file compilation
898 // settings to disk for dependency analysis
902 } catch (IOException ex
) {
903 this.log("Error writing history.xml: " + ex
.toString());
906 // if we threw a compile exception and
907 // didn't throw it at the time because
908 // we were relentless then
909 // save the history and
910 // throw the exception
912 if (compileException
!= null) {
914 throw compileException
;
916 log(compileException
.getMessage(), Project
.MSG_ERR
);
922 // if the dependency tree was not fully
923 // evaluated, then throw an exception
924 // since we really didn't do what we
928 if (dependencyDepth
>= 0) {
929 throw new BuildException(
930 "All files at depth "
931 + Integer
.toString(dependencyDepth
)
932 + " from changes successfully compiled.\n"
933 + "Remove or change dependencyDepth to -1 to perform full compilation.");
936 // if no link target then
937 // commit the history for the object files
938 // and leave the task
939 if (linkTarget
!= null) {
941 // get the history for the link target (may be the same
942 // as the object history)
943 TargetHistoryTable linkHistory
= getLinkHistory(objHistory
);
945 // see if it needs to be rebuilt
947 linkHistory
.markForRebuild(linkTarget
);
949 // if it needs to be rebuilt, rebuild it
951 File output
= linkTarget
.getOutput();
952 if (linkTarget
.getRebuild()) {
953 log("Starting link");
954 LinkerConfiguration linkConfig
= (LinkerConfiguration
) linkTarget
957 linkConfig
.link(this, linkTarget
);
960 linkConfig
.link(this, linkTarget
);
961 } catch (BuildException ex
) {
962 log(ex
.getMessage(), Project
.MSG_ERR
);
966 if (outputFileProperty
!= null)
967 getProject().setProperty(outputFileProperty
,
968 output
.getAbsolutePath());
969 linkHistory
.update(linkTarget
);
971 linkHistory
.commit();
972 } catch (IOException ex
) {
973 log("Error writing link history.xml: " + ex
.toString());
976 if (outputFileProperty
!= null)
977 getProject().setProperty(outputFileProperty
,
978 output
.getAbsolutePath());
986 * @return Returns a String
988 public String
getDataset() {
992 protected TargetHistoryTable
getLinkHistory(TargetHistoryTable objHistory
) {
993 File outputFileDir
= new File(_outfile
.getParent());
995 // if the output file is being produced in the link
996 // directory, then we can use the same history file
998 if (_objDir
.equals(outputFileDir
)) {
1001 return new TargetHistoryTable(this, outputFileDir
);
1004 protected TargetInfo
getLinkTarget(LinkerConfiguration linkerConfig
,
1005 Vector objectFiles
, Vector sysObjectFiles
,
1006 Hashtable compileTargets
, Hashtable assemblerTargets
) {
1008 // walk the compile phase targets and
1009 // add those sources that have already been
1010 // assigned to the linker or
1011 // our output files the linker knows how to consume
1012 // files the linker knows how to consume
1014 Enumeration compileTargetsEnum
= compileTargets
.elements();
1015 while (compileTargetsEnum
.hasMoreElements()) {
1016 TargetInfo compileTarget
= (TargetInfo
) compileTargetsEnum
1019 // output of compile tasks
1021 int bid
= linkerConfig
.bid(compileTarget
.getOutput().toString());
1023 objectFiles
.addElement(compileTarget
.getOutput());
1027 // walk the assembler phase targets and
1028 // add those sources that have already been
1029 // assigned to the linker or
1030 // our output files the linker knows how to consume
1031 // files the linker knows how to consume
1033 Enumeration assembleTargetsEnum
= assemblerTargets
.elements();
1034 while (assembleTargetsEnum
.hasMoreElements()) {
1035 TargetInfo assemblerTarget
= (TargetInfo
) assembleTargetsEnum
1038 // output of assemble tasks
1040 int bid
= linkerConfig
.bid(assemblerTarget
.getOutput().toString());
1042 objectFiles
.addElement(assemblerTarget
.getOutput());
1045 File
[] objectFileArray
= new File
[objectFiles
.size()];
1046 objectFiles
.copyInto(objectFileArray
);
1047 File
[] sysObjectFileArray
= new File
[sysObjectFiles
.size()];
1048 sysObjectFiles
.copyInto(sysObjectFileArray
);
1049 String baseName
= _outfile
.getName();
1050 String fullName
= linkerConfig
.getOutputFileName(baseName
);
1051 File outputFile
= new File(_outfile
.getParent(), fullName
);
1052 return new TargetInfo(linkerConfig
, objectFileArray
,
1053 sysObjectFileArray
, outputFile
, linkerConfig
1057 public File
getObjdir() {
1061 public File
getOutfile() {
1065 public TargetDef
getTargetPlatform() {
1070 * This method collects a Hashtable, keyed by output file name, of
1071 * TargetInfo's for every source file that is specified in the filesets of
1072 * the <aslcompiler> elements. The TargetInfo's contain the appropriate ACPI
1073 * configurations for their possible acpi
1076 private Hashtable
getAcpiTargets(LinkerConfiguration linkerConfig
,
1077 Vector objectFiles
) {
1078 Hashtable targets
= new Hashtable(1000);
1079 TargetDef targetPlatform
= getTargetPlatform();
1080 Vector biddingProcessors
= new Vector(_aslcompiler
.size());
1081 for (int i
= 0; i
< _aslcompiler
.size(); i
++) {
1082 AslcompilerDef currentAslDef
= (AslcompilerDef
) _aslcompiler
1084 if (currentAslDef
.isActive()) {
1085 ProcessorConfiguration config
= currentAslDef
1086 .createConfiguration(this, linkType
,
1087 aslcompilerDef
, targetPlatform
);
1089 // if the aslcompiler has a fileset
1090 // then allow it to add its files to
1091 // the set of potential targets
1093 ProcessorConfiguration
[] localConfigs
= new ProcessorConfiguration
[] { config
};
1094 if (currentAslDef
.hasFileSets()) {
1095 TargetMatcher matcher
= new TargetMatcher(this, _objDir
,
1096 localConfigs
, linkerConfig
, objectFiles
,
1098 currentAslDef
.visitFiles(matcher
);
1100 biddingProcessors
.addElement(config
);
1104 // add fallback compiler at the end
1106 ProcessorConfiguration config
= aslcompilerDef
.createConfiguration(
1107 this, linkType
, null, targetPlatform
);
1108 biddingProcessors
.addElement(config
);
1109 ProcessorConfiguration
[] bidders
= new ProcessorConfiguration
[biddingProcessors
1111 biddingProcessors
.copyInto(bidders
);
1112 TargetMatcher matcher
= new TargetMatcher(this, _objDir
, bidders
,
1113 linkerConfig
, objectFiles
, targets
);
1114 aslcompilerDef
.visitFiles(matcher
);
1119 * This method collects a Hashtable, keyed by output file name, of
1120 * TargetInfo's for every source file that is specified in the filesets of
1121 * the <assembler> elements. The TargetInfo's contain the appropriate
1122 * assembler configurations for their possible assembly
1125 private Hashtable
getAssemblerTargets(LinkerConfiguration linkerConfig
,
1126 Vector objectFiles
) {
1127 Hashtable targets
= new Hashtable(1000);
1128 TargetDef targetPlatform
= getTargetPlatform();
1129 Vector biddingProcessors
= new Vector(_assemblers
.size());
1130 for (int i
= 0; i
< _assemblers
.size(); i
++) {
1131 AssemblerDef currentAssemblerDef
= (AssemblerDef
) _assemblers
1133 if (currentAssemblerDef
.isActive()) {
1134 ProcessorConfiguration config
= currentAssemblerDef
1135 .createConfiguration(this, linkType
,
1136 assemblerDef
, targetPlatform
);
1138 // if the assembler has a fileset
1139 // then allow it to add its files to
1140 // the set of potential targets
1142 ProcessorConfiguration
[] localConfigs
= new ProcessorConfiguration
[] { config
};
1143 if (currentAssemblerDef
.hasFileSets()) {
1144 TargetMatcher matcher
= new TargetMatcher(this, _objDir
,
1145 localConfigs
, linkerConfig
, objectFiles
,
1147 currentAssemblerDef
.visitFiles(matcher
);
1149 biddingProcessors
.addElement(config
);
1153 // add fallback assembler at the end
1155 ProcessorConfiguration config
= assemblerDef
.createConfiguration(this,
1156 linkType
, null, targetPlatform
);
1157 biddingProcessors
.addElement(config
);
1158 ProcessorConfiguration
[] bidders
= new ProcessorConfiguration
[biddingProcessors
1160 biddingProcessors
.copyInto(bidders
);
1161 TargetMatcher matcher
= new TargetMatcher(this, _objDir
, bidders
,
1162 linkerConfig
, objectFiles
, targets
);
1163 assemblerDef
.visitFiles(matcher
);
1168 * This method collects a Hashtable, keyed by output file name, of
1169 * TargetInfo's for every source file that is specified in the filesets of
1170 * the <cc>and nested <compiler>elements. The TargetInfo's contain the
1171 * appropriate compiler configurations for their possible compilation
1174 private Hashtable
getTargets(LinkerConfiguration linkerConfig
,
1175 Vector objectFiles
) {
1176 Hashtable targets
= new Hashtable(1000);
1177 TargetDef targetPlatform
= getTargetPlatform();
1179 // find active (specialized) compilers
1181 Vector biddingProcessors
= new Vector(_compilers
.size());
1182 for (int i
= 0; i
< _compilers
.size(); i
++) {
1183 CompilerDef currentCompilerDef
= (CompilerDef
) _compilers
1185 if (currentCompilerDef
.isActive()) {
1186 ProcessorConfiguration config
= currentCompilerDef
1187 .createConfiguration(this, linkType
,
1188 compilerDef
, targetPlatform
);
1190 // see if this processor had a precompile child element
1192 PrecompileDef precompileDef
= currentCompilerDef
1193 .getActivePrecompile(compilerDef
);
1194 ProcessorConfiguration
[] localConfigs
= new ProcessorConfiguration
[] { config
};
1198 if (precompileDef
!= null) {
1199 File prototype
= precompileDef
.getPrototype();
1201 // will throw exceptions if prototype doesn't exist, etc
1203 if (!prototype
.exists()) {
1204 throw new BuildException("prototype ("
1205 + prototype
.toString()
1206 + ") does not exist.");
1208 if (prototype
.isDirectory()) {
1209 throw new BuildException("prototype ("
1210 + prototype
.toString()
1211 + ") is a directory.");
1213 String
[] exceptFiles
= precompileDef
.getExceptFiles();
1215 // create a precompile building and precompile using
1216 // variants of the configuration
1217 // or return null if compiler doesn't support
1219 CompilerConfiguration
[] configs
= ((CompilerConfiguration
) config
)
1220 .createPrecompileConfigurations(prototype
,
1222 if (configs
!= null && configs
.length
== 2) {
1224 // visit the precompiled file to add it into the
1225 // targets list (just like any other file if
1226 // compiler doesn't support precompilation)
1227 TargetMatcher matcher
= new TargetMatcher(
1230 new ProcessorConfiguration
[] { configs
[0] },
1231 linkerConfig
, objectFiles
, targets
);
1232 matcher
.visit(new File(prototype
.getParent()),
1233 prototype
.getName());
1235 // only the configuration that uses the
1236 // precompiled header gets added to the bidding list
1237 biddingProcessors
.addElement(configs
[1]);
1238 localConfigs
= new ProcessorConfiguration
[2];
1239 localConfigs
[0] = configs
[1];
1240 localConfigs
[1] = config
;
1244 // if the compiler has a fileset
1245 // then allow it to add its files
1246 // to the set of potential targets
1247 if (currentCompilerDef
.hasFileSets()) {
1248 TargetMatcher matcher
= new TargetMatcher(this, _objDir
,
1249 localConfigs
, linkerConfig
, objectFiles
,
1251 currentCompilerDef
.visitFiles(matcher
);
1253 biddingProcessors
.addElement(config
);
1257 // add fallback compiler at the end
1259 ProcessorConfiguration config
= compilerDef
.createConfiguration(this,
1260 linkType
, null, targetPlatform
);
1261 biddingProcessors
.addElement(config
);
1262 ProcessorConfiguration
[] bidders
= new ProcessorConfiguration
[biddingProcessors
1264 biddingProcessors
.copyInto(bidders
);
1266 // bid out the <fileset>'s in the cctask
1268 TargetMatcher matcher
= new TargetMatcher(this, _objDir
, bidders
,
1269 linkerConfig
, objectFiles
, targets
);
1270 compilerDef
.visitFiles(matcher
);
1275 * Sets the default compiler adapter. Use the "name" attribute when the
1276 * compiler is a supported compiler.
1279 * fully qualified classname which implements CompilerAdapter
1281 public void setClassname(String classname
) {
1282 compilerDef
.setClassname(classname
);
1283 linkerDef
.setClassname(classname
);
1284 assemblerDef
.setClassname(classname
);
1285 aslcompilerDef
.setClassname(classname
);
1289 * Sets the dataset for OS/390 builds.
1292 * The dataset to set
1294 public void setDataset(String dataset
) {
1295 this.dataset
= dataset
;
1299 * Enables or disables generation of debug info.
1301 public void setDebug(boolean debug
) {
1302 compilerDef
.setDebug(debug
);
1303 linkerDef
.setDebug(debug
);
1304 assemblerDef
.setDebug(debug
);
1305 aslcompilerDef
.setDebug(debug
);
1311 * Controls the depth of the dependency evaluation. Used to do a quick check
1312 * of changes before a full build.
1314 * Any negative value which will perform full dependency checking. Positive
1315 * values will truncate dependency checking. A value of 0 will cause only
1316 * those files that changed to be recompiled, a value of 1 which cause files
1317 * that changed or that explicitly include a file that changed to be
1320 * Any non-negative value will cause a BuildException to be thrown before
1321 * attempting a link or completing the task.
1324 public void setDependencyDepth(int depth
) {
1325 dependencyDepth
= depth
;
1329 * Enables generation of exception handling code
1331 public void setExceptions(boolean exceptions
) {
1332 compilerDef
.setExceptions(exceptions
);
1336 * Enables run-time type information.
1338 public void setRtti(boolean rtti
) {
1339 compilerDef
.setRtti(rtti
);
1342 // public LinkType getLinkType() {
1346 * Enables or disables incremental linking.
1348 * @param incremental
1351 public void setIncremental(boolean incremental
) {
1352 linkerDef
.setIncremental(incremental
);
1356 * Set use of libtool.
1358 * If set to true, the "libtool " will be prepended to the command line for
1359 * compatible processors
1362 * If true, use libtool.
1364 public void setLibtool(boolean libtool
) {
1365 compilerDef
.setLibtool(libtool
);
1366 linkerDef
.setLibtool(libtool
);
1367 assemblerDef
.setLibtool(libtool
);
1368 aslcompilerDef
.setLibtool(libtool
);
1372 * Sets the output file type. Supported values "executable", "shared", and
1373 * "static". Deprecated, specify outtype instead.
1377 public void setLink(OutputTypeEnum outputType
) {
1378 linkType
.setOutputType(outputType
);
1382 * Enables or disables generation of multithreaded code
1385 * If true, generated code may be multithreaded.
1387 public void setMultithreaded(boolean multi
) {
1388 compilerDef
.setMultithreaded(multi
);
1392 // keep near duplicate comment at CompilerDef.setName in sync
1395 * Sets type of the default compiler and linker.
1397 * <table width="100%" border="1"> <thead>Supported compilers </thead>
1399 * <td>gcc (default)</td>
1400 * <td>GCC C++ compiler</td>
1404 * <td>GCC C++ compiler</td>
1408 * <td>GCC C++ compiler</td>
1412 * <td>GNU FORTRAN compiler</td>
1416 * <td>Microsoft Visual C++</td>
1420 * <td>Borland C++ Compiler</td>
1424 * <td>Microsoft Resource Compiler</td>
1428 * <td>Borland Resource Compiler</td>
1432 * <td>Compaq Visual Fortran Compiler</td>
1436 * <td>Microsoft MIDL Compiler</td>
1440 * <td>Intel C++ compiler for Windows (IA-32)</td>
1444 * <td>Intel C++ compiler for Windows (IA-64)</td>
1448 * <td>Intel C++ compiler for Linux (IA-32)</td>
1452 * <td>Intel C++ compiler for Linux (IA-64)</td>
1456 * <td>Sun ONE C++ compiler</td>
1460 * <td>HP aC++ C++ Compiler</td>
1464 * <td>OS390 C Compiler</td>
1468 * <td>Icc Compiler</td>
1472 * <td>Sun C89 C Compiler</td>
1476 * <td>VisualAge C Compiler</td>
1481 public void setName(CompilerEnum name
) {
1482 compilerDef
.setName(name
);
1483 Processor compiler
= compilerDef
.getProcessor();
1484 Linker linker
= compiler
.getLinker(linkType
);
1485 linkerDef
.setProcessor(linker
);
1489 * Do not propagate old environment when new environment variables are
1492 public void setNewenvironment(boolean newenv
) {
1493 compilerDef
.setNewenvironment(newenv
);
1494 linkerDef
.setNewenvironment(newenv
);
1495 assemblerDef
.setNewenvironment(newenv
);
1496 aslcompilerDef
.setNewenvironment(newenv
);
1500 * Sets the destination directory for object files.
1502 * Generally this should be a property expression that evaluates to distinct
1503 * debug and release object file directories.
1508 public void setObjdir(File dir
) {
1510 throw new NullPointerException("dir");
1516 * Sets the output file name. If not specified, the task will only compile
1517 * files and not attempt to link. If an extension is not specified, the task
1518 * may use a system appropriate extension and prefix, for example,
1519 * outfile="example" may result in "libexample.so" being created.
1524 public void setOutfile(File outfile
) {
1526 // if file name was empty, skip link step
1528 if (outfile
== null || outfile
.toString().length() > 0) {
1534 * Specifies the name of a property to set with the physical filename that
1535 * is produced by the linker
1537 public void setOutputFileProperty(String outputFileProperty
) {
1538 this.outputFileProperty
= outputFileProperty
;
1542 * Sets the output file type. Supported values "executable", "shared", and
1545 public void setOuttype(OutputTypeEnum outputType
) {
1546 linkType
.setOutputType(outputType
);
1552 public void setProject(Project project
) {
1553 super.setProject(project
);
1554 compilerDef
.setProject(project
);
1555 linkerDef
.setProject(project
);
1556 assemblerDef
.setProject(project
);
1557 aslcompilerDef
.setProject(project
);
1561 * If set to true, all files will be rebuilt.
1563 * @paran rebuildAll If true, all files will be rebuilt. If false, up to
1564 * date files will not be rebuilt.
1566 public void setRebuild(boolean rebuildAll
) {
1567 compilerDef
.setRebuild(rebuildAll
);
1568 linkerDef
.setRebuild(rebuildAll
);
1569 assemblerDef
.setRebuild(rebuildAll
);
1570 aslcompilerDef
.setRebuild(rebuildAll
);
1574 * If set to true, compilation errors will not stop the task until all files
1575 * have been attempted.
1578 * If true, don't stop on the first compilation error
1581 public void setRelentless(boolean relentless
) {
1582 this.relentless
= relentless
;
1586 * Sets the type of runtime library, possible values "dynamic", "static".
1588 public void setRuntime(RuntimeType rtlType
) {
1589 linkType
.setStaticRuntime((rtlType
.getIndex() == 1));
1593 * Sets the nature of the subsystem under which that the program will
1596 * <table width="100%" border="1"> <thead>Supported subsystems </thead>
1599 * <td>Graphical User Interface</td>
1603 * <td>Command Line Console</td>
1613 * @throws NullPointerException
1614 * if subsystem is null
1616 public void setSubsystem(SubsystemEnum subsystem
) {
1617 if (subsystem
== null) {
1618 throw new NullPointerException("subsystem");
1620 linkType
.setSubsystem(subsystem
);
1624 * Enumerated attribute with the values "none", "severe", "default",
1625 * "production", "diagnostic", and "failtask".
1627 public void setWarnings(CompilerDef
.WarningLevel level
) {
1628 compilerDef
.setWarnings(level
);
1632 * Indicates whether the build will continue even if there are compilation
1633 * errors; defaults to true.
1636 * if true halt the build on failure
1638 public void setFailonerror(boolean fail
) {
1643 * Gets the failonerror flag.
1645 * @return the failonerror flag
1647 public boolean getFailonerror() {
1652 * Adds descriptive version information to be included in the generated
1653 * file. The first active version info block will be used. (Non-functional
1656 public void addConfiguredVersioninfo(VersionInfo info
) {
1657 linkerDef
.addConfiguredVersioninfo(info
);
1661 * Adds a target definition or reference (Non-functional prototype).
1665 * @throws NullPointerException
1666 * if compiler is null
1668 public void addConfiguredTarget(TargetDef target
) {
1669 if (target
== null) {
1670 throw new NullPointerException("target");
1672 target
.setProject(getProject());
1673 targetPlatforms
.addElement(target
);
1677 * Adds a distributer definition or reference (Non-functional prototype).
1679 * @param distributer
1681 * @throws NullPointerException
1682 * if compiler is null
1684 public void addConfiguredDistributer(DistributerDef distributer
) {
1685 if (distributer
== null) {
1686 throw new NullPointerException("distributer");
1688 distributer
.setProject(getProject());
1689 distributers
.addElement(distributer
);
1693 * Sets optimization.
1694 * @param optimization
1696 public void setOptimize(OptimizationEnum optimization
) {
1697 compilerDef
.setOptimize(optimization
);
1700 public boolean isAssembler() {
1704 public void setAssembler(boolean assembler
) {
1705 this.assembler
= assembler
;
1708 public boolean isAslcompiler() {
1712 public void setAslcompiler(boolean aslcompiler
) {
1713 this.aslcompiler
= aslcompiler
;
1716 public boolean isUserdefine() {
1720 public void setUserdefine(boolean userdefine
) {
1721 this.userdefine
= userdefine
;
1724 public String
getArch() {
1728 public void setArch(String arch
) {
1732 public String
getOs() {
1736 public void setOs(String os
) {
1740 public String
getVendor() {
1744 public void setVendor(String vendor
) {
1745 this.vendor
= vendor
;