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;
21  
22  import java.io.File;
23  import java.io.FileFilter;
24  import java.io.IOException;
25  import java.util.ArrayList;
26  import java.util.Comparator;
27  import java.util.Enumeration;
28  import java.util.HashMap;
29  import java.util.Hashtable;
30  import java.util.Iterator;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.TreeMap;
34  import java.util.Vector;
35  
36  import org.apache.tools.ant.BuildException;
37  import org.apache.tools.ant.Project;
38  import org.apache.tools.ant.Task;
39  import org.apache.tools.ant.types.Environment;
40  import org.apache.commons.io.FilenameUtils;
41  
42  import com.github.maven_nar.cpptasks.compiler.CompilerConfiguration;
43  import com.github.maven_nar.cpptasks.compiler.LinkType;
44  import com.github.maven_nar.cpptasks.compiler.Linker;
45  import com.github.maven_nar.cpptasks.compiler.LinkerConfiguration;
46  import com.github.maven_nar.cpptasks.compiler.Processor;
47  import com.github.maven_nar.cpptasks.compiler.ProcessorConfiguration;
48  import com.github.maven_nar.cpptasks.compiler.AbstractCompiler;
49  import com.github.maven_nar.cpptasks.compiler.CommandLineCompilerConfiguration;
50  import com.github.maven_nar.cpptasks.ide.ProjectDef;
51  import com.github.maven_nar.cpptasks.types.CompilerArgument;
52  import com.github.maven_nar.cpptasks.types.ConditionalFileSet;
53  import com.github.maven_nar.cpptasks.types.DefineSet;
54  import com.github.maven_nar.cpptasks.types.IncludePath;
55  import com.github.maven_nar.cpptasks.types.LibrarySet;
56  import com.github.maven_nar.cpptasks.types.LinkerArgument;
57  import com.github.maven_nar.cpptasks.types.SystemIncludePath;
58  import com.github.maven_nar.cpptasks.types.SystemLibrarySet;
59  
60  /**
61   * Compile and link task.
62   * 
63   * <p>
64   * This task can compile various source languages and produce executables,
65   * shared libraries (aka DLL's) and static libraries. Compiler adaptors are
66   * currently available for several C/C++ compilers, FORTRAN, MIDL and Windows
67   * Resource files.
68   * </p>
69   * 
70   * @author Adam Murdoch
71   * @author Curt Arnold
72   */
73  public class CCTask extends Task {
74  
75    // BEGINFREEHEP
76    class Core extends Thread {
77      private final CCTask task;
78      private final CompilerConfiguration config;
79      private final File objDir;
80      private final List<String> sourceFiles;
81      private final boolean relentless;
82      private final CCTaskProgressMonitor monitor;
83      private Exception compileException;
84  
85      Core(final CCTask task, final int coreNo, final CompilerConfiguration config, final File objDir,
86          final List<String> set, final boolean relentless, final CCTaskProgressMonitor monitor) {
87        super("Core " + coreNo);
88        this.task = task;
89        this.config = config;
90        this.objDir = objDir;
91        this.sourceFiles = set;
92        this.relentless = relentless;
93        this.monitor = monitor;
94      }
95  
96      public Exception getException() {
97        return this.compileException;
98      }
99  
100     @Override
101     public void run() {
102       super.run();
103       try {
104         String[] sources = new String[this.sourceFiles.size()];
105         sources = this.sourceFiles.toArray(sources);
106 
107         this.config.compile(this.task, this.objDir, sources, this.relentless, this.monitor);
108       } catch (final Exception ex) {
109         if (this.compileException == null) {
110           this.compileException = ex;
111         }
112       }
113     }
114   }
115 
116   // BEGINFREEHEP
117   class Progress extends Thread {
118 
119     private boolean stop = false;
120     private final File objDir;
121     private final int rebuildCount;
122 
123     public Progress(final File objDir, final int rebuildCount) {
124       this.objDir = objDir;
125       this.rebuildCount = rebuildCount;
126     }
127 
128     public void exit() {
129       this.stop = true;
130     }
131 
132     @Override
133     public void run() {
134       if (this.rebuildCount < 10) {
135         return;
136       }
137       try {
138         final FileFilter updatedFiles = new FileFilter() {
139           private final long startTime = System.currentTimeMillis();
140 
141           @Override
142           public boolean accept(final File file) {
143             return file.lastModified() > this.startTime && !file.getName().endsWith(".xml");
144           }
145         };
146         while (!this.stop) {
147           System.err.print("\r" + this.objDir.listFiles(updatedFiles).length + " / " + this.rebuildCount
148               + " files compiled...");
149           System.err.print("\r");
150           System.err.flush();
151           if (!this.stop) {
152             Thread.sleep(5000);
153           }
154         }
155       } catch (final InterruptedException e) {
156       }
157       System.err.print("\r                                                                    ");
158       System.err.print("\r");
159       System.err.flush();
160       log(Integer.toString(this.rebuildCount) + " files were compiled.");
161     }
162 
163   }
164 
165   private static class ProjectFileCollector implements FileVisitor {
166     private final List<File> files;
167 
168     /**
169      * Creates a new ProjectFileCollector.
170      * 
171      * @param files
172      *          vector for collected files.
173      */
174     public ProjectFileCollector(final List<File> files) {
175       this.files = files;
176     }
177 
178     /**
179      * Called for each file to be considered for collection.
180      * 
181      * @param parentDir
182      *          parent directory
183      * @param filename
184      *          filename within directory
185      */
186     @Override
187     public void visit(final File parentDir, final String filename) {
188       this.files.add(new File(parentDir, filename));
189     }
190   }
191 
192   private static class SystemLibraryCollector implements FileVisitor {
193     private final Hashtable<String, File> libraries;
194     private final Linker linker;
195 
196     public SystemLibraryCollector(final Linker linker, final Hashtable<String, File> libraries) {
197       this.linker = linker;
198       this.libraries = libraries;
199     }
200 
201     @Override
202     public void visit(final File basedir, final String filename) {
203       if (this.linker.bid(filename) > 0) {
204         final File libfile = new File(basedir, filename);
205         final String key = this.linker.getLibraryKey(libfile);
206         this.libraries.put(key, libfile);
207       }
208     }
209   }
210 
211   private static final ProcessorConfiguration[] EMPTY_CONFIG_ARRAY = new ProcessorConfiguration[0];
212 
213   /**
214    * Builds a Hashtable to targets needing to be rebuilt keyed by compiler
215    * configuration
216    */
217   public static Map<CompilerConfiguration, Vector<TargetInfo>> getTargetsToBuildByConfiguration(
218       final Map<String, TargetInfo> targets) {
219     final Map<CompilerConfiguration, Vector<TargetInfo>> targetsByConfig = new HashMap<>();
220     for (final TargetInfo target : targets.values()) {
221       if (target.getRebuild()) {
222         // FIXME: Types do not match between the key of targetsByConfig and the return value of target.getConfiguration
223         Vector<TargetInfo> targetsForSameConfig = targetsByConfig.get(target.getConfiguration());
224         if (targetsForSameConfig != null) {
225           targetsForSameConfig.addElement(target);
226         } else {
227           targetsForSameConfig = new Vector<>();
228           targetsForSameConfig.addElement(target);
229           targetsByConfig.put((CompilerConfiguration) target.getConfiguration(), targetsForSameConfig);
230         }
231       }
232     }
233     return targetsByConfig;
234   }
235 
236   // FREEHEP
237   private int maxCores = 0;
238   private boolean ordered = false;
239   /** The compiler definitions. */
240   private final Vector<CompilerDef> _compilers = new Vector<>();
241   /** The output file type. */
242   // private LinkType _linkType = LinkType.EXECUTABLE;
243   /** The library sets. */
244   private final Vector _libsets = new Vector();
245   /** The linker definitions. */
246   private final Vector<LinkerDef> _linkers = new Vector<>();
247   /** The object directory. */
248   private File _objDir;
249   /** The output file. */
250   private File _outfile;
251   /** The linker definitions. */
252   private final Vector<TargetDef> targetPlatforms = new Vector<>();
253   /** The distributer definitions. */
254   private final Vector<DistributerDef> distributers = new Vector<>();
255   private final Vector<VersionInfo> versionInfos = new Vector<>();
256 
257   private final Vector<ProjectDef> projects = new Vector<>();
258 
259   private boolean projectsOnly = false;
260 
261   private boolean decorateLinkerOptions = true;
262 
263   /**
264    * If true, stop build on compile failure.
265    */
266   protected boolean failOnError = true;
267 
268   /**
269    * Content that appears in <cc>and also in <compiler>are maintained by a
270    * captive CompilerDef instance
271    */
272   private final CompilerDef compilerDef = new CompilerDef();
273   /** The OS390 dataset to build to object to */
274   private String dataset;
275   /**
276    * 
277    * Depth of dependency checking
278    * 
279    * Values < 0 indicate full dependency checking Values >= 0 indicate
280    * partial dependency checking and for superficial compilation checks. Will
281    * throw BuildException before attempting link
282    */
283   private int dependencyDepth = -1;
284   /**
285    * Content that appears in <cc>and also in <linker>are maintained by a
286    * captive CompilerDef instance
287    */
288   private final LinkerDef linkerDef = new LinkerDef();
289   /**
290    * contains the subsystem, output type and
291    * 
292    */
293   private final LinkType linkType = new LinkType();
294   /**
295    * The property name which will be set with the physical filename of the
296    * file that is generated by the linker
297    */
298   private String outputFileProperty;
299   /**
300    * if relentless = true, compilations should attempt to compile as many
301    * files as possible before throwing a BuildException
302    */
303   private boolean relentless;
304 
305   /**
306    * At which log-level do we log command-lines in the build?
307    */
308   private int commandLogLevel = Project.MSG_VERBOSE;
309 
310   public CCTask() {
311   }
312 
313   /**
314    * Adds a compiler definition or reference.
315    * 
316    * @param compiler
317    *          compiler
318    * @throws NullPointerException
319    *           if compiler is null
320    */
321   public void addConfiguredCompiler(final CompilerDef compiler) {
322     if (compiler == null) {
323       throw new NullPointerException("compiler");
324     }
325     compiler.setProject(getProject());
326     this._compilers.addElement(compiler);
327   }
328 
329   /**
330    * Adds a compiler command-line arg. Argument will be inherited by all
331    * nested compiler elements that do not have inherit="false".
332    * 
333    */
334   public void addConfiguredCompilerArg(final CompilerArgument arg) {
335     this.compilerDef.addConfiguredCompilerArg(arg);
336   }
337 
338   /**
339    * Adds a defineset. Will be inherited by all compiler elements that do not
340    * have inherit="false".
341    * 
342    * @param defs
343    *          Define set
344    */
345   public void addConfiguredDefineset(final DefineSet defs) {
346     this.compilerDef.addConfiguredDefineset(defs);
347   }
348 
349   /**
350    * Adds a distributer definition or reference (Non-functional prototype).
351    * 
352    * @param distributer
353    *          distributer
354    * @throws NullPointerException
355    *           if compiler is null
356    */
357   public void addConfiguredDistributer(final DistributerDef distributer) {
358     if (distributer == null) {
359       throw new NullPointerException("distributer");
360     }
361     distributer.setProject(getProject());
362     this.distributers.addElement(distributer);
363   }
364 
365   /**
366    * Adds a linker definition. The first linker that is not disqualified by
367    * its "if" and "unless" attributes will perform the link. If no child
368    * linker element is active, the linker implied by the cc elements name or
369    * classname attribute will be used.
370    * 
371    * @param linker
372    *          linker
373    * @throws NullPointerException
374    *           if linker is null
375    */
376   public void addConfiguredLinker(final LinkerDef linker) {
377     if (linker == null) {
378       throw new NullPointerException("linker");
379     }
380     linker.setProject(getProject());
381     this._linkers.addElement(linker);
382   }
383 
384   /**
385    * Adds a linker command-line arg. Argument will be inherited by all nested
386    * linker elements that do not have inherit="false".
387    */
388   public void addConfiguredLinkerArg(final LinkerArgument arg) {
389     this.linkerDef.addConfiguredLinkerArg(arg);
390   }
391 
392   /**
393    * Adds a target definition or reference (Non-functional prototype).
394    * 
395    * @param target
396    *          target
397    * @throws NullPointerException
398    *           if compiler is null
399    */
400   public void addConfiguredTarget(final TargetDef target) {
401     if (target == null) {
402       throw new NullPointerException("target");
403     }
404     target.setProject(getProject());
405     this.targetPlatforms.addElement(target);
406   }
407 
408   /**
409    * Adds desriptive version information to be included in the
410    * generated file. The first active version info block will
411    * be used.
412    */
413   public void addConfiguredVersioninfo(final VersionInfo newVersionInfo) {
414     newVersionInfo.setProject(this.getProject());
415     this.versionInfos.addElement(newVersionInfo);
416   }
417 
418   /**
419    * Add an environment variable to the launched process.
420    */
421   public void addEnv(final Environment.Variable var) {
422     this.compilerDef.addEnv(var);
423     for (int i = 0; i < this._compilers.size(); i++) {
424       final CompilerDef currentCompilerDef = this._compilers.elementAt(i);
425       currentCompilerDef.addEnv(var);
426     }
427     this.linkerDef.addEnv(var);
428   }
429 
430   /**
431    * Adds a source file set.
432    * 
433    * Files in these filesets will be auctioned to the available compiler
434    * configurations, with the default compiler implied by the cc element
435    * bidding last. If no compiler is interested in the file, it will be
436    * passed to the linker.
437    * 
438    * To have a file be processed by a particular compiler configuration, add
439    * a fileset to the corresponding compiler element.
440    */
441   public void addFileset(final ConditionalFileSet srcSet) {
442     this.compilerDef.addFileset(srcSet);
443   }
444 
445   /**
446    * Adds a library set.
447    * 
448    * Library sets will be inherited by all linker elements that do not have
449    * inherit="false".
450    * 
451    * @param libset
452    *          library set
453    * @throws NullPointerException
454    *           if libset is null.
455    */
456   public void addLibset(final LibrarySet libset) {
457     if (libset == null) {
458       throw new NullPointerException("libset");
459     }
460     this.linkerDef.addLibset(libset);
461   }
462 
463   /**
464    * Specifies the generation of IDE project file. Experimental.
465    * 
466    * @param projectDef
467    *          project file generation specification
468    */
469   public void addProject(final ProjectDef projectDef) {
470     if (projectDef == null) {
471       throw new NullPointerException("projectDef");
472     }
473     this.projects.addElement(projectDef);
474   }
475 
476   /**
477    * Adds a system library set. Timestamps and locations of system library
478    * sets are not used in dependency analysis.
479    * 
480    * Essential libraries (such as C Runtime libraries) should not be
481    * specified since the task will attempt to identify the correct libraries
482    * based on the multithread, debug and runtime attributes.
483    * 
484    * System library sets will be inherited by all linker elements that do not
485    * have inherit="false".
486    * 
487    * @param libset
488    *          library set
489    * @throws NullPointerException
490    *           if libset is null.
491    */
492   public void addSyslibset(final SystemLibrarySet libset) {
493     if (libset == null) {
494       throw new NullPointerException("libset");
495     }
496     this.linkerDef.addSyslibset(libset);
497   }
498 
499   /**
500    * Checks all targets that are not forced to be rebuilt or are missing
501    * object files to be checked for modified include files
502    * 
503    * @return total number of targets to be rebuilt
504    * 
505    */
506   protected int checkForChangedIncludeFiles(final Map<String, TargetInfo> targets) {
507     int potentialTargets = 0;
508     int definiteTargets = 0;
509     Iterator<TargetInfo> targetEnum = targets.values().iterator();
510     while (targetEnum.hasNext()) {
511       final TargetInfo target = targetEnum.next();
512       if (!target.getRebuild()) {
513         potentialTargets++;
514       } else {
515         definiteTargets++;
516       }
517     }
518     //
519     // If there were remaining targets that
520     // might be out of date
521     //
522     if (potentialTargets > 0) {
523       log("Starting dependency analysis for " + Integer.toString(potentialTargets) + " files.");
524       final DependencyTable dependencyTable = new DependencyTable(this._objDir);
525       try {
526         dependencyTable.load();
527       } catch (final Exception ex) {
528         log("Problem reading dependencies.xml: " + ex.toString());
529       }
530       targetEnum = targets.values().iterator();
531       while (targetEnum.hasNext()) {
532         final TargetInfo target = targetEnum.next();
533         if (!target.getRebuild()) {
534           if (dependencyTable.needsRebuild(this, target, this.dependencyDepth)) {
535             target.mustRebuild();
536           }
537         }
538       }
539       dependencyTable.commit(this);
540     }
541     //
542     // count files being rebuilt now
543     //
544     int currentTargets = 0;
545     targetEnum = targets.values().iterator();
546     while (targetEnum.hasNext()) {
547       final TargetInfo target = targetEnum.next();
548       if (target.getRebuild()) {
549         currentTargets++;
550       }
551     }
552     if (potentialTargets > 0) {
553       log(Integer.toString(potentialTargets - currentTargets + definiteTargets) + " files are up to date.");
554       log(Integer.toString(currentTargets - definiteTargets) + " files to be recompiled from dependency analysis.");
555     }
556     log(Integer.toString(currentTargets) + " total files to be compiled.");
557     return currentTargets;
558   }
559 
560   protected LinkerConfiguration collectExplicitObjectFiles(final Vector<File> objectFiles,
561       final Vector<File> sysObjectFiles, final VersionInfo versionInfo) {
562     //
563     // find the first eligible linker
564     //
565     //
566     ProcessorConfiguration linkerConfig = null;
567     LinkerDef selectedLinkerDef = null;
568     Linker selectedLinker = null;
569     final Hashtable<String, File> sysLibraries = new Hashtable<>();
570     final TargetDef targetPlatform = getTargetPlatform();
571     FileVisitor objCollector = null;
572     FileVisitor sysLibraryCollector = null;
573     for (int i = 0; i < this._linkers.size(); i++) {
574       final LinkerDef currentLinkerDef = this._linkers.elementAt(i);
575       if (currentLinkerDef.isActive()) {
576         selectedLinkerDef = currentLinkerDef;
577         selectedLinker = currentLinkerDef.getProcessor().getLinker(this.linkType);
578         //
579         // skip the linker if it doesn't know how to
580         // produce the specified link type
581         if (selectedLinker != null) {
582           linkerConfig = currentLinkerDef.createConfiguration(this, this.linkType, this.linkerDef, targetPlatform,
583               versionInfo);
584           if (linkerConfig != null) {
585             //
586             // create collectors for object files
587             // and system libraries
588             objCollector = new ObjectFileCollector(selectedLinker, objectFiles);
589             sysLibraryCollector = new SystemLibraryCollector(selectedLinker, sysLibraries);
590             //
591             // if the <linker> has embedded <fileset>'s
592             // (such as linker specific libraries)
593             // add them as object files.
594             //
595             if (currentLinkerDef.hasFileSets()) {
596               currentLinkerDef.visitFiles(objCollector);
597             }
598             //
599             // user libraries are just a specialized form
600             // of an object fileset
601             selectedLinkerDef.visitUserLibraries(selectedLinker, objCollector);
602           }
603           break;
604         }
605       }
606     }
607     if (linkerConfig == null) {
608       linkerConfig = this.linkerDef.createConfiguration(this, this.linkType, null, targetPlatform, versionInfo);
609       selectedLinker = this.linkerDef.getProcessor().getLinker(this.linkType);
610       objCollector = new ObjectFileCollector(selectedLinker, objectFiles);
611       sysLibraryCollector = new SystemLibraryCollector(selectedLinker, sysLibraries);
612     }
613     //
614     // unless there was a <linker> element that
615     // explicitly did not inherit files from
616     // containing <cc> element
617     if (selectedLinkerDef == null || selectedLinkerDef.getInherit()) {
618       this.linkerDef.visitUserLibraries(selectedLinker, objCollector);
619       this.linkerDef.visitSystemLibraries(selectedLinker, sysLibraryCollector);
620     }
621     //
622     // if there was a <syslibset> in a nested <linker>
623     // evaluate it last so it takes priority over
624     // identically named libs from <cc> element
625     //
626     if (selectedLinkerDef != null) {
627       //
628       // add any system libraries to the hashtable
629       // done in reverse order so the earliest
630       // on the classpath takes priority
631       selectedLinkerDef.visitSystemLibraries(selectedLinker, sysLibraryCollector);
632     }
633     //
634     // copy over any system libraries to the
635     // object files vector
636     //
637     final Enumeration<File> sysLibEnum = sysLibraries.elements();
638     while (sysLibEnum.hasMoreElements()) {
639       sysObjectFiles.addElement(sysLibEnum.nextElement());
640     }
641     return (LinkerConfiguration) linkerConfig;
642   }
643 
644   /**
645    * Adds an include path.
646    * 
647    * Include paths will be inherited by nested compiler elements that do not
648    * have inherit="false".
649    */
650   public IncludePath createIncludePath() {
651     return this.compilerDef.createIncludePath();
652   }
653 
654   /**
655    * Specifies precompilation prototype file and exclusions. Inherited by all
656    * compilers that do not have inherit="false".
657    * 
658    */
659   public PrecompileDef createPrecompile() throws BuildException {
660     return this.compilerDef.createPrecompile();
661   }
662 
663   /**
664    * Adds a system include path. Locations and timestamps of files located
665    * using the system include paths are not used in dependency analysis.
666    * 
667    * 
668    * Standard include locations should not be specified. The compiler
669    * adapters should recognized the settings from the appropriate environment
670    * variables or configuration files.
671    * 
672    * System include paths will be inherited by nested compiler elements that
673    * do not have inherit="false".
674    */
675   public SystemIncludePath createSysIncludePath() {
676     return this.compilerDef.createSysIncludePath();
677   }
678 
679   // ENDFREEHEP
680 
681   /**
682    * Executes the task. Compiles the given files.
683    * 
684    * @throws BuildException
685    *           if someting goes wrong with the build
686    */
687   @Override
688   public void execute() throws BuildException {
689     //
690     // if link type allowed objdir to be defaulted
691     // provide it from outfile
692     if (this._objDir == null) {
693       if (this._outfile != null) {
694         this._objDir = new File(this._outfile.getParent());
695       } else {
696         this._objDir = new File(".");
697       }
698     }
699 
700     //
701     // if the object directory does not exist
702     //
703     if (!this._objDir.exists()) {
704       throw new BuildException("Object directory does not exist");
705     }
706     final TargetHistoryTable objHistory = new TargetHistoryTable(this, this._objDir);
707 
708     //
709     // get the first active version info
710     //
711     VersionInfo versionInfo = null;
712     final Enumeration<VersionInfo> versionEnum = this.versionInfos.elements();
713     while (versionEnum.hasMoreElements()) {
714       versionInfo = versionEnum.nextElement();
715       versionInfo = versionInfo.merge();
716       if (versionInfo.isActive()) {
717         break;
718       } else {
719         versionInfo = null;
720       }
721     }
722 
723     //
724     // determine the eventual linker configuration
725     // (may be null) and collect any explicit
726     // object files or libraries
727     final Vector<File> objectFiles = new Vector<>();
728     final Vector<File> sysObjectFiles = new Vector<>();
729     final LinkerConfiguration linkerConfig = collectExplicitObjectFiles(objectFiles, sysObjectFiles, versionInfo);
730 
731     //
732     // Assemble hashtable of all files
733     // that we know how to compile (keyed by output file name)
734     //
735     final Map<String, TargetInfo> targets = getTargets(linkerConfig, objectFiles, versionInfo, this._outfile);
736     TargetInfo linkTarget = null;
737     //
738     // if output file is not specified,
739     // then skip link step
740     //
741     if (this._outfile != null) {
742       linkTarget = getLinkTarget(linkerConfig, objectFiles, sysObjectFiles, targets, versionInfo);
743     }
744 
745     if (this.projects.size() > 0) {
746       final List<File> files = new ArrayList<>();
747       final ProjectFileCollector matcher = new ProjectFileCollector(files);
748       for (int i = 0; i < this._compilers.size(); i++) {
749         final CompilerDef currentCompilerDef = this._compilers.elementAt(i);
750         if (currentCompilerDef.isActive()) {
751           if (currentCompilerDef.hasFileSets()) {
752             currentCompilerDef.visitFiles(matcher);
753           }
754         }
755       }
756       this.compilerDef.visitFiles(matcher);
757 
758       final Enumeration<ProjectDef> iter = this.projects.elements();
759       while (iter.hasMoreElements()) {
760         final ProjectDef projectDef = iter.nextElement();
761         if (projectDef.isActive()) {
762           projectDef.execute(this, files, targets, linkTarget);
763         }
764       }
765     }
766     if (this.projectsOnly) {
767       return;
768     }
769 
770     //
771     // mark targets that don't have a history record or
772     // whose source last modification time is not
773     // the same as the history to be rebuilt
774     //
775     objHistory.markForRebuild(targets);
776     final CCTaskProgressMonitor monitor = new CCTaskProgressMonitor(objHistory, versionInfo);
777     //
778     // check for changed include files
779     //
780     final int rebuildCount = checkForChangedIncludeFiles(targets);
781     if (rebuildCount > 0) {
782       BuildException compileException = null;
783       //
784       // compile all targets with getRebuild() == true
785       //
786       final Map<CompilerConfiguration, Vector<TargetInfo>> targetsByConfig = getTargetsToBuildByConfiguration(targets);
787       //
788       // build array containing Vectors with precompiled generation
789       // steps going first
790       //
791       final ArrayList<Vector<TargetInfo>> targetVectorsPreComp = new ArrayList<>();
792       final ArrayList<Vector<TargetInfo>> targetVectors = new ArrayList<>();
793 
794       int index = 0;
795       for (final Map.Entry<CompilerConfiguration, Vector<TargetInfo>> targetsForConfig : targetsByConfig.entrySet()) {
796         //
797         // get the configuration from the first entry
798         //
799         final CompilerConfiguration config = targetsForConfig.getKey();
800         if (config.isPrecompileGeneration()) {
801           targetVectorsPreComp.add(targetsForConfig.getValue());
802         } else {
803           targetVectors.add(targetsForConfig.getValue());
804         }
805       }
806 
807       // BEGINFREEHEP
808       final Progress progress = new Progress(getObjdir(), rebuildCount);
809       progress.start();
810       // ENDFREEHEP
811 
812       compileException = runTargetPool(monitor, compileException, targetVectorsPreComp);
813       if (compileException == null || this.relentless)
814         compileException = runTargetPool(monitor, compileException, targetVectors);
815 
816       // BEGINFREEHEP
817       progress.exit();
818       try {
819         progress.join();
820       } catch (final InterruptedException ex) {
821       }
822       // ENDFREEHEP
823 
824       //
825       // save the details of the object file compilation
826       // settings to disk for dependency analysis
827       //
828       try {
829         objHistory.commit();
830       } catch (final IOException ex) {
831         this.log("Error writing history.xml: " + ex.toString());
832       }
833       //
834       // if we threw a compile exception and
835       // didn't throw it at the time because
836       // we were relentless then
837       // save the history and
838       // throw the exception
839       //
840       if (compileException != null) {
841         if (this.failOnError) {
842           throw compileException;
843         } else {
844           log(compileException.getMessage(), Project.MSG_ERR);
845           return;
846         }
847       }
848     }
849     //
850     // if the dependency tree was not fully
851     // evaluated, then throw an exception
852     // since we really didn't do what we
853     // should have done
854     //
855     //
856     if (this.dependencyDepth >= 0) {
857       throw new BuildException("All files at depth " + Integer.toString(this.dependencyDepth)
858           + " from changes successfully compiled.\n"
859           + "Remove or change dependencyDepth to -1 to perform full compilation.");
860     }
861     //
862     // if no link target then
863     // commit the history for the object files
864     // and leave the task
865     if (linkTarget != null) {
866       //
867       // get the history for the link target (may be the same
868       // as the object history)
869       final TargetHistoryTable linkHistory = getLinkHistory(objHistory);
870       //
871       // see if it needs to be rebuilt
872       //
873       linkHistory.markForRebuild(linkTarget);
874       //
875       // if it needs to be rebuilt, rebuild it
876       //
877       final File output = linkTarget.getOutput();
878       if (linkTarget.getRebuild()) {
879         final LinkerConfiguration linkConfig = (LinkerConfiguration) linkTarget.getConfiguration();
880         // BEGINFREEHEP
881         log("Linking...");
882         log("Starting link {" + linkConfig.getIdentifier() + "}");
883         // ENDFREEHEP
884         if (this.failOnError) {
885           linkConfig.link(this, linkTarget);
886         } else {
887           try {
888             linkConfig.link(this, linkTarget);
889           } catch (final BuildException ex) {
890             log(ex.getMessage(), Project.MSG_ERR);
891             return;
892           }
893         }
894         if (this.outputFileProperty != null) {
895           getProject().setProperty(this.outputFileProperty, output.getAbsolutePath());
896         }
897         linkHistory.update(linkTarget);
898         try {
899           linkHistory.commit();
900         } catch (final IOException ex) {
901           log("Error writing link history.xml: " + ex.toString());
902         }
903       } else {
904         if (this.outputFileProperty != null) {
905           getProject().setProperty(this.outputFileProperty, output.getAbsolutePath());
906         }
907       }
908     }
909   }
910 
911   private BuildException runTargetPool(final CCTaskProgressMonitor monitor, BuildException compileException,
912       final ArrayList<Vector<TargetInfo>> targetVectors) {
913     int index;
914     for (final Vector<TargetInfo> targetsForConfig : targetVectors) {
915       //
916       // get the configuration from the first entry
917       //
918       final CompilerConfiguration config = (CompilerConfiguration) targetsForConfig.elementAt(0).getConfiguration();
919       //
920       // prepare the list of source files
921       //
922 
923       // BEGINFREEHEP
924       int noOfCores = Runtime.getRuntime().availableProcessors();
925       log("Found " + noOfCores + " processors available");
926       if (this.maxCores > 0) {
927         noOfCores = Math.min(this.maxCores, noOfCores);
928         log("Limited processors to " + noOfCores);
929       }
930       final int noOfFiles = targetsForConfig.size();
931       if (noOfFiles < noOfCores) {
932         noOfCores = noOfFiles;
933         log("Limited used processors to " + noOfCores);
934       }
935       if (this.ordered) {
936         noOfCores = 1;
937         log("Limited processors to 1 due to ordering of source files");
938       }
939 
940       final List<String>[] sourceFiles = new List[noOfCores];
941       for (int j = 0; j < sourceFiles.length; j++) {
942         sourceFiles[j] = new ArrayList<>(noOfFiles / sourceFiles.length);
943       }
944       final Enumeration<TargetInfo> targetsEnum = targetsForConfig.elements();
945       index = 0;
946       while (targetsEnum.hasMoreElements()) {
947         final TargetInfo targetInfo = targetsEnum.nextElement();
948         sourceFiles[index++].add(targetInfo.getSources()[0].toString());
949         index %= sourceFiles.length;
950       }
951 
952       // setup cores/cpus
953       final Core[] cores = new Core[noOfCores];
954       for (int j = 0; j < cores.length; j++) {
955         cores[j] = new Core(this, j, config, this._objDir, sourceFiles[j], this.relentless, monitor);
956         log("\nStarting Core " + j + " with " + sourceFiles[j].size() + " source files...");
957       }
958 
959       // starting cores
960       for (final Core core : cores) {
961         core.start();
962       }
963 
964       // checking cores
965       boolean alive = false;
966       try {
967         do {
968           alive = false;
969           for (int j = 0; j < cores.length; j++) {
970             if (cores[j] != null) {
971               if (cores[j].isAlive()) {
972                 alive = true;
973               } else {
974                 final Exception exception = cores[j].getException();
975                 if (exception != null) {
976                   if (compileException == null && exception instanceof BuildException) {
977                     compileException = (BuildException) exception;
978                   } else {
979                     log(cores[j].getName() + " " + exception + "                                  ", Project.MSG_ERR);
980                   }
981                   if (!this.relentless) {
982                     cores[j] = null;
983                     alive = false;
984                     break;
985                   }
986                 }
987                 cores[j] = null;
988               }
989             }
990           }
991           if (alive) {
992             // wait for a maximum of 5 seconds or #files*2 seconds.
993             Thread.sleep(Math.min(5000, sourceFiles[0].size() * 2000));
994           }
995         } while (alive);
996       } catch (final InterruptedException e) {
997         break;
998       }
999 
1000       // killing leftovers
1001       for (final Core core : cores) {
1002         if (core != null) {
1003           core.interrupt();
1004           log(core.getName() + " interrupted                                          ");
1005         }
1006       }
1007 
1008       if (!this.relentless && compileException != null) {
1009         break;
1010       }
1011       // ENDFREEHEP
1012 
1013       /*
1014        * OLD CODE
1015        * String[] sourceFiles = new String[targetsForConfig.size()];
1016        * Enumeration targetsEnum = targetsForConfig.elements();
1017        * index = 0;
1018        * while (targetsEnum.hasMoreElements()) {
1019        * TargetInfo targetInfo = ((TargetInfo) targetsEnum
1020        * .nextElement());
1021        * sourceFiles[index++] = targetInfo.getSources()[0]
1022        * .toString();
1023        * }
1024        * try {
1025        * config.compile(this, _objDir, sourceFiles, relentless,
1026        * monitor);
1027        * } catch (BuildException ex) {
1028        * if (compileException == null) {
1029        * compileException = ex;
1030        * }
1031        * if (!relentless)
1032        * break;
1033        * }
1034        */
1035     }
1036     return compileException;
1037   }
1038 
1039   // ENDFREEHEP
1040 
1041   /**
1042    * Get the commandLogLevel
1043    * 
1044    * @return The current commandLogLevel
1045    */
1046   public int getCommandLogLevel() {
1047     return this.commandLogLevel;
1048   }
1049 
1050   /**
1051    * Gets the dataset.
1052    * 
1053    * @return Returns a String
1054    */
1055   public String getDataset() {
1056     return this.dataset;
1057   }
1058 
1059   /**
1060    * Gets debug state.
1061    * 
1062    * @return true if building for debugging
1063    */
1064   public boolean getDebug() {
1065     return this.compilerDef.getDebug(null, 0);
1066   }
1067 
1068   /**
1069    * Gets the failonerror flag.
1070    * 
1071    * @return the failonerror flag
1072    */
1073   public boolean getFailonerror() {
1074     return this.failOnError;
1075   }
1076 
1077   protected TargetHistoryTable getLinkHistory(final TargetHistoryTable objHistory) {
1078     final File outputFileDir = new File(this._outfile.getParent());
1079     //
1080     // if the output file is being produced in the link
1081     // directory, then we can use the same history file
1082     //
1083     if (this._objDir.equals(outputFileDir)) {
1084       return objHistory;
1085     }
1086     return new TargetHistoryTable(this, outputFileDir);
1087   }
1088 
1089   protected TargetInfo getLinkTarget(final LinkerConfiguration linkerConfig, final Vector<File> objectFiles,
1090       final Vector<File> sysObjectFiles, final Map<String, TargetInfo> compileTargets, final VersionInfo versionInfo) {
1091     //
1092     // walk the compile phase targets and
1093     // add those sources that have already been
1094     // assigned to the linker or
1095     // our output files the linker knows how to consume
1096     // files the linker knows how to consume
1097     //
1098     for (final TargetInfo compileTarget : compileTargets.values()) {
1099       //
1100       // output of compile tasks
1101       //
1102       final int bid = linkerConfig.bid(compileTarget.getOutput().toString());
1103       if (bid > 0) {
1104         objectFiles.addElement(compileTarget.getOutput());
1105       }
1106     }
1107     final File[] objectFileArray = new File[objectFiles.size()];
1108     objectFiles.copyInto(objectFileArray);
1109     final File[] sysObjectFileArray = new File[sysObjectFiles.size()];
1110     sysObjectFiles.copyInto(sysObjectFileArray);
1111     final String baseName = this._outfile.getName();
1112     final String[] fullNames = linkerConfig.getOutputFileNames(baseName, versionInfo);
1113     final File outputFile = new File(this._outfile.getParent(), fullNames[0]);
1114     return new TargetInfo(linkerConfig, objectFileArray, sysObjectFileArray, outputFile, linkerConfig.getRebuild());
1115   }
1116 
1117   public int getMaxCores() {
1118     return this.maxCores;
1119   }
1120 
1121   public File getObjdir() {
1122     return this._objDir;
1123   }
1124 
1125   public File getOutfile() {
1126     return this._outfile;
1127   }
1128 
1129   /**
1130    * Gets output type.
1131    * 
1132    * @return output type
1133    */
1134   public String getOuttype() {
1135     return this.linkType.getOutputType();
1136   }
1137 
1138   /**
1139    * Gets subsystem name.
1140    * 
1141    * @return Subsystem name
1142    */
1143   public String getSubsystem() {
1144     return this.linkType.getSubsystem();
1145   }
1146 
1147   public TargetDef getTargetPlatform() {
1148     return null;
1149   }
1150 
1151   /**
1152    * This method collects a Hashtable, keyed by output file name, of
1153    * TargetInfo's for every source file that is specified in the filesets of
1154    * the <cc>and nested <compiler>elements. The TargetInfo's contain the
1155    * appropriate compiler configurations for their possible compilation
1156    * 
1157    */
1158   private Map<String, TargetInfo> getTargets(final LinkerConfiguration linkerConfig, final Vector<File> objectFiles,
1159       final VersionInfo versionInfo, final File outputFile) {
1160     // FREEHEP
1161     final List<String> order = new ArrayList<>();
1162 
1163     final Map<String, TargetInfo> targets = new TreeMap<>(new Comparator<String>() {
1164       // Order according to "order" List followed by alphabetical order
1165       @Override public int compare(String f0, String f1) {
1166         if (order.isEmpty()) {
1167           return f0.compareTo(f1);
1168         }
1169 
1170         // Trimming the path and trailing file extension to allow for order
1171         // comparison
1172         String compf0 = FilenameUtils.getBaseName(f0);
1173         String compf1 = FilenameUtils.getBaseName(f1);
1174 
1175         // remove the hash
1176         // TODO: well we hope it's a hash
1177         compf0 = FilenameUtils.removeExtension(compf0);
1178         compf1 = FilenameUtils.removeExtension(compf1);
1179 
1180         // order according to list or alphabetical
1181         final int i0 = order.indexOf(compf0);
1182         final int i1 = order.indexOf(compf1);
1183 
1184         if (i0 < 0 && i1 < 0) {
1185           // none in list
1186           // compare original values
1187           return f0.compareTo(f1);
1188         } else {
1189           // make sure we use only one core
1190           CCTask.this.ordered = true;
1191 
1192           if (i0 > 0 && i1 > 0) {
1193             // both in list
1194             return i0 == i1 ? 0 : i0 < i1 ? -1 : +1;
1195           } else if (i1 < 0) {
1196             // i0 in list
1197             return -1;
1198           } else {
1199             // i1 in list
1200             return +1;
1201           }
1202         }
1203       }
1204     });
1205 
1206     final TargetDef targetPlatform = getTargetPlatform();
1207 
1208     // BEGINFREEHEP
1209     // a little trick here, the inner function needs the list to be final,
1210     // so that the map order doesn't change after we start adding items,
1211     // populate with all the ordered items from each compiler type
1212     order.clear();
1213     for (int i = 0; i < this._compilers.size(); i++) {
1214       final CompilerDef currentCompilerDef = this._compilers.elementAt(i);
1215       if (currentCompilerDef.isActive()) {
1216         final List<String> compilerFileOrder = currentCompilerDef.getOrder();
1217         if (compilerFileOrder != null) {
1218           order.addAll(compilerFileOrder);
1219         }
1220       }
1221     }
1222     // ENDFREEHEP
1223     //
1224     // find active (specialized) compilers
1225     //
1226     final Vector<ProcessorConfiguration> biddingProcessors = new Vector<>(this._compilers.size());
1227     for (int i = 0; i < this._compilers.size(); i++) {
1228       final CompilerDef currentCompilerDef = this._compilers.elementAt(i);
1229       if (currentCompilerDef.isActive()) {
1230         final ProcessorConfiguration config = currentCompilerDef.createConfiguration(this, this.linkType,
1231             this.compilerDef, targetPlatform, versionInfo);
1232         //
1233         // see if this processor had a precompile child element
1234         //
1235         final PrecompileDef precompileDef = currentCompilerDef.getActivePrecompile(this.compilerDef);
1236         CommandLineCompilerConfiguration commandLineConfig = (CommandLineCompilerConfiguration) config;
1237         AbstractCompiler compiler = (AbstractCompiler) commandLineConfig.getCompiler();
1238         compiler.setWorkDir(currentCompilerDef.getWorkDir());
1239         ProcessorConfiguration[] localConfigs = new ProcessorConfiguration[] {
1240           config
1241         };
1242         //
1243         // if it does then
1244         //
1245         if (precompileDef != null) {
1246           final File prototype = precompileDef.getPrototype();
1247           //
1248           // will throw exceptions if prototype doesn't exist, etc
1249           //
1250           if (!prototype.exists()) {
1251             throw new BuildException("prototype (" + prototype.toString() + ") does not exist.");
1252           }
1253           if (prototype.isDirectory()) {
1254             throw new BuildException("prototype (" + prototype.toString() + ") is a directory.");
1255           }
1256           final String[] exceptFiles = precompileDef.getExceptFiles();
1257           //
1258           // create a precompile building and precompile using
1259           // variants of the configuration
1260           // or return null if compiler doesn't support
1261           // precompilation
1262           final CompilerConfiguration[] configs = ((CompilerConfiguration) config).createPrecompileConfigurations(
1263               prototype, exceptFiles);
1264           if (configs != null && configs.length == 2) {
1265             //
1266             // visit the precompiled file to add it into the
1267             // targets list (just like any other file if
1268             // compiler doesn't support precompilation)
1269             final TargetMatcher matcher = new TargetMatcher(this, this._objDir, new ProcessorConfiguration[] {
1270               configs[0]
1271             }, linkerConfig, objectFiles, targets, versionInfo);
1272 
1273             matcher.visit(new File(prototype.getParent()), prototype.getName());
1274             //
1275             // only the configuration that uses the
1276             // precompiled header gets added to the bidding list
1277             biddingProcessors.addElement(configs[1]);
1278             localConfigs = new ProcessorConfiguration[2];
1279             localConfigs[0] = configs[1];
1280             localConfigs[1] = config;
1281           }
1282         }
1283 
1284         //
1285         // if the compiler has a fileset
1286         // then allow it to add its files
1287         // to the set of potential targets
1288         if (currentCompilerDef.hasFileSets()) {
1289           final TargetMatcher matcher = new TargetMatcher(this, this._objDir, localConfigs, linkerConfig, objectFiles,
1290               targets, versionInfo);
1291           currentCompilerDef.visitFiles(matcher);
1292         }
1293         biddingProcessors.addElement(config);
1294       }
1295     }
1296     //
1297     // add fallback compiler at the end
1298     //
1299     if (this._compilers.size()==0) {
1300       final ProcessorConfiguration config = this.compilerDef.createConfiguration(this, this.linkType, null,
1301           targetPlatform, versionInfo);
1302       biddingProcessors.addElement(config);
1303       final ProcessorConfiguration[] bidders = new ProcessorConfiguration[biddingProcessors.size()];
1304       biddingProcessors.copyInto(bidders);
1305       //
1306       // bid out the <fileset>'s in the cctask
1307       //
1308       final TargetMatcher matcher = new TargetMatcher(this, this._objDir, bidders, linkerConfig, objectFiles, targets,
1309           versionInfo);
1310       this.compilerDef.visitFiles(matcher);
1311 
1312       if (outputFile != null && versionInfo != null) {
1313         final boolean isDebug = linkerConfig.isDebug();
1314         try {
1315           linkerConfig.getLinker()
1316               .addVersionFiles(versionInfo, this.linkType, outputFile, isDebug, this._objDir, matcher);
1317         } catch (final IOException ex) {
1318           throw new BuildException(ex);
1319         }
1320       }
1321     }
1322     return targets;
1323   }
1324 
1325   public boolean isDecorateLinkerOptions() {
1326     return this.decorateLinkerOptions;
1327   }
1328 
1329   /**
1330    * Sets the default compiler adapter. Use the "name" attribute when the
1331    * compiler is a supported compiler.
1332    * 
1333    * @param classname
1334    *          fully qualified classname which implements CompilerAdapter
1335    */
1336   public void setClassname(final String classname) {
1337     this.compilerDef.setClassname(classname);
1338     this.linkerDef.setClassname(classname);
1339   }
1340 
1341   /**
1342    * Set commandLogLevel
1343    * 
1344    * ( CUtil.runCommand() will honor this... )
1345    * 
1346    * @param commandLogLevel
1347    *          The log-level for command-logs, default is MSG_VERBOSE.
1348    */
1349   public void setCommandLogLevel(final int commandLogLevel) {
1350     this.commandLogLevel = commandLogLevel;
1351   }
1352 
1353   /**
1354    * Sets the dataset for OS/390 builds.
1355    * 
1356    * @param dataset
1357    *          The dataset to set
1358    */
1359   public void setDataset(final String dataset) {
1360     this.dataset = dataset;
1361   }
1362 
1363   /**
1364    * Enables or disables generation of debug info.
1365    */
1366   public void setDebug(final boolean debug) {
1367     this.compilerDef.setDebug(debug);
1368     this.linkerDef.setDebug(debug);
1369   }
1370 
1371   public void setDecorateLinkerOptions(final boolean decorateLinkerOptions) {
1372     this.decorateLinkerOptions = decorateLinkerOptions;
1373   }
1374 
1375   /**
1376    * Deprecated.
1377    * 
1378    * Controls the depth of the dependency evaluation. Used to do a quick
1379    * check of changes before a full build.
1380    * 
1381    * Any negative value which will perform full dependency checking. Positive
1382    * values will truncate dependency checking. A value of 0 will cause only
1383    * those files that changed to be recompiled, a value of 1 which cause
1384    * files that changed or that explicitly include a file that changed to be
1385    * recompiled.
1386    * 
1387    * Any non-negative value will cause a BuildException to be thrown before
1388    * attempting a link or completing the task.
1389    * 
1390    */
1391   public void setDependencyDepth(final int depth) {
1392     this.dependencyDepth = depth;
1393   }
1394 
1395   /**
1396    * Enables generation of exception handling code
1397    */
1398   public void setExceptions(final boolean exceptions) {
1399     this.compilerDef.setExceptions(exceptions);
1400   }
1401 
1402   /**
1403    * Indicates whether the build will continue
1404    * even if there are compilation errors; defaults to true.
1405    * 
1406    * @param fail
1407    *          if true halt the build on failure
1408    */
1409   public void setFailonerror(final boolean fail) {
1410     this.failOnError = fail;
1411   }
1412 
1413   // public LinkType getLinkType() {
1414   // return linkType;
1415   // }
1416   /**
1417    * Enables or disables incremental linking.
1418    * 
1419    * @param incremental
1420    *          new state
1421    */
1422   public void setIncremental(final boolean incremental) {
1423     this.linkerDef.setIncremental(incremental);
1424   }
1425 
1426   /**
1427    * Set use of libtool.
1428    * 
1429    * If set to true, the "libtool " will be prepended to the command line for
1430    * compatible processors
1431    * 
1432    * @param libtool
1433    *          If true, use libtool.
1434    */
1435   public void setLibtool(final boolean libtool) {
1436     this.compilerDef.setLibtool(libtool);
1437     this.linkerDef.setLibtool(libtool);
1438   }
1439 
1440   /**
1441    * Sets the output file type. Supported values "executable", "shared", and
1442    * "static". Deprecated, specify outtype instead.
1443    * 
1444    * @deprecated
1445    */
1446   @Deprecated
1447   public void setLink(final OutputTypeEnum outputType) {
1448     this.linkType.setOutputType(outputType);
1449   }
1450 
1451   // BEGINFREEHEP
1452   public void setLinkCPP(final boolean linkCPP) {
1453     this.linkType.setLinkCPP(linkCPP);
1454   }
1455 
1456   public void setLinkFortran(final boolean linkFortran) {
1457     this.linkType.setLinkFortran(linkFortran);
1458   }
1459 
1460   public void setLinkFortranMain(final boolean linkFortranMain) {
1461     this.linkType.setLinkFortranMain(linkFortranMain);
1462   }
1463 
1464   // ENDFREEHEP
1465 
1466   // BEGINFREEHEP
1467   public void setMaxCores(final int maxCores) {
1468     this.maxCores = maxCores;
1469   }
1470 
1471   /**
1472    * Enables or disables generation of multithreaded code
1473    * 
1474    * @param multi
1475    *          If true, generated code may be multithreaded.
1476    */
1477   public void setMultithreaded(final boolean multi) {
1478     this.compilerDef.setMultithreaded(multi);
1479   }
1480 
1481   //
1482   // keep near duplicate comment at CompilerDef.setName in sync
1483   //
1484   /**
1485    * Sets type of the default compiler and linker.
1486    * 
1487    * <table width="100%" border="1">
1488    * <thead>Supported compilers </thead>
1489    * <tr>
1490    * <td>gcc (default)</td>
1491    * <td>GCC C++ compiler</td>
1492    * </tr>
1493    * <tr>
1494    * <td>g++</td>
1495    * <td>GCC C++ compiler</td>
1496    * </tr>
1497    * <tr>
1498    * <td>c++</td>
1499    * <td>GCC C++ compiler</td>
1500    * </tr>
1501    * <tr>
1502    * <td>g77</td>
1503    * <td>GNU FORTRAN compiler</td>
1504    * </tr>
1505    * <tr>
1506    * <td>msvc</td>
1507    * <td>Microsoft Visual C++</td>
1508    * </tr>
1509    * <tr>
1510    * <td>bcc</td>
1511    * <td>Borland C++ Compiler</td>
1512    * </tr>
1513    * <tr>
1514    * <td>msrc</td>
1515    * <td>Microsoft Resource Compiler</td>
1516    * </tr>
1517    * <tr>
1518    * <td>brc</td>
1519    * <td>Borland Resource Compiler</td>
1520    * </tr>
1521    * <tr>
1522    * <td>df</td>
1523    * <td>Compaq Visual Fortran Compiler</td>
1524    * </tr>
1525    * <tr>
1526    * <td>midl</td>
1527    * <td>Microsoft MIDL Compiler</td>
1528    * </tr>
1529    * <tr>
1530    * <td>icl</td>
1531    * <td>Intel C++ compiler for Windows (IA-32)</td>
1532    * </tr>
1533    * <tr>
1534    * <td>ecl</td>
1535    * <td>Intel C++ compiler for Windows (IA-64)</td>
1536    * </tr>
1537    * <tr>
1538    * <td>icc</td>
1539    * <td>Intel C++ compiler for Linux (IA-32)</td>
1540    * </tr>
1541    * <tr>
1542    * <td>ecc</td>
1543    * <td>Intel C++ compiler for Linux (IA-64)</td>
1544    * </tr>
1545    * <tr>
1546    * <td>CC</td>
1547    * <td>Sun ONE C++ compiler</td>
1548    * </tr>
1549    * <tr>
1550    * <td>aCC</td>
1551    * <td>HP aC++ C++ Compiler</td>
1552    * </tr>
1553    * <tr>
1554    * <td>os390</td>
1555    * <td>OS390 C Compiler</td>
1556    * </tr>
1557    * <tr>
1558    * <td>os400</td>
1559    * <td>Icc Compiler</td>
1560    * </tr>
1561    * <tr>
1562    * <td>sunc89</td>
1563    * <td>Sun C89 C Compiler</td>
1564    * </tr>
1565    * <tr>
1566    * <td>xlC</td>
1567    * <td>VisualAge C Compiler</td>
1568    * </tr>
1569    * <tr>
1570    * <td>uic</td>
1571    * <td>Qt user interface compiler (creates .h, .cpp and moc_*.cpp files).</td>
1572    * </tr>
1573    * <tr>
1574    * <td>moc</td>
1575    * <td>Qt meta-object compiler</td>
1576    * </tr>
1577    * <tr>
1578    * <td>xpidl</td>
1579    * <td>Mozilla xpidl compiler (creates .h and .xpt files).</td>
1580    * </tr>
1581    * <tr>
1582    * <td>wcl</td>
1583    * <td>OpenWatcom C/C++ compiler</td>
1584    * </tr>
1585    * <tr>
1586    * <td>wfl</td>
1587    * <td>OpenWatcom FORTRAN compiler</td>
1588    * </tr>
1589    * </table>
1590    * 
1591    */
1592   public void setName(final CompilerEnum name) {
1593     this.compilerDef.setName(name);
1594     final Processor compiler = this.compilerDef.getProcessor();
1595     final Linker linker = compiler.getLinker(this.linkType);
1596     this.linkerDef.setProcessor(linker);
1597   }
1598 
1599   /**
1600    * Do not propagate old environment when new environment variables are
1601    * specified.
1602    */
1603   public void setNewenvironment(final boolean newenv) {
1604     this.compilerDef.setNewenvironment(newenv);
1605     for (int i = 0; i < this._compilers.size(); i++) {
1606       final CompilerDef currentCompilerDef = this._compilers.elementAt(i);
1607       currentCompilerDef.setNewenvironment(newenv);
1608     }
1609     this.linkerDef.setNewenvironment(newenv);
1610   }
1611 
1612   /**
1613    * Sets the destination directory for object files.
1614    * 
1615    * Generally this should be a property expression that evaluates to
1616    * distinct debug and release object file directories.
1617    * 
1618    * @param dir
1619    *          object directory
1620    */
1621   public void setObjdir(final File dir) {
1622     if (dir == null) {
1623       throw new NullPointerException("dir");
1624     }
1625     this._objDir = dir;
1626   }
1627 
1628   /**
1629    * Sets optimization.
1630    * 
1631    * @param optimization
1632    */
1633   public void setOptimize(final OptimizationEnum optimization) {
1634     this.compilerDef.setOptimize(optimization);
1635   }
1636 
1637   /**
1638    * Sets the output file name. If not specified, the task will only compile
1639    * files and not attempt to link. If an extension is not specified, the
1640    * task may use a system appropriate extension and prefix, for example,
1641    * outfile="example" may result in "libexample.so" being created.
1642    * 
1643    * @param outfile
1644    *          output file name
1645    */
1646   public void setOutfile(final File outfile) {
1647     //
1648     // if file name was empty, skip link step
1649     //
1650     if (outfile == null || outfile.toString().length() > 0) {
1651       this._outfile = outfile;
1652     }
1653   }
1654 
1655   /**
1656    * Specifies the name of a property to set with the physical filename that
1657    * is produced by the linker
1658    */
1659   public void setOutputFileProperty(final String outputFileProperty) {
1660     this.outputFileProperty = outputFileProperty;
1661   }
1662 
1663   /**
1664    * Sets the output file type. Supported values "executable", "shared", and
1665    * "static".
1666    */
1667   public void setOuttype(final OutputTypeEnum outputType) {
1668     this.linkType.setOutputType(outputType);
1669   }
1670 
1671   // ENDFREEHEP
1672 
1673   /**
1674    * Sets the project.
1675    */
1676   @Override
1677   public void setProject(final Project project) {
1678     super.setProject(project);
1679     this.compilerDef.setProject(project);
1680     this.linkerDef.setProject(project);
1681   }
1682 
1683   public void setProjectsOnly(final boolean value) {
1684     this.projectsOnly = value;
1685   }
1686 
1687   /**
1688    * If set to true, all files will be rebuilt.
1689    * 
1690    * @param rebuildAll
1691    *          If true, all files will be rebuilt. If false, up to
1692    *          date files will not be rebuilt.
1693    */
1694   public void setRebuild(final boolean rebuildAll) {
1695     this.compilerDef.setRebuild(rebuildAll);
1696     this.linkerDef.setRebuild(rebuildAll);
1697   }
1698 
1699   /**
1700    * If set to true, compilation errors will not stop the task until all
1701    * files have been attempted.
1702    * 
1703    * @param relentless
1704    *          If true, don't stop on the first compilation error
1705    * 
1706    */
1707   public void setRelentless(final boolean relentless) {
1708     this.relentless = relentless;
1709   }
1710 
1711   /**
1712    * Enables run-time type information.
1713    */
1714   public void setRtti(final boolean rtti) {
1715     this.compilerDef.setRtti(rtti);
1716   }
1717 
1718   /**
1719    * Sets the type of runtime library, possible values "dynamic", "static".
1720    */
1721   public void setRuntime(final RuntimeType rtlType) {
1722     this.linkType.setStaticRuntime(rtlType.getIndex() == 1);
1723   }
1724 
1725   /**
1726    * Sets the nature of the subsystem under which that the program will
1727    * execute.
1728    * 
1729    * <table width="100%" border="1">
1730    * <thead>Supported subsystems </thead>
1731    * <tr>
1732    * <td>gui</td>
1733    * <td>Graphical User Interface</td>
1734    * </tr>
1735    * <tr>
1736    * <td>console</td>
1737    * <td>Command Line Console</td>
1738    * </tr>
1739    * <tr>
1740    * <td>other</td>
1741    * <td>Other</td>
1742    * </tr>
1743    * </table>
1744    * 
1745    * @param subsystem
1746    *          subsystem
1747    * @throws NullPointerException
1748    *           if subsystem is null
1749    */
1750   public void setSubsystem(final SubsystemEnum subsystem) {
1751     if (subsystem == null) {
1752       throw new NullPointerException("subsystem");
1753     }
1754     this.linkType.setSubsystem(subsystem);
1755   }
1756 
1757   /**
1758    * Enumerated attribute with the values "none", "severe", "default",
1759    * "production", "diagnostic", and "aserror".
1760    */
1761   public void setWarnings(final WarningLevelEnum level) {
1762     this.compilerDef.setWarnings(level);
1763   }
1764 
1765 }