diff options
Diffstat (limited to 'src/main')
47 files changed, 4009 insertions, 2724 deletions
diff --git a/src/main/java/net/sf/antcontrib/cpptasks/CCTask.java b/src/main/java/net/sf/antcontrib/cpptasks/CCTask.java index b1ef17b..ab40e95 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/CCTask.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/CCTask.java @@ -1,6 +1,6 @@ /* * - * Copyright 2001-2005 The Ant-Contrib project + * Copyright 2001-2008 The Ant-Contrib project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ * limitations under the License. */ package net.sf.antcontrib.cpptasks; - import java.io.File; import java.io.FileFilter; import java.io.IOException; @@ -47,7 +46,6 @@ import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; import org.apache.tools.ant.types.Environment; - /** * Compile and link task. * @@ -58,9 +56,8 @@ import org.apache.tools.ant.types.Environment; * Resource files. * </p> * - * * <p> - * Copyright (c) 2001-2006, The Ant-Contrib project. + * Copyright (c) 2001-2008, The Ant-Contrib project. * </p> * * <p> @@ -74,1619 +71,1612 @@ import org.apache.tools.ant.types.Environment; * </p> * * <p> - * THIS SOFTWARE IS PROVIDED 'AS-IS', See + * THIS SOFTWARE IS PROVIDED 'AS-IS', See * http://www.apache.org/licenses/LICENSE-2.0 for additional disclaimers. * </p> * * To use: * <ol> - * <li>Place cpptasks.jar into Ant's classpath by placing in Ant's lib - * directory, adding to CLASSPATH environment variable or using the -lib command - * line option.</li> - * <li>Add type and task definitions in build file: + * <li> + * Place cpptasks.jar into Ant's classpath by placing it in Ant's lib + * directory, adding it to the CLASSPATH environment variable or by using the + * -lib command line option. + * </li> + * <li> + * Add type and task definitions to the build file: + * <ul> + * <li> + * Ant 1.6 or later: + * <ul> + * <li>Add xmlns:cpptasks="antlib:net.sf.antcontrib.cpptasks" to + * <project> element. + * </li> + * <li> + * Add <cpptasks:cc/>, <cpptasks:compiler/> and + * <cpptasks:linker/> elements to the project. + * </li> + * </ul> + * </li> + * <li> + * Ant 1.5 or later: * <ul> - * <li>Ant 1.6 or later: add - * xmlns:cpptasks="antlib:org.sf.net.antcontrib.cpptasks" to <project> - * element.</li> - * <li>Ant 1.5 or later: Add <taskdef resource="cpptasks.tasks"/> and - * <typedef resource="cpptasks.types"/> to body of <project> - * element.</li> + * <li>Add <taskdef resource="cpptasks.tasks"/> and + * <typedef resource="cpptasks.types"/> to body of <project> + * element. + * </li> + * <li> + * Add <cc/>, <compiler/> and <linker/> elements to the + * project. + * </li> * </ul> * </li> - * <li>Add <cc/>, <compiler/> and <linker/> elements to - * project.</li> - * <li>Set path and environment variables to be able to run compiler from - * command line.</li> - * <li>Build project.</li> + * </ul> + * </li> + * <li> + * Set the path and environment variables to be able to run compiler from + * command line. + * </li> + * <li> + * Build the project. + * </li> * </ol> * * @author Adam Murdoch * @author Curt Arnold */ public class CCTask extends Task { - private static class SystemLibraryCollector implements FileVisitor { - private Hashtable libraries; - private Linker linker; - - public SystemLibraryCollector(Linker linker, Hashtable libraries) { - this.linker = linker; - this.libraries = libraries; - } - - public void visit(File basedir, String filename) { - if (linker.bid(filename) > 0) { - File libfile = new File(basedir, filename); - String key = linker.getLibraryKey(libfile); - libraries.put(key, libfile); - } - } - } - - private static class ProjectFileCollector implements FileVisitor { - private final List files; - - /** - * Creates a new ProjectFileCollector. - * - * @param files - * vector for collected files. - */ - public ProjectFileCollector(List files) { - this.files = files; - } - - /** - * Called for each file to be considered for collection. - * - * @param parentDir - * parent directory - * @param filename - * filename within directory - */ - public void visit(File parentDir, String filename) { - files.add(new File(parentDir, filename)); - } - } - - private static final ProcessorConfiguration[] EMPTY_CONFIG_ARRAY = new ProcessorConfiguration[0]; - - /** - * Builds a Hashtable to targets needing to be rebuilt keyed by compiler - * configuration - */ - public static Hashtable getTargetsToBuildByConfiguration(Hashtable targets) { - Hashtable targetsByConfig = new Hashtable(); - Enumeration targetEnum = targets.elements(); - while (targetEnum.hasMoreElements()) { - TargetInfo target = (TargetInfo) targetEnum.nextElement(); - if (target.getRebuild()) { - Vector targetsForSameConfig = (Vector) targetsByConfig - .get(target.getConfiguration()); - if (targetsForSameConfig != null) { - targetsForSameConfig.addElement(target); - } else { - targetsForSameConfig = new Vector(); - targetsForSameConfig.addElement(target); - targetsByConfig.put(target.getConfiguration(), - targetsForSameConfig); - } - } - } - return targetsByConfig; - } - - // FREEHEP - private int maxCores = 0; - /** The compiler definitions. */ - private Vector _compilers = new Vector(); - /** The output file type. */ - // private LinkType _linkType = LinkType.EXECUTABLE; - /** The library sets. */ - private Vector _libsets = new Vector(); - /** The linker definitions. */ - private Vector _linkers = new Vector(); - /** The object directory. */ - private File _objDir; - /** The output file. */ - private File _outfile; - /** The linker definitions. */ - private final Vector targetPlatforms = new Vector(); - /** The distributer definitions. */ - private Vector distributers = new Vector(); - private final Vector versionInfos = new Vector(); - private final Vector projects = new Vector(); - private boolean projectsOnly = false; - - /** - * If true, stop build on compile failure. - */ - protected boolean failOnError = true; - - /** - * Content that appears in <cc>and also in <compiler>are maintained by a - * captive CompilerDef instance - */ - private final CompilerDef compilerDef = new CompilerDef(); - /** The OS390 dataset to build to object to */ - private String dataset; - /** - * - * Depth of dependency checking - * - * Values < 0 indicate full dependency checking Values >= 0 indicate partial - * dependency checking and for superficial compilation checks. Will throw - * BuildException before attempting link - */ - private int dependencyDepth = -1; - /** - * Content that appears in <cc>and also in <linker>are maintained by a - * captive CompilerDef instance - */ - private final LinkerDef linkerDef = new LinkerDef(); - /** - * contains the subsystem, output type and - * - */ - private final LinkType linkType = new LinkType(); - /** - * The property name which will be set with the physical filename of the - * file that is generated by the linker - */ - private String outputFileProperty; - /** - * if relentless = true, compilations should attempt to compile as many - * files as possible before throwing a BuildException - */ - private boolean relentless; - - public CCTask() { - } - - /** - * Adds a compiler definition or reference. - * - * @param compiler - * compiler - * @throws NullPointerException - * if compiler is null - */ - public void addConfiguredCompiler(CompilerDef compiler) { - if (compiler == null) { - throw new NullPointerException("compiler"); - } - compiler.setProject(getProject()); - _compilers.addElement(compiler); - } - - /** - * Adds a compiler command-line arg. Argument will be inherited by all - * nested compiler elements that do not have inherit="false". - * - */ - public void addConfiguredCompilerArg(CompilerArgument arg) { - compilerDef.addConfiguredCompilerArg(arg); - } - /** - * Adds a defineset. Will be inherited by all compiler elements that do not - * have inherit="false". - * - * @param defs - * Define set - */ - public void addConfiguredDefineset(DefineSet defs) { - compilerDef.addConfiguredDefineset(defs); - } - /** - * Adds a linker definition. The first linker that is not disqualified by - * its "if" and "unless" attributes will perform the link. If no child - * linker element is active, the linker implied by the cc elements name or - * classname attribute will be used. - * - * @param linker - * linker - * @throws NullPointerException - * if linker is null - */ - public void addConfiguredLinker(LinkerDef linker) { - if (linker == null) { - throw new NullPointerException("linker"); - } - linker.setProject(getProject()); - _linkers.addElement(linker); - } - /** - * Adds a linker command-line arg. Argument will be inherited by all nested - * linker elements that do not have inherit="false". - */ - public void addConfiguredLinkerArg(LinkerArgument arg) { - linkerDef.addConfiguredLinkerArg(arg); - } - /** - * Add an environment variable to the launched process. - */ - public void addEnv(Environment.Variable var) { - compilerDef.addEnv(var); - linkerDef.addEnv(var); - } - /** - * Adds a source file set. - * - * Files in these filesets will be auctioned to the available compiler - * configurations, with the default compiler implied by the cc element - * bidding last. If no compiler is interested in the file, it will be passed - * to the linker. - * - * To have a file be processed by a particular compiler configuration, add a - * fileset to the corresponding compiler element. - */ - public void addFileset(ConditionalFileSet srcSet) { - compilerDef.addFileset(srcSet); - } - /** - * Adds a library set. - * - * Library sets will be inherited by all linker elements that do not have - * inherit="false". - * - * @param libset - * library set - * @throws NullPointerException - * if libset is null. - */ - public void addLibset(LibrarySet libset) { - if (libset == null) { - throw new NullPointerException("libset"); - } - linkerDef.addLibset(libset); - } - - /** - * Adds a system library set. Timestamps and locations of system library - * sets are not used in dependency analysis. - * - * Essential libraries (such as C Runtime libraries) should not be specified - * since the task will attempt to identify the correct libraries based on - * the multithread, debug and runtime attributes. - * - * System library sets will be inherited by all linker elements that do not - * have inherit="false". - * - * @param libset - * library set - * @throws NullPointerException - * if libset is null. - */ - public void addSyslibset(SystemLibrarySet libset) { - if (libset == null) { - throw new NullPointerException("libset"); - } - linkerDef.addSyslibset(libset); - } - - /** - * Specifies the generation of IDE project file. Experimental. - * - * @param projectDef - * project file generation specification - */ - public void addProject(final ProjectDef projectDef) { - if (projectDef == null) { - throw new NullPointerException("projectDef"); - } - projects.addElement(projectDef); - } - - public void setProjectsOnly(final boolean value) { - projectsOnly = value; - } - - /** - * Checks all targets that are not forced to be rebuilt or are missing - * object files to be checked for modified include files - * - * @returns total number of targets to be rebuilt - * - */ - protected int checkForChangedIncludeFiles(Hashtable targets) { - int potentialTargets = 0; - int definiteTargets = 0; - Enumeration targetEnum = targets.elements(); - while (targetEnum.hasMoreElements()) { - TargetInfo target = (TargetInfo) targetEnum.nextElement(); - if (!target.getRebuild()) { - potentialTargets++; - } else { - definiteTargets++; - } - } - // - // If there were remaining targets that - // might be out of date - // - if (potentialTargets > 0) { - log("Starting dependency analysis for " - + Integer.toString(potentialTargets) + " files."); - DependencyTable dependencyTable = new DependencyTable(_objDir); - try { - dependencyTable.load(); - } catch (Exception ex) { - log("Problem reading dependencies.xml: " + ex.toString()); - } - targetEnum = targets.elements(); - while (targetEnum.hasMoreElements()) { - TargetInfo target = (TargetInfo) targetEnum.nextElement(); - if (!target.getRebuild()) { - if (dependencyTable.needsRebuild(this, target, - dependencyDepth)) { - target.mustRebuild(); - } - } - } - dependencyTable.commit(this); - } - // - // count files being rebuilt now - // - int currentTargets = 0; - targetEnum = targets.elements(); - while (targetEnum.hasMoreElements()) { - TargetInfo target = (TargetInfo) targetEnum.nextElement(); - if (target.getRebuild()) { - currentTargets++; - } - } - if (potentialTargets > 0) { - log(Integer.toString(potentialTargets - currentTargets - + definiteTargets) - + " files are up to date."); - log(Integer.toString(currentTargets - definiteTargets) - + " files to be recompiled from dependency analysis."); - } - log(Integer.toString(currentTargets) + " total files to be compiled."); - return currentTargets; - } - - protected LinkerConfiguration collectExplicitObjectFiles( - Vector objectFiles, Vector sysObjectFiles, VersionInfo versionInfo) { - // - // find the first eligible linker - // - // - ProcessorConfiguration linkerConfig = null; - LinkerDef selectedLinkerDef = null; - Linker selectedLinker = null; - Hashtable sysLibraries = new Hashtable(); - TargetDef targetPlatform = getTargetPlatform(); - FileVisitor objCollector = null; - FileVisitor sysLibraryCollector = null; - for (int i = 0; i < _linkers.size(); i++) { - LinkerDef currentLinkerDef = (LinkerDef) _linkers.elementAt(i); - if (currentLinkerDef.isActive()) { - selectedLinkerDef = currentLinkerDef; - selectedLinker = currentLinkerDef.getProcessor().getLinker( - linkType); - // - // skip the linker if it doesn't know how to - // produce the specified link type - if (selectedLinker != null) { - linkerConfig = currentLinkerDef.createConfiguration(this, - linkType, linkerDef, targetPlatform, versionInfo); - if (linkerConfig != null) { - // - // create collectors for object files - // and system libraries - objCollector = new ObjectFileCollector(selectedLinker, - objectFiles); - sysLibraryCollector = new SystemLibraryCollector( - selectedLinker, sysLibraries); - // - // if the <linker> has embedded <fileset>'s - // (such as linker specific libraries) - // add them as object files. - // - if (currentLinkerDef.hasFileSets()) { - currentLinkerDef.visitFiles(objCollector); - } - // - // user libraries are just a specialized form - // of an object fileset - selectedLinkerDef.visitUserLibraries(selectedLinker, - objCollector); - } - break; - } - } - } - if (linkerConfig == null) { - linkerConfig = linkerDef.createConfiguration(this, linkType, null, - targetPlatform, versionInfo); - selectedLinker = (Linker) linkerDef.getProcessor().getLinker( - linkType); - objCollector = new ObjectFileCollector(selectedLinker, objectFiles); - sysLibraryCollector = new SystemLibraryCollector(selectedLinker, - sysLibraries); - } - // - // unless there was a <linker> element that - // explicitly did not inherit files from - // containing <cc> element - if (selectedLinkerDef == null || selectedLinkerDef.getInherit()) { - linkerDef.visitUserLibraries(selectedLinker, objCollector); - linkerDef.visitSystemLibraries(selectedLinker, sysLibraryCollector); - } - // - // if there was a <syslibset> in a nested <linker> - // evaluate it last so it takes priority over - // identically named libs from <cc> element - // - if (selectedLinkerDef != null) { - // - // add any system libraries to the hashtable - // done in reverse order so the earliest - // on the classpath takes priority - selectedLinkerDef.visitSystemLibraries(selectedLinker, - sysLibraryCollector); - } - // - // copy over any system libraries to the - // object files vector - // - Enumeration sysLibEnum = sysLibraries.elements(); - while (sysLibEnum.hasMoreElements()) { - sysObjectFiles.addElement(sysLibEnum.nextElement()); - } - return (LinkerConfiguration) linkerConfig; - } - - /** - * Adds an include path. - * - * Include paths will be inherited by nested compiler elements that do not - * have inherit="false". - */ - public IncludePath createIncludePath() { - return compilerDef.createIncludePath(); - } - - /** - * Specifies precompilation prototype file and exclusions. Inherited by all - * compilers that do not have inherit="false". - * - */ - public PrecompileDef createPrecompile() throws BuildException { - return compilerDef.createPrecompile(); - } - - /** - * Adds a system include path. Locations and timestamps of files located - * using the system include paths are not used in dependency analysis. - * - * - * Standard include locations should not be specified. The compiler adapters - * should recognized the settings from the appropriate environment variables - * or configuration files. - * - * System include paths will be inherited by nested compiler elements that - * do not have inherit="false". - */ - public SystemIncludePath createSysIncludePath() { - return compilerDef.createSysIncludePath(); - } - - /** - * Executes the task. Compiles the given files. - * - * @throws BuildException - * if someting goes wrong with the build - */ - public void execute() throws BuildException { - // - // if link type allowed objdir to be defaulted - // provide it from outfile - if (_objDir == null) { - if (_outfile != null) { - _objDir = new File(_outfile.getParent()); - } else { - _objDir = new File("."); - } - } - - // - // if the object directory does not exist - // - if (!_objDir.exists()) { - throw new BuildException("Object directory does not exist"); - } - TargetHistoryTable objHistory = new TargetHistoryTable(this, _objDir); - - // - // get the first active version info - // - VersionInfo versionInfo = null; - Enumeration versionEnum = versionInfos.elements(); - while (versionEnum.hasMoreElements()) { - versionInfo = (VersionInfo) versionEnum.nextElement(); - versionInfo = versionInfo.merge(); - if (versionInfo.isActive()) { - break; - } else { - versionInfo = null; - } - } - - // - // determine the eventual linker configuration - // (may be null) and collect any explicit - // object files or libraries - Vector objectFiles = new Vector(); - Vector sysObjectFiles = new Vector(); - LinkerConfiguration linkerConfig = collectExplicitObjectFiles( - objectFiles, sysObjectFiles, versionInfo); - - // - // Assemble hashtable of all files - // that we know how to compile (keyed by output file name) - // - Hashtable targets = getTargets(linkerConfig, objectFiles, versionInfo, - _outfile); - TargetInfo linkTarget = null; - // - // if output file is not specified, - // then skip link step - // - if (_outfile != null) { - linkTarget = getLinkTarget(linkerConfig, objectFiles, - sysObjectFiles, targets, versionInfo); - } - - if (projects.size() > 0) { - ArrayList files = new ArrayList(); - ProjectFileCollector matcher = new ProjectFileCollector(files); - for (int i = 0; i < _compilers.size(); i++) { - CompilerDef currentCompilerDef = (CompilerDef) _compilers - .elementAt(i); - if (currentCompilerDef.isActive()) { - if (currentCompilerDef.hasFileSets()) { - currentCompilerDef.visitFiles(matcher); - } - } - } - compilerDef.visitFiles(matcher); - - Enumeration iter = projects.elements(); - while (iter.hasMoreElements()) { - ProjectDef projectDef = (ProjectDef) iter.nextElement(); - if (projectDef.isActive()) { - projectDef.execute(this, files, targets, linkTarget); - } - } - } - if (projectsOnly) - return; - - // - // mark targets that don't have a history record or - // whose source last modification time is not - // the same as the history to be rebuilt - // - objHistory.markForRebuild(targets); - CCTaskProgressMonitor monitor = new CCTaskProgressMonitor(objHistory, - versionInfo); - // - // check for changed include files - // - int rebuildCount = checkForChangedIncludeFiles(targets); - if (rebuildCount > 0) { - BuildException compileException = null; - // - // compile all targets with getRebuild() == true - // - Hashtable targetsByConfig = getTargetsToBuildByConfiguration(targets); - // - // build array containing Vectors with precompiled generation - // steps going first - // - Vector[] targetVectors = new Vector[targetsByConfig.size()]; - int index = 0; - Enumeration targetVectorEnum = targetsByConfig.elements(); - while (targetVectorEnum.hasMoreElements()) { - Vector targetsForConfig = (Vector) targetVectorEnum - .nextElement(); - // - // get the configuration from the first entry - // - CompilerConfiguration config = (CompilerConfiguration) ((TargetInfo) targetsForConfig - .elementAt(0)).getConfiguration(); - if (config.isPrecompileGeneration()) { - targetVectors[index++] = targetsForConfig; - } - } - targetVectorEnum = targetsByConfig.elements(); - while (targetVectorEnum.hasMoreElements()) { - Vector targetsForConfig = (Vector) targetVectorEnum - .nextElement(); - for (int i = 0; i < targetVectors.length; i++) { - if (targetVectors[i] == targetsForConfig) { - break; - } - if (targetVectors[i] == null) { - targetVectors[i] = targetsForConfig; - break; - } - } - } - - // BEGINFREEHEP - Progress progress = new Progress(getObjdir(), rebuildCount); - progress.start(); - - for (int i = 0; i < targetVectors.length; i++) { - // - // get the targets for this configuration - // - Vector targetsForConfig = targetVectors[i]; - // - // get the configuration from the first entry - // - CompilerConfiguration config = (CompilerConfiguration) ((TargetInfo) targetsForConfig - .elementAt(0)).getConfiguration(); - // - // prepare the list of source files - // - - // BEGINFREEHEP - int noOfCores = Runtime.getRuntime().availableProcessors(); - log("Found "+noOfCores+" processors available"); - if (maxCores > 0) { - noOfCores = Math.min(maxCores, noOfCores); - log("Limited processors to "+noOfCores); - } - int noOfFiles = targetsForConfig.size(); - if (noOfFiles < noOfCores) { - noOfCores = noOfFiles; - log("Limited used processors to "+noOfCores); - } - - Set[] sourceFiles = new HashSet[noOfCores]; - for (int j = 0; j < sourceFiles.length; j++) { - sourceFiles[j] = new HashSet(noOfFiles - / sourceFiles.length); - } - Enumeration targetsEnum = targetsForConfig.elements(); - index = 0; - while (targetsEnum.hasMoreElements()) { - TargetInfo targetInfo = ((TargetInfo) targetsEnum - .nextElement()); - sourceFiles[index++].add(targetInfo.getSources()[0] - .toString()); - index %= sourceFiles.length; - } - - // setup cores/cpus - Core[] cores = new Core[noOfCores]; - for (int j = 0; j < cores.length; j++) { - cores[j] = new Core(this, j, config, _objDir, sourceFiles[j], - relentless, monitor); - log("\nStarting Core " + j + " with " - + sourceFiles[j].size() + " source files..."); - } - - // starting cores - for (int j = 0; j < cores.length; j++) { - cores[j].start(); - } - - // checking cores - boolean alive = false; - try { - do { - alive = false; - for (int j = 0; j < cores.length; j++) { - if (cores[j] != null) { - if (cores[j].isAlive()) { - alive = true; - } else { - Exception exception = cores[j].getException(); - if (exception != null) { - if ((compileException == null) && (exception instanceof BuildException)) { - compileException = (BuildException)exception; - } else { - log(cores[j].getName()+" "+exception+" ", Project.MSG_ERR); - } - if (!relentless) { - cores[j] = null; - alive = false; - break; - } - } - cores[j] = null; - } - } - } - if (alive) { - // wait for a maximum of 5 seconds or #files*2 seconds. - Thread.sleep(Math.min(5000, sourceFiles[0].size()*2000)); - } - } while (alive); - } catch (InterruptedException e) { - break; - } - - // killing leftovers - for (int j = 0; j < cores.length; j++) { - if (cores[j] != null) { - cores[j].interrupt(); - log(cores[j].getName()+" interrupted "); - } - } - - if ((!relentless) && (compileException != null)) { - break; + private static class SystemLibraryCollector implements FileVisitor { + private Hashtable libraries; + private Linker linker; + public SystemLibraryCollector(Linker linker, Hashtable libraries) { + this.linker = linker; + this.libraries = libraries; + } + public void visit(File basedir, String filename) { + if (linker.bid(filename) > 0) { + File libfile = new File(basedir, filename); + String key = linker.getLibraryKey(libfile); + libraries.put(key, libfile); + } + } + } + + private static class ProjectFileCollector implements FileVisitor { + private final List files; + /** + * Creates a new ProjectFileCollector. + * @param files vector for collected files. + */ + public ProjectFileCollector(List files) { + this.files = files; + } + /** + * Called for each file to be considered for collection. + * @param parentDir parent directory + * @param filename filename within directory + */ + public void visit(File parentDir, String filename) { + files.add(new File(parentDir, filename)); + } + } + + private static final ProcessorConfiguration[] EMPTY_CONFIG_ARRAY = new ProcessorConfiguration[0]; + /** + * Builds a Hashtable to targets needing to be rebuilt keyed by compiler + * configuration + */ + public static Hashtable getTargetsToBuildByConfiguration(Hashtable targets) { + Hashtable targetsByConfig = new Hashtable(); + Enumeration targetEnum = targets.elements(); + while (targetEnum.hasMoreElements()) { + TargetInfo target = (TargetInfo) targetEnum.nextElement(); + if (target.getRebuild()) { + Vector targetsForSameConfig = (Vector) targetsByConfig + .get(target.getConfiguration()); + if (targetsForSameConfig != null) { + targetsForSameConfig.addElement(target); + } else { + targetsForSameConfig = new Vector(); + targetsForSameConfig.addElement(target); + targetsByConfig.put(target.getConfiguration(), + targetsForSameConfig); + } + } + } + return targetsByConfig; + } + // FREEHEP + private int maxCores = 0; + /** The compiler definitions. */ + private Vector _compilers = new Vector(); + /** The output file type. */ + // private LinkType _linkType = LinkType.EXECUTABLE; + /** The library sets. */ + private Vector _libsets = new Vector(); + /** The linker definitions. */ + private Vector _linkers = new Vector(); + /** The object directory. */ + private File _objDir; + /** The output file. */ + private File _outfile; + /** The linker definitions. */ + private final Vector targetPlatforms = new Vector(); + /** The distributer definitions. */ + private Vector distributers = new Vector(); + private final Vector versionInfos = new Vector(); + private final Vector projects = new Vector(); + private boolean projectsOnly = false; + + + /** + * If true, stop build on compile failure. + */ + protected boolean failOnError = true; + + /** + * Content that appears in <cc>and also in <compiler>are maintained by a + * captive CompilerDef instance + */ + private final CompilerDef compilerDef = new CompilerDef(); + /** The OS390 dataset to build to object to */ + private String dataset; + /** + * + * Depth of dependency checking + * + * Values < 0 indicate full dependency checking Values >= 0 indicate + * partial dependency checking and for superficial compilation checks. Will + * throw BuildException before attempting link + */ + private int dependencyDepth = -1; + /** + * Content that appears in <cc>and also in <linker>are maintained by a + * captive CompilerDef instance + */ + private final LinkerDef linkerDef = new LinkerDef(); + /** + * contains the subsystem, output type and + * + */ + private final LinkType linkType = new LinkType(); + /** + * The property name which will be set with the physical filename of the + * file that is generated by the linker + */ + private String outputFileProperty; + /** + * if relentless = true, compilations should attempt to compile as many + * files as possible before throwing a BuildException + */ + private boolean relentless; + public CCTask() { + } + /** + * Adds a compiler definition or reference. + * + * @param compiler + * compiler + * @throws NullPointerException + * if compiler is null + */ + public void addConfiguredCompiler(CompilerDef compiler) { + if (compiler == null) { + throw new NullPointerException("compiler"); + } + compiler.setProject(getProject()); + _compilers.addElement(compiler); + } + /** + * Adds a compiler command-line arg. Argument will be inherited by all + * nested compiler elements that do not have inherit="false". + * + */ + public void addConfiguredCompilerArg(CompilerArgument arg) { + compilerDef.addConfiguredCompilerArg(arg); + } + /** + * Adds a defineset. Will be inherited by all compiler elements that do not + * have inherit="false". + * + * @param defs + * Define set + */ + public void addConfiguredDefineset(DefineSet defs) { + compilerDef.addConfiguredDefineset(defs); + } + /** + * Adds a linker definition. The first linker that is not disqualified by + * its "if" and "unless" attributes will perform the link. If no child + * linker element is active, the linker implied by the cc elements name or + * classname attribute will be used. + * + * @param linker + * linker + * @throws NullPointerException + * if linker is null + */ + public void addConfiguredLinker(LinkerDef linker) { + if (linker == null) { + throw new NullPointerException("linker"); + } + linker.setProject(getProject()); + _linkers.addElement(linker); + } + /** + * Adds a linker command-line arg. Argument will be inherited by all nested + * linker elements that do not have inherit="false". + */ + public void addConfiguredLinkerArg(LinkerArgument arg) { + linkerDef.addConfiguredLinkerArg(arg); + } + /** + * Add an environment variable to the launched process. + */ + public void addEnv(Environment.Variable var) { + compilerDef.addEnv(var); + linkerDef.addEnv(var); + } + /** + * Adds a source file set. + * + * Files in these filesets will be auctioned to the available compiler + * configurations, with the default compiler implied by the cc element + * bidding last. If no compiler is interested in the file, it will be + * passed to the linker. + * + * To have a file be processed by a particular compiler configuration, add + * a fileset to the corresponding compiler element. + */ + public void addFileset(ConditionalFileSet srcSet) { + compilerDef.addFileset(srcSet); + } + /** + * Adds a library set. + * + * Library sets will be inherited by all linker elements that do not have + * inherit="false". + * + * @param libset + * library set + * @throws NullPointerException + * if libset is null. + */ + public void addLibset(LibrarySet libset) { + if (libset == null) { + throw new NullPointerException("libset"); + } + linkerDef.addLibset(libset); + } + /** + * Adds a system library set. Timestamps and locations of system library + * sets are not used in dependency analysis. + * + * Essential libraries (such as C Runtime libraries) should not be + * specified since the task will attempt to identify the correct libraries + * based on the multithread, debug and runtime attributes. + * + * System library sets will be inherited by all linker elements that do not + * have inherit="false". + * + * @param libset + * library set + * @throws NullPointerException + * if libset is null. + */ + public void addSyslibset(SystemLibrarySet libset) { + if (libset == null) { + throw new NullPointerException("libset"); + } + linkerDef.addSyslibset(libset); + } + /** + * Specifies the generation of IDE project file. Experimental. + * @param projectDef project file generation specification + */ + public void addProject(final ProjectDef projectDef) { + if (projectDef == null) { + throw new NullPointerException("projectDef"); + } + projects.addElement(projectDef); + } + public void setProjectsOnly(final boolean value) { + projectsOnly = value; + } + /** + * Checks all targets that are not forced to be rebuilt or are missing + * object files to be checked for modified include files + * + * @return total number of targets to be rebuilt + * + */ + protected int checkForChangedIncludeFiles(Hashtable targets) { + int potentialTargets = 0; + int definiteTargets = 0; + Enumeration targetEnum = targets.elements(); + while (targetEnum.hasMoreElements()) { + TargetInfo target = (TargetInfo) targetEnum.nextElement(); + if (!target.getRebuild()) { + potentialTargets++; + } else { + definiteTargets++; + } + } + // + // If there were remaining targets that + // might be out of date + // + if (potentialTargets > 0) { + log("Starting dependency analysis for " + + Integer.toString(potentialTargets) + " files."); + DependencyTable dependencyTable = new DependencyTable(_objDir); + try { + dependencyTable.load(); + } catch (Exception ex) { + log("Problem reading dependencies.xml: " + ex.toString()); + } + targetEnum = targets.elements(); + while (targetEnum.hasMoreElements()) { + TargetInfo target = (TargetInfo) targetEnum.nextElement(); + if (!target.getRebuild()) { + if (dependencyTable.needsRebuild(this, target, + dependencyDepth)) { + target.mustRebuild(); + } + } + } + dependencyTable.commit(this); + } + // + // count files being rebuilt now + // + int currentTargets = 0; + targetEnum = targets.elements(); + while (targetEnum.hasMoreElements()) { + TargetInfo target = (TargetInfo) targetEnum.nextElement(); + if (target.getRebuild()) { + currentTargets++; + } + } + if (potentialTargets > 0) { + log(Integer.toString(potentialTargets - currentTargets + + definiteTargets) + + " files are up to date."); + log(Integer.toString(currentTargets - definiteTargets) + + " files to be recompiled from dependency analysis."); + } + log(Integer.toString(currentTargets) + " total files to be compiled."); + return currentTargets; + } + protected LinkerConfiguration collectExplicitObjectFiles( + Vector objectFiles, Vector sysObjectFiles, VersionInfo versionInfo) { + // + // find the first eligible linker + // + // + ProcessorConfiguration linkerConfig = null; + LinkerDef selectedLinkerDef = null; + Linker selectedLinker = null; + Hashtable sysLibraries = new Hashtable(); + TargetDef targetPlatform = getTargetPlatform(); + FileVisitor objCollector = null; + FileVisitor sysLibraryCollector = null; + for (int i = 0; i < _linkers.size(); i++) { + LinkerDef currentLinkerDef = (LinkerDef) _linkers.elementAt(i); + if (currentLinkerDef.isActive()) { + selectedLinkerDef = currentLinkerDef; + selectedLinker = currentLinkerDef.getProcessor().getLinker( + linkType); + // + // skip the linker if it doesn't know how to + // produce the specified link type + if (selectedLinker != null) { + linkerConfig = currentLinkerDef.createConfiguration(this, + linkType, linkerDef, targetPlatform, versionInfo); + if (linkerConfig != null) { + // + // create collectors for object files + // and system libraries + objCollector = new ObjectFileCollector(selectedLinker, + objectFiles); + sysLibraryCollector = new SystemLibraryCollector( + selectedLinker, sysLibraries); + // + // if the <linker> has embedded <fileset>'s + // (such as linker specific libraries) + // add them as object files. + // + if (currentLinkerDef.hasFileSets()) { + currentLinkerDef.visitFiles(objCollector); + } + // + // user libraries are just a specialized form + // of an object fileset + selectedLinkerDef.visitUserLibraries(selectedLinker, + objCollector); + } + break; + } + } + } + if (linkerConfig == null) { + linkerConfig = linkerDef.createConfiguration(this, linkType, null, targetPlatform, versionInfo); + selectedLinker = (Linker) linkerDef.getProcessor().getLinker( + linkType); + objCollector = new ObjectFileCollector(selectedLinker, objectFiles); + sysLibraryCollector = new SystemLibraryCollector(selectedLinker, + sysLibraries); + } + // + // unless there was a <linker> element that + // explicitly did not inherit files from + // containing <cc> element + if (selectedLinkerDef == null || selectedLinkerDef.getInherit()) { + linkerDef.visitUserLibraries(selectedLinker, objCollector); + linkerDef.visitSystemLibraries(selectedLinker, sysLibraryCollector); + } + // + // if there was a <syslibset> in a nested <linker> + // evaluate it last so it takes priority over + // identically named libs from <cc> element + // + if (selectedLinkerDef != null) { + // + // add any system libraries to the hashtable + // done in reverse order so the earliest + // on the classpath takes priority + selectedLinkerDef.visitSystemLibraries(selectedLinker, + sysLibraryCollector); + } + // + // copy over any system libraries to the + // object files vector + // + Enumeration sysLibEnum = sysLibraries.elements(); + while (sysLibEnum.hasMoreElements()) { + sysObjectFiles.addElement(sysLibEnum.nextElement()); + } + return (LinkerConfiguration) linkerConfig; + } + /** + * Adds an include path. + * + * Include paths will be inherited by nested compiler elements that do not + * have inherit="false". + */ + public IncludePath createIncludePath() { + return compilerDef.createIncludePath(); + } + /** + * Specifies precompilation prototype file and exclusions. Inherited by all + * compilers that do not have inherit="false". + * + */ + public PrecompileDef createPrecompile() throws BuildException { + return compilerDef.createPrecompile(); + } + /** + * Adds a system include path. Locations and timestamps of files located + * using the system include paths are not used in dependency analysis. + * + * + * Standard include locations should not be specified. The compiler + * adapters should recognized the settings from the appropriate environment + * variables or configuration files. + * + * System include paths will be inherited by nested compiler elements that + * do not have inherit="false". + */ + public SystemIncludePath createSysIncludePath() { + return compilerDef.createSysIncludePath(); + } + /** + * Executes the task. Compiles the given files. + * + * @throws BuildException + * if someting goes wrong with the build + */ + public void execute() throws BuildException { + // + // if link type allowed objdir to be defaulted + // provide it from outfile + if (_objDir == null) { + if(_outfile != null) { + _objDir = new File(_outfile.getParent()); + } else { + _objDir = new File("."); + } + } + + // + // if the object directory does not exist + // + if (!_objDir.exists()) { + throw new BuildException("Object directory does not exist"); + } + TargetHistoryTable objHistory = new TargetHistoryTable(this, _objDir); + + // + // get the first active version info + // + VersionInfo versionInfo = null; + Enumeration versionEnum = versionInfos.elements(); + while (versionEnum.hasMoreElements()) { + versionInfo = (VersionInfo) versionEnum.nextElement(); + versionInfo = versionInfo.merge(); + if (versionInfo.isActive()) { + break; + } else { + versionInfo = null; + } + } + + + // + // determine the eventual linker configuration + // (may be null) and collect any explicit + // object files or libraries + Vector objectFiles = new Vector(); + Vector sysObjectFiles = new Vector(); + LinkerConfiguration linkerConfig = collectExplicitObjectFiles( + objectFiles, sysObjectFiles, versionInfo); + + + // + // Assemble hashtable of all files + // that we know how to compile (keyed by output file name) + // + Hashtable targets = getTargets(linkerConfig, objectFiles, versionInfo, _outfile); + TargetInfo linkTarget = null; + // + // if output file is not specified, + // then skip link step + // + if (_outfile != null) { + linkTarget = getLinkTarget(linkerConfig, objectFiles, + sysObjectFiles, targets, versionInfo); + } + + if (projects.size() > 0) { + ArrayList files = new ArrayList(); + ProjectFileCollector matcher = new ProjectFileCollector(files); + for (int i = 0; i < _compilers.size(); i++) { + CompilerDef currentCompilerDef = (CompilerDef) _compilers + .elementAt(i); + if (currentCompilerDef.isActive()) { + if (currentCompilerDef.hasFileSets()) { + currentCompilerDef.visitFiles(matcher); + } + } + } + compilerDef.visitFiles(matcher); + + + Enumeration iter = projects.elements(); + while (iter.hasMoreElements()) { + ProjectDef projectDef = (ProjectDef) iter.nextElement(); + if (projectDef.isActive()) { + projectDef.execute(this, files, targets, linkTarget); + } + } + } + if (projectsOnly) return; + + + + // + // mark targets that don't have a history record or + // whose source last modification time is not + // the same as the history to be rebuilt + // + objHistory.markForRebuild(targets); + CCTaskProgressMonitor monitor = new CCTaskProgressMonitor(objHistory, versionInfo); + // + // check for changed include files + // + int rebuildCount = checkForChangedIncludeFiles(targets); + if (rebuildCount > 0) { + BuildException compileException = null; + // + // compile all targets with getRebuild() == true + // + Hashtable targetsByConfig = getTargetsToBuildByConfiguration(targets); + // + // build array containing Vectors with precompiled generation + // steps going first + // + Vector[] targetVectors = new Vector[targetsByConfig.size()]; + int index = 0; + Enumeration targetVectorEnum = targetsByConfig.elements(); + while (targetVectorEnum.hasMoreElements()) { + Vector targetsForConfig = (Vector) targetVectorEnum + .nextElement(); + // + // get the configuration from the first entry + // + CompilerConfiguration config = (CompilerConfiguration) ((TargetInfo) targetsForConfig + .elementAt(0)).getConfiguration(); + if (config.isPrecompileGeneration()) { + targetVectors[index++] = targetsForConfig; + } + } + targetVectorEnum = targetsByConfig.elements(); + while (targetVectorEnum.hasMoreElements()) { + Vector targetsForConfig = (Vector) targetVectorEnum + .nextElement(); + for (int i = 0; i < targetVectors.length; i++) { + if (targetVectors[i] == targetsForConfig) { + break; + } + if (targetVectors[i] == null) { + targetVectors[i] = targetsForConfig; + break; + } + } + } + // BEGINFREEHEP + Progress progress = new Progress(getObjdir(), rebuildCount); + progress.start(); + // ENDFREEHEP + + for (int i = 0; i < targetVectors.length; i++) { + // + // get the targets for this configuration + // + Vector targetsForConfig = targetVectors[i]; + // + // get the configuration from the first entry + // + CompilerConfiguration config = (CompilerConfiguration) ((TargetInfo) targetsForConfig + .elementAt(0)).getConfiguration(); + // + // prepare the list of source files + // + + // BEGINFREEHEP + int noOfCores = Runtime.getRuntime().availableProcessors(); + log("Found "+noOfCores+" processors available"); + if (maxCores > 0) { + noOfCores = Math.min(maxCores, noOfCores); + log("Limited processors to "+noOfCores); + } + int noOfFiles = targetsForConfig.size(); + if (noOfFiles < noOfCores) { + noOfCores = noOfFiles; + log("Limited used processors to "+noOfCores); + } + + Set[] sourceFiles = new HashSet[noOfCores]; + for (int j = 0; j < sourceFiles.length; j++) { + sourceFiles[j] = new HashSet(noOfFiles + / sourceFiles.length); + } + Enumeration targetsEnum = targetsForConfig.elements(); + index = 0; + while (targetsEnum.hasMoreElements()) { + TargetInfo targetInfo = ((TargetInfo) targetsEnum + .nextElement()); + sourceFiles[index++].add(targetInfo.getSources()[0] + .toString()); + index %= sourceFiles.length; + } + + // setup cores/cpus + Core[] cores = new Core[noOfCores]; + for (int j = 0; j < cores.length; j++) { + cores[j] = new Core(this, j, config, _objDir, sourceFiles[j], + relentless, monitor); + log("\nStarting Core " + j + " with " + + sourceFiles[j].size() + " source files..."); + } + + // starting cores + for (int j = 0; j < cores.length; j++) { + cores[j].start(); + } + + // checking cores + boolean alive = false; + try { + do { + alive = false; + for (int j = 0; j < cores.length; j++) { + if (cores[j] != null) { + if (cores[j].isAlive()) { + alive = true; + } else { + Exception exception = cores[j].getException(); + if (exception != null) { + if ((compileException == null) && (exception instanceof BuildException)) { + compileException = (BuildException)exception; + } else { + log(cores[j].getName()+" "+exception+" ", Project.MSG_ERR); + } + if (!relentless) { + cores[j] = null; + alive = false; + break; + } + } + cores[j] = null; } - // ENDFREEHEP - } - - // BEGINFREEHEP - progress.exit(); - try { - progress.join(); - } catch (InterruptedException ex) { - } - - // ENDFREEHEP - - // - // save the details of the object file compilation - // settings to disk for dependency analysis - // - try { - objHistory.commit(); - } catch (IOException ex) { - this.log("Error writing history.xml: " + ex.toString()); - } - // - // if we threw a compile exception and - // didn't throw it at the time because - // we were relentless then - // save the history and - // throw the exception - // - if (compileException != null) { - if (failOnError) { - throw compileException; - } else { - log(compileException.getMessage(), Project.MSG_ERR); - return; - } - } - } - // - // if the dependency tree was not fully - // evaluated, then throw an exception - // since we really didn't do what we - // should have done - // - // - if (dependencyDepth >= 0) { - throw new BuildException( - "All files at depth " - + Integer.toString(dependencyDepth) - + " from changes successfully compiled.\n" - + "Remove or change dependencyDepth to -1 to perform full compilation."); - } - // - // if no link target then - // commit the history for the object files - // and leave the task - if (linkTarget != null) { - // - // get the history for the link target (may be the same - // as the object history) - TargetHistoryTable linkHistory = getLinkHistory(objHistory); - // - // see if it needs to be rebuilt - // - linkHistory.markForRebuild(linkTarget); - // - // if it needs to be rebuilt, rebuild it - // - File output = linkTarget.getOutput(); - if (linkTarget.getRebuild()) { - LinkerConfiguration linkConfig = (LinkerConfiguration) linkTarget - .getConfiguration(); - // BEGINFREEHEP - log("Linking..."); - log("Starting link {" + linkConfig.getIdentifier() + "}"); - // ENDFREEHEP - if (failOnError) { - linkConfig.link(this, linkTarget); - } else { - try { - linkConfig.link(this, linkTarget); - } catch (BuildException ex) { - log(ex.getMessage(), Project.MSG_ERR); - return; - } - } - if (outputFileProperty != null) - getProject().setProperty(outputFileProperty, - output.getAbsolutePath()); - linkHistory.update(linkTarget); - try { - linkHistory.commit(); - } catch (IOException ex) { - log("Error writing link history.xml: " + ex.toString()); - } - } else { - if (outputFileProperty != null) - getProject().setProperty(outputFileProperty, - output.getAbsolutePath()); - } - } - } - - // BEGINFREEHEP - class Core extends Thread { - private CCTask task; - private CompilerConfiguration config; - private File objDir; - private Set sourceFiles; - private boolean relentless; - private CCTaskProgressMonitor monitor; - private Exception compileException; - - Core(CCTask task, int coreNo, CompilerConfiguration config, File objDir, - Set set, boolean relentless, - CCTaskProgressMonitor monitor) { - super("Core "+coreNo); - this.task = task; - this.config = config; - this.objDir = objDir; - this.sourceFiles = set; - this.relentless = relentless; - this.monitor = monitor; - } - - public Exception getException() { - return compileException; - } - - public void run() { - super.run(); - try { - String[] sources = new String[sourceFiles.size()]; - sources = (String[]) sourceFiles.toArray(sources); - config.compile(task, objDir, sources, relentless, monitor); - } catch (Exception ex) { - if (compileException == null) { - compileException = ex; - } - } - } - } - - // ENDFREEHEP - - // BEGINFREEHEP - class Progress extends Thread { - - private boolean stop = false; - private File objDir; - private int rebuildCount; - - public Progress(File objDir, int rebuildCount) { - this.objDir = objDir; - this.rebuildCount = rebuildCount; - } - - public void run() { - if (rebuildCount < 10) - return; - try { - FileFilter updatedFiles = new FileFilter() { - private long startTime = System.currentTimeMillis(); - - public boolean accept(File file) { - return file.lastModified() > startTime - && !file.getName().endsWith(".xml"); - } - }; - while (!stop) { - System.err.print("\r" - + objDir.listFiles(updatedFiles).length + " / " - + rebuildCount + " files compiled..."); - System.err.print("\r"); - System.err.flush(); - if (!stop) { - Thread.sleep(5000); - } - } - } catch (InterruptedException e) { - } - System.err - .print("\r "); - System.err.print("\r"); - System.err.flush(); - log(Integer.toString(rebuildCount) + " files were compiled."); - } - - public void exit() { - stop = true; - } - - } - - // ENDFREEHEP - - /** - * Gets the dataset. - * - * @return Returns a String - */ - public String getDataset() { - return dataset; - } - - protected TargetHistoryTable getLinkHistory(TargetHistoryTable objHistory) { - File outputFileDir = new File(_outfile.getParent()); - // - // if the output file is being produced in the link - // directory, then we can use the same history file - // - if (_objDir.equals(outputFileDir)) { - return objHistory; - } - return new TargetHistoryTable(this, outputFileDir); - } - - protected TargetInfo getLinkTarget(LinkerConfiguration linkerConfig, - Vector objectFiles, Vector sysObjectFiles, + } + } + if (alive) { + // wait for a maximum of 5 seconds or #files*2 seconds. + Thread.sleep(Math.min(5000, sourceFiles[0].size()*2000)); + } + } while (alive); + } catch (InterruptedException e) { + break; + } + + // killing leftovers + for (int j = 0; j < cores.length; j++) { + if (cores[j] != null) { + cores[j].interrupt(); + log(cores[j].getName()+" interrupted "); + } + } + + if ((!relentless) && (compileException != null)) { + break; + } + // ENDFREEHEP + + + /* OLD CODE + String[] sourceFiles = new String[targetsForConfig.size()]; + Enumeration targetsEnum = targetsForConfig.elements(); + index = 0; + while (targetsEnum.hasMoreElements()) { + TargetInfo targetInfo = ((TargetInfo) targetsEnum + .nextElement()); + sourceFiles[index++] = targetInfo.getSources()[0] + .toString(); + } + try { + config.compile(this, _objDir, sourceFiles, relentless, + monitor); + } catch (BuildException ex) { + if (compileException == null) { + compileException = ex; + } + if (!relentless) + break; + } + */ + } + + // BEGINFREEHEP + progress.exit(); + try { + progress.join(); + } catch (InterruptedException ex) { + } + // ENDFREEHEP + + // + // save the details of the object file compilation + // settings to disk for dependency analysis + // + try { + objHistory.commit(); + } catch (IOException ex) { + this.log("Error writing history.xml: " + ex.toString()); + } + // + // if we threw a compile exception and + // didn't throw it at the time because + // we were relentless then + // save the history and + // throw the exception + // + if (compileException != null) { + if (failOnError) { + throw compileException; + } else { + log(compileException.getMessage(), Project.MSG_ERR); + return; + } + } + } + // + // if the dependency tree was not fully + // evaluated, then throw an exception + // since we really didn't do what we + // should have done + // + // + if (dependencyDepth >= 0) { + throw new BuildException( + "All files at depth " + + Integer.toString(dependencyDepth) + + " from changes successfully compiled.\n" + + "Remove or change dependencyDepth to -1 to perform full compilation."); + } + // + // if no link target then + // commit the history for the object files + // and leave the task + if (linkTarget != null) { + // + // get the history for the link target (may be the same + // as the object history) + TargetHistoryTable linkHistory = getLinkHistory(objHistory); + // + // see if it needs to be rebuilt + // + linkHistory.markForRebuild(linkTarget); + // + // if it needs to be rebuilt, rebuild it + // + File output = linkTarget.getOutput(); + if (linkTarget.getRebuild()) { + LinkerConfiguration linkConfig = (LinkerConfiguration) linkTarget + .getConfiguration(); + // BEGINFREEHEP + log("Linking..."); + log("Starting link {" + linkConfig.getIdentifier() + "}"); + // ENDFREEHEP + if (failOnError) { + linkConfig.link(this, linkTarget); + } else { + try { + linkConfig.link(this, linkTarget); + } catch(BuildException ex) { + log(ex.getMessage(), Project.MSG_ERR); + return; + } + } + if (outputFileProperty != null) + getProject().setProperty(outputFileProperty, + output.getAbsolutePath()); + linkHistory.update(linkTarget); + try { + linkHistory.commit(); + } catch (IOException ex) { + log("Error writing link history.xml: " + ex.toString()); + } + } else { + if (outputFileProperty != null) + getProject().setProperty(outputFileProperty, + output.getAbsolutePath()); + } + } + } + + // BEGINFREEHEP + class Core extends Thread { + private CCTask task; + private CompilerConfiguration config; + private File objDir; + private Set sourceFiles; + private boolean relentless; + private CCTaskProgressMonitor monitor; + private Exception compileException; + + Core(CCTask task, int coreNo, CompilerConfiguration config, File objDir, + Set set, boolean relentless, + CCTaskProgressMonitor monitor) { + super("Core "+coreNo); + this.task = task; + this.config = config; + this.objDir = objDir; + this.sourceFiles = set; + this.relentless = relentless; + this.monitor = monitor; + } + + public Exception getException() { + return compileException; + } + + public void run() { + super.run(); + try { + String[] sources = new String[sourceFiles.size()]; + sources = (String[]) sourceFiles.toArray(sources); + config.compile(task, objDir, sources, relentless, monitor); + } catch (Exception ex) { + if (compileException == null) { + compileException = ex; + } + } + } + } + + // ENDFREEHEP + + // BEGINFREEHEP + class Progress extends Thread { + + private boolean stop = false; + private File objDir; + private int rebuildCount; + + public Progress(File objDir, int rebuildCount) { + this.objDir = objDir; + this.rebuildCount = rebuildCount; + } + + public void run() { + if (rebuildCount < 10) + return; + try { + FileFilter updatedFiles = new FileFilter() { + private long startTime = System.currentTimeMillis(); + + public boolean accept(File file) { + return file.lastModified() > startTime + && !file.getName().endsWith(".xml"); + } + }; + while (!stop) { + System.err.print("\r" + + objDir.listFiles(updatedFiles).length + " / " + + rebuildCount + " files compiled..."); + System.err.print("\r"); + System.err.flush(); + if (!stop) { + Thread.sleep(5000); + } + } + } catch (InterruptedException e) { + } + System.err + .print("\r "); + System.err.print("\r"); + System.err.flush(); + log(Integer.toString(rebuildCount) + " files were compiled."); + } + + public void exit() { + stop = true; + } + + } + + // ENDFREEHEP + + + /** + * Gets the dataset. + * + * @return Returns a String + */ + public String getDataset() { + return dataset; + } + protected TargetHistoryTable getLinkHistory(TargetHistoryTable objHistory) { + File outputFileDir = new File(_outfile.getParent()); + // + // if the output file is being produced in the link + // directory, then we can use the same history file + // + if (_objDir.equals(outputFileDir)) { + return objHistory; + } + return new TargetHistoryTable(this, outputFileDir); + } + protected TargetInfo getLinkTarget(LinkerConfiguration linkerConfig, + Vector objectFiles, Vector sysObjectFiles, Hashtable compileTargets, VersionInfo versionInfo) { - // - // walk the compile phase targets and - // add those sources that have already been - // assigned to the linker or - // our output files the linker knows how to consume - // files the linker knows how to consume - // - Enumeration compileTargetsEnum = compileTargets.elements(); - while (compileTargetsEnum.hasMoreElements()) { - TargetInfo compileTarget = (TargetInfo) compileTargetsEnum - .nextElement(); - // - // output of compile tasks - // - int bid = linkerConfig.bid(compileTarget.getOutput().toString()); - if (bid > 0) { - objectFiles.addElement(compileTarget.getOutput()); - } - } - File[] objectFileArray = new File[objectFiles.size()]; - objectFiles.copyInto(objectFileArray); - File[] sysObjectFileArray = new File[sysObjectFiles.size()]; - sysObjectFiles.copyInto(sysObjectFileArray); - String baseName = _outfile.getName(); - String[] fullNames = linkerConfig.getOutputFileNames(baseName, - versionInfo); - File outputFile = new File(_outfile.getParent(), fullNames[0]); - return new TargetInfo(linkerConfig, objectFileArray, - sysObjectFileArray, outputFile, linkerConfig.getRebuild()); - } - - public File getObjdir() { - return _objDir; - } - - public File getOutfile() { - return _outfile; - } - - public TargetDef getTargetPlatform() { - return null; - } - - /** - * This method collects a Hashtable, keyed by output file name, of - * TargetInfo's for every source file that is specified in the filesets of - * the <cc>and nested <compiler>elements. The TargetInfo's contain the - * appropriate compiler configurations for their possible compilation - * - */ - private Hashtable getTargets(LinkerConfiguration linkerConfig, - Vector objectFiles, VersionInfo versionInfo, File outputFile) { - Hashtable targets = new Hashtable(1000); - TargetDef targetPlatform = getTargetPlatform(); - // - // find active (specialized) compilers - // - Vector biddingProcessors = new Vector(_compilers.size()); - for (int i = 0; i < _compilers.size(); i++) { - CompilerDef currentCompilerDef = (CompilerDef) _compilers - .elementAt(i); - if (currentCompilerDef.isActive()) { - ProcessorConfiguration config = currentCompilerDef - .createConfiguration(this, linkType, compilerDef, - targetPlatform, versionInfo); - // - // see if this processor had a precompile child element - // - PrecompileDef precompileDef = currentCompilerDef - .getActivePrecompile(compilerDef); - ProcessorConfiguration[] localConfigs = new ProcessorConfiguration[] { config }; - // - // if it does then - // - if (precompileDef != null) { - File prototype = precompileDef.getPrototype(); - // - // will throw exceptions if prototype doesn't exist, etc - // - if (!prototype.exists()) { - throw new BuildException("prototype (" - + prototype.toString() + ") does not exist."); - } - if (prototype.isDirectory()) { - throw new BuildException("prototype (" - + prototype.toString() + ") is a directory."); - } - String[] exceptFiles = precompileDef.getExceptFiles(); - // - // create a precompile building and precompile using - // variants of the configuration - // or return null if compiler doesn't support - // precompilation - CompilerConfiguration[] configs = ((CompilerConfiguration) config) - .createPrecompileConfigurations(prototype, - exceptFiles); - if (configs != null && configs.length == 2) { - // - // visit the precompiled file to add it into the - // targets list (just like any other file if - // compiler doesn't support precompilation) - TargetMatcher matcher = new TargetMatcher(this, - _objDir, - new ProcessorConfiguration[] { configs[0] }, - linkerConfig, objectFiles, targets, versionInfo); - - matcher.visit(new File(prototype.getParent()), - prototype.getName()); - // - // only the configuration that uses the - // precompiled header gets added to the bidding list - biddingProcessors.addElement(configs[1]); - localConfigs = new ProcessorConfiguration[2]; - localConfigs[0] = configs[1]; - localConfigs[1] = config; - } - } - // - // if the compiler has a fileset - // then allow it to add its files - // to the set of potential targets - if (currentCompilerDef.hasFileSets()) { - TargetMatcher matcher = new TargetMatcher(this, _objDir, - localConfigs, linkerConfig, objectFiles, targets, + // + // walk the compile phase targets and + // add those sources that have already been + // assigned to the linker or + // our output files the linker knows how to consume + // files the linker knows how to consume + // + Enumeration compileTargetsEnum = compileTargets.elements(); + while (compileTargetsEnum.hasMoreElements()) { + TargetInfo compileTarget = (TargetInfo) compileTargetsEnum + .nextElement(); + // + // output of compile tasks + // + int bid = linkerConfig.bid(compileTarget.getOutput().toString()); + if (bid > 0) { + objectFiles.addElement(compileTarget.getOutput()); + } + } + File[] objectFileArray = new File[objectFiles.size()]; + objectFiles.copyInto(objectFileArray); + File[] sysObjectFileArray = new File[sysObjectFiles.size()]; + sysObjectFiles.copyInto(sysObjectFileArray); + String baseName = _outfile.getName(); + String[] fullNames = linkerConfig.getOutputFileNames(baseName, versionInfo); + File outputFile = new File(_outfile.getParent(), fullNames[0]); + return new TargetInfo(linkerConfig, objectFileArray, + sysObjectFileArray, outputFile, linkerConfig.getRebuild()); + } + public File getObjdir() { + return _objDir; + } + public File getOutfile() { + return _outfile; + } + + public TargetDef getTargetPlatform() { + return null; + } + /** + * This method collects a Hashtable, keyed by output file name, of + * TargetInfo's for every source file that is specified in the filesets of + * the <cc>and nested <compiler>elements. The TargetInfo's contain the + * appropriate compiler configurations for their possible compilation + * + */ + private Hashtable getTargets(LinkerConfiguration linkerConfig, + Vector objectFiles, VersionInfo versionInfo, File outputFile) { + Hashtable targets = new Hashtable(1000); + TargetDef targetPlatform = getTargetPlatform(); + // + // find active (specialized) compilers + // + Vector biddingProcessors = new Vector(_compilers.size()); + for (int i = 0; i < _compilers.size(); i++) { + CompilerDef currentCompilerDef = (CompilerDef) _compilers + .elementAt(i); + if (currentCompilerDef.isActive()) { + ProcessorConfiguration config = currentCompilerDef + .createConfiguration(this, linkType, compilerDef, + targetPlatform, versionInfo); + // + // see if this processor had a precompile child element + // + PrecompileDef precompileDef = currentCompilerDef + .getActivePrecompile(compilerDef); + ProcessorConfiguration[] localConfigs = new ProcessorConfiguration[]{config}; + // + // if it does then + // + if (precompileDef != null) { + File prototype = precompileDef.getPrototype(); + // + // will throw exceptions if prototype doesn't exist, etc + // + if (!prototype.exists()) { + throw new BuildException("prototype (" + + prototype.toString() + ") does not exist."); + } + if (prototype.isDirectory()) { + throw new BuildException("prototype (" + + prototype.toString() + ") is a directory."); + } + String[] exceptFiles = precompileDef.getExceptFiles(); + // + // create a precompile building and precompile using + // variants of the configuration + // or return null if compiler doesn't support + // precompilation + CompilerConfiguration[] configs = ((CompilerConfiguration) config) + .createPrecompileConfigurations(prototype, + exceptFiles); + if (configs != null && configs.length == 2) { + // + // visit the precompiled file to add it into the + // targets list (just like any other file if + // compiler doesn't support precompilation) + TargetMatcher matcher = new TargetMatcher(this, + _objDir, + new ProcessorConfiguration[]{configs[0]}, + linkerConfig, objectFiles, targets, versionInfo); + + matcher.visit(new File(prototype.getParent()), + prototype.getName()); + // + // only the configuration that uses the + // precompiled header gets added to the bidding list + biddingProcessors.addElement(configs[1]); + localConfigs = new ProcessorConfiguration[2]; + localConfigs[0] = configs[1]; + localConfigs[1] = config; + } + } + // + // if the compiler has a fileset + // then allow it to add its files + // to the set of potential targets + if (currentCompilerDef.hasFileSets()) { + TargetMatcher matcher = new TargetMatcher(this, _objDir, + localConfigs, linkerConfig, objectFiles, targets, versionInfo); - currentCompilerDef.visitFiles(matcher); - } - biddingProcessors.addElement(config); - } - } - // - // add fallback compiler at the end - // - ProcessorConfiguration config = compilerDef.createConfiguration(this, - linkType, null, targetPlatform, versionInfo); - biddingProcessors.addElement(config); - ProcessorConfiguration[] bidders = new ProcessorConfiguration[biddingProcessors - .size()]; - biddingProcessors.copyInto(bidders); - // - // bid out the <fileset>'s in the cctask - // - TargetMatcher matcher = new TargetMatcher(this, _objDir, bidders, - linkerConfig, objectFiles, targets, versionInfo); - compilerDef.visitFiles(matcher); - - if (outputFile != null && versionInfo != null) { - boolean isDebug = linkerConfig.isDebug(); - try { - linkerConfig.getLinker().addVersionFiles(versionInfo, linkType, - outputFile, isDebug, _objDir, matcher); - } catch (IOException ex) { - throw new BuildException(ex); - } - } - return targets; - } - - /** - * Sets the default compiler adapter. Use the "name" attribute when the - * compiler is a supported compiler. - * - * @param classname - * fully qualified classname which implements CompilerAdapter - */ - public void setClassname(String classname) { - compilerDef.setClassname(classname); - linkerDef.setClassname(classname); - } - - /** - * Sets the dataset for OS/390 builds. - * - * @param dataset - * The dataset to set - */ - public void setDataset(String dataset) { - this.dataset = dataset; - } - - /** - * Enables or disables generation of debug info. - */ - public void setDebug(boolean debug) { - compilerDef.setDebug(debug); - linkerDef.setDebug(debug); - } - - /** - * Gets debug state. - * - * @return true if building for debugging - */ - public boolean getDebug() { - return compilerDef.getDebug(null, 0); - } - - /** - * Deprecated. - * - * Controls the depth of the dependency evaluation. Used to do a quick check - * of changes before a full build. - * - * Any negative value which will perform full dependency checking. Positive - * values will truncate dependency checking. A value of 0 will cause only - * those files that changed to be recompiled, a value of 1 which cause files - * that changed or that explicitly include a file that changed to be - * recompiled. - * - * Any non-negative value will cause a BuildException to be thrown before - * attempting a link or completing the task. - * - */ - public void setDependencyDepth(int depth) { - dependencyDepth = depth; - } - - /** - * Enables generation of exception handling code - */ - public void setExceptions(boolean exceptions) { - compilerDef.setExceptions(exceptions); - } - - /** - * Enables run-time type information. - */ - public void setRtti(boolean rtti) { - compilerDef.setRtti(rtti); - } - - // public LinkType getLinkType() { - // return linkType; - // } - /** - * Enables or disables incremental linking. - * - * @param incremental - * new state - */ - public void setIncremental(boolean incremental) { - linkerDef.setIncremental(incremental); - } - - /** - * Set use of libtool. - * - * If set to true, the "libtool " will be prepended to the command line for - * compatible processors - * - * @param libtool - * If true, use libtool. - */ - public void setLibtool(boolean libtool) { - compilerDef.setLibtool(libtool); - linkerDef.setLibtool(libtool); - } - - /** - * Sets the output file type. Supported values "executable", "shared", and - * "static". Deprecated, specify outtype instead. - * - * @deprecated - */ - public void setLink(OutputTypeEnum outputType) { - linkType.setOutputType(outputType); - } - - // BEGINFREEHEP - public void setLinkCPP(boolean linkCPP) { - linkType.setLinkCPP(linkCPP); - } - - public void setLinkFortran(boolean linkFortran) { - linkType.setLinkFortran(linkFortran); - } - - // ENDFREEHEP - /** - * Enables or disables generation of multithreaded code - * - * @param multi - * If true, generated code may be multithreaded. - */ - public void setMultithreaded(boolean multi) { - compilerDef.setMultithreaded(multi); - } - - // - // keep near duplicate comment at CompilerDef.setName in sync - // - /** - * Sets type of the default compiler and linker. - * - * <table width="100%" border="1"> <thead>Supported compilers </thead> - * <tr> - * <td>gcc (default)</td> - * <td>GCC C++ compiler</td> - * </tr> - * <tr> - * <td>g++</td> - * <td>GCC C++ compiler</td> - * </tr> - * <tr> - * <td>c++</td> - * <td>GCC C++ compiler</td> - * </tr> - * <tr> - * <td>g77</td> - * <td>GNU FORTRAN compiler</td> - * </tr> - * <tr> - * <td>msvc</td> - * <td>Microsoft Visual C++</td> - * </tr> - * <tr> - * <td>bcc</td> - * <td>Borland C++ Compiler</td> - * </tr> - * <tr> - * <td>msrc</td> - * <td>Microsoft Resource Compiler</td> - * </tr> - * <tr> - * <td>brc</td> - * <td>Borland Resource Compiler</td> - * </tr> - * <tr> - * <td>df</td> - * <td>Compaq Visual Fortran Compiler</td> - * </tr> - * <tr> - * <td>midl</td> - * <td>Microsoft MIDL Compiler</td> - * </tr> - * <tr> - * <td>icl</td> - * <td>Intel C++ compiler for Windows (IA-32)</td> - * </tr> - * <tr> - * <td>ecl</td> - * <td>Intel C++ compiler for Windows (IA-64)</td> - * </tr> - * <tr> - * <td>icc</td> - * <td>Intel C++ compiler for Linux (IA-32)</td> - * </tr> - * <tr> - * <td>ecc</td> - * <td>Intel C++ compiler for Linux (IA-64)</td> - * </tr> - * <tr> - * <td>CC</td> - * <td>Sun ONE C++ compiler</td> - * </tr> - * <tr> - * <td>aCC</td> - * <td>HP aC++ C++ Compiler</td> - * </tr> - * <tr> - * <td>os390</td> - * <td>OS390 C Compiler</td> - * </tr> - * <tr> - * <td>os400</td> - * <td>Icc Compiler</td> - * </tr> - * <tr> - * <td>sunc89</td> - * <td>Sun C89 C Compiler</td> - * </tr> - * <tr> - * <td>xlC</td> - * <td>VisualAge C Compiler</td> - * </tr> - * <tr> - * <td>uic</td> - * <td>Qt user interface compiler (creates .h, .cpp and moc_*.cpp files).</td> - * </tr> - * <tr> - * <td>moc</td> - * <td>Qt meta-object compiler</td> - * </tr> - * <tr> - * <td>xpidl</td> - * <td>Mozilla xpidl compiler (creates .h and .xpt files).</td> - * </tr> - * <tr> - * <td>wcl</td> - * <td>OpenWatcom C/C++ compiler</td> - * </tr> - * <tr> - * <td>wfl</td> - * <td>OpenWatcom FORTRAN compiler</td> - * </tr> - * </table> - * - */ - public void setName(CompilerEnum name) { - compilerDef.setName(name); - Processor compiler = compilerDef.getProcessor(); - Linker linker = compiler.getLinker(linkType); - linkerDef.setProcessor(linker); - } - - /** - * Do not propagate old environment when new environment variables are - * specified. - */ - public void setNewenvironment(boolean newenv) { - compilerDef.setNewenvironment(newenv); - linkerDef.setNewenvironment(newenv); - } - - /** - * Sets the destination directory for object files. - * - * Generally this should be a property expression that evaluates to distinct - * debug and release object file directories. - * - * @param dir - * object directory - */ - public void setObjdir(File dir) { - if (dir == null) { - throw new NullPointerException("dir"); - } - _objDir = dir; - } - - /** - * Sets the output file name. If not specified, the task will only compile - * files and not attempt to link. If an extension is not specified, the task - * may use a system appropriate extension and prefix, for example, - * outfile="example" may result in "libexample.so" being created. - * - * @param outfile - * output file name - */ - public void setOutfile(File outfile) { - // - // if file name was empty, skip link step - // - if (outfile == null || outfile.toString().length() > 0) { - _outfile = outfile; - } - } - - /** - * Specifies the name of a property to set with the physical filename that - * is produced by the linker - */ - public void setOutputFileProperty(String outputFileProperty) { - this.outputFileProperty = outputFileProperty; - } - - /** - * Sets the output file type. Supported values "executable", "shared", and - * "static". - */ - public void setOuttype(OutputTypeEnum outputType) { - linkType.setOutputType(outputType); - } - - /** - * Gets output type. - * - * @return output type - */ - public String getOuttype() { - return linkType.getOutputType(); - } - - /** - * Sets the project. - */ - public void setProject(Project project) { - super.setProject(project); - compilerDef.setProject(project); - linkerDef.setProject(project); - } - - /** - * If set to true, all files will be rebuilt. - * - * @paran rebuildAll If true, all files will be rebuilt. If false, up to - * date files will not be rebuilt. - */ - public void setRebuild(boolean rebuildAll) { - compilerDef.setRebuild(rebuildAll); - linkerDef.setRebuild(rebuildAll); - } - - /** - * If set to true, compilation errors will not stop the task until all files - * have been attempted. - * - * @param relentless - * If true, don't stop on the first compilation error - * - */ - public void setRelentless(boolean relentless) { - this.relentless = relentless; - } - - /** - * Sets the type of runtime library, possible values "dynamic", "static". - */ - public void setRuntime(RuntimeType rtlType) { - linkType.setStaticRuntime((rtlType.getIndex() == 1)); - } - - /** - * Sets the nature of the subsystem under which that the program will - * execute. - * - * <table width="100%" border="1"> <thead>Supported subsystems </thead> - * <tr> - * <td>gui</td> - * <td>Graphical User Interface</td> - * </tr> - * <tr> - * <td>console</td> - * <td>Command Line Console</td> - * </tr> - * <tr> - * <td>other</td> - * <td>Other</td> - * </tr> - * </table> - * - * @param subsystem - * subsystem - * @throws NullPointerException - * if subsystem is null - */ - public void setSubsystem(SubsystemEnum subsystem) { - if (subsystem == null) { - throw new NullPointerException("subsystem"); - } - linkType.setSubsystem(subsystem); - } - - /** - * Gets subsystem name. - * - * @return Subsystem name - */ - public String getSubsystem() { - return linkType.getSubsystem(); - } - - /** - * Enumerated attribute with the values "none", "severe", "default", - * "production", "diagnostic", and "failtask". - */ - public void setWarnings(WarningLevelEnum level) { - compilerDef.setWarnings(level); - } - - // BEGINFREEHEP - public void setMaxCores(int maxCores) { - this.maxCores = maxCores; - } - - public int getMaxCores() { - return maxCores; - } - - // ENDFREEHEP - - /** - * Indicates whether the build will continue even if there are compilation - * errors; defaults to true. - * - * @param fail - * if true halt the build on failure - */ - public void setFailonerror(boolean fail) { - failOnError = fail; - } - - /** - * Gets the failonerror flag. - * - * @return the failonerror flag - */ - public boolean getFailonerror() { - return failOnError; - } - - /** - * Adds a target definition or reference (Non-functional prototype). - * - * @param target - * target - * @throws NullPointerException - * if compiler is null - */ - public void addConfiguredTarget(TargetDef target) { - if (target == null) { - throw new NullPointerException("target"); - } - target.setProject(getProject()); - targetPlatforms.addElement(target); - } - - /** - * Adds a distributer definition or reference (Non-functional prototype). - * - * @param distributer - * distributer - * @throws NullPointerException - * if compiler is null - */ - public void addConfiguredDistributer(DistributerDef distributer) { - if (distributer == null) { - throw new NullPointerException("distributer"); - } - distributer.setProject(getProject()); - distributers.addElement(distributer); - } - - /** - * Sets optimization. - * - * @param optimization - */ - public void setOptimize(OptimizationEnum optimization) { - compilerDef.setOptimize(optimization); - } - - /** - * Adds desriptive version information to be included in the generated file. - * The first active version info block will be used. - */ - public void addConfiguredVersioninfo(VersionInfo newVersionInfo) { - newVersionInfo.setProject(this.getProject()); - versionInfos.addElement(newVersionInfo); - } - + currentCompilerDef.visitFiles(matcher); + } + biddingProcessors.addElement(config); + } + } + // + // add fallback compiler at the end + // + ProcessorConfiguration config = compilerDef.createConfiguration(this, + linkType, null, targetPlatform, versionInfo); + biddingProcessors.addElement(config); + ProcessorConfiguration[] bidders = new ProcessorConfiguration[biddingProcessors + .size()]; + biddingProcessors.copyInto(bidders); + // + // bid out the <fileset>'s in the cctask + // + TargetMatcher matcher = new TargetMatcher(this, _objDir, bidders, + linkerConfig, objectFiles, targets, versionInfo); + compilerDef.visitFiles(matcher); + + if (outputFile != null && versionInfo != null) { + boolean isDebug = linkerConfig.isDebug(); + try { + linkerConfig.getLinker().addVersionFiles(versionInfo, linkType, + outputFile, + isDebug, + _objDir, matcher); + } catch(IOException ex) { + throw new BuildException(ex); + } + } + return targets; + } + /** + * Sets the default compiler adapter. Use the "name" attribute when the + * compiler is a supported compiler. + * + * @param classname + * fully qualified classname which implements CompilerAdapter + */ + public void setClassname(String classname) { + compilerDef.setClassname(classname); + linkerDef.setClassname(classname); + } + /** + * Sets the dataset for OS/390 builds. + * + * @param dataset + * The dataset to set + */ + public void setDataset(String dataset) { + this.dataset = dataset; + } + /** + * Enables or disables generation of debug info. + */ + public void setDebug(boolean debug) { + compilerDef.setDebug(debug); + linkerDef.setDebug(debug); + } + + /** + * Gets debug state. + * @return true if building for debugging + */ + public boolean getDebug() { + return compilerDef.getDebug(null, 0); + } + + /** + * Deprecated. + * + * Controls the depth of the dependency evaluation. Used to do a quick + * check of changes before a full build. + * + * Any negative value which will perform full dependency checking. Positive + * values will truncate dependency checking. A value of 0 will cause only + * those files that changed to be recompiled, a value of 1 which cause + * files that changed or that explicitly include a file that changed to be + * recompiled. + * + * Any non-negative value will cause a BuildException to be thrown before + * attempting a link or completing the task. + * + */ + public void setDependencyDepth(int depth) { + dependencyDepth = depth; + } + /** + * Enables generation of exception handling code + */ + public void setExceptions(boolean exceptions) { + compilerDef.setExceptions(exceptions); + } + /** + * Enables run-time type information. + */ + public void setRtti(boolean rtti) { + compilerDef.setRtti(rtti); + } + // public LinkType getLinkType() { + // return linkType; + // } + /** + * Enables or disables incremental linking. + * + * @param incremental + * new state + */ + public void setIncremental(boolean incremental) { + linkerDef.setIncremental(incremental); + } + /** + * Set use of libtool. + * + * If set to true, the "libtool " will be prepended to the command line for + * compatible processors + * + * @param libtool + * If true, use libtool. + */ + public void setLibtool(boolean libtool) { + compilerDef.setLibtool(libtool); + linkerDef.setLibtool(libtool); + } + /** + * Sets the output file type. Supported values "executable", "shared", and + * "static". Deprecated, specify outtype instead. + * + * @deprecated + */ + public void setLink(OutputTypeEnum outputType) { + linkType.setOutputType(outputType); + } + + // BEGINFREEHEP + public void setLinkCPP(boolean linkCPP) { + linkType.setLinkCPP(linkCPP); + } + + public void setLinkFortran(boolean linkFortran) { + linkType.setLinkFortran(linkFortran); + } + + // ENDFREEHEP + + /** + * Enables or disables generation of multithreaded code + * + * @param multi + * If true, generated code may be multithreaded. + */ + public void setMultithreaded(boolean multi) { + compilerDef.setMultithreaded(multi); + } + // + // keep near duplicate comment at CompilerDef.setName in sync + // + /** + * Sets type of the default compiler and linker. + * + * <table width="100%" border="1"> <thead>Supported compilers </thead> + * <tr> + * <td>gcc (default)</td> + * <td>GCC C++ compiler</td> + * </tr> + * <tr> + * <td>g++</td> + * <td>GCC C++ compiler</td> + * </tr> + * <tr> + * <td>c++</td> + * <td>GCC C++ compiler</td> + * </tr> + * <tr> + * <td>g77</td> + * <td>GNU FORTRAN compiler</td> + * </tr> + * <tr> + * <td>msvc</td> + * <td>Microsoft Visual C++</td> + * </tr> + * <tr> + * <td>bcc</td> + * <td>Borland C++ Compiler</td> + * </tr> + * <tr> + * <td>msrc</td> + * <td>Microsoft Resource Compiler</td> + * </tr> + * <tr> + * <td>brc</td> + * <td>Borland Resource Compiler</td> + * </tr> + * <tr> + * <td>df</td> + * <td>Compaq Visual Fortran Compiler</td> + * </tr> + * <tr> + * <td>midl</td> + * <td>Microsoft MIDL Compiler</td> + * </tr> + * <tr> + * <td>icl</td> + * <td>Intel C++ compiler for Windows (IA-32)</td> + * </tr> + * <tr> + * <td>ecl</td> + * <td>Intel C++ compiler for Windows (IA-64)</td> + * </tr> + * <tr> + * <td>icc</td> + * <td>Intel C++ compiler for Linux (IA-32)</td> + * </tr> + * <tr> + * <td>ecc</td> + * <td>Intel C++ compiler for Linux (IA-64)</td> + * </tr> + * <tr> + * <td>CC</td> + * <td>Sun ONE C++ compiler</td> + * </tr> + * <tr> + * <td>aCC</td> + * <td>HP aC++ C++ Compiler</td> + * </tr> + * <tr> + * <td>os390</td> + * <td>OS390 C Compiler</td> + * </tr> + * <tr> + * <td>os400</td> + * <td>Icc Compiler</td> + * </tr> + * <tr> + * <td>sunc89</td> + * <td>Sun C89 C Compiler</td> + * </tr> + * <tr> + * <td>xlC</td> + * <td>VisualAge C Compiler</td> + * </tr> + * <tr> + * <td>uic</td> + * <td>Qt user interface compiler (creates .h, .cpp and moc_*.cpp files).</td> + * </tr> + * <tr> + * <td>moc</td> + * <td>Qt meta-object compiler</td> + * </tr> + * <tr> + * <td>xpidl</td> + * <td>Mozilla xpidl compiler (creates .h and .xpt files).</td> + * </tr> + * <tr> + * <td>wcl</td> + * <td>OpenWatcom C/C++ compiler</td> + * </tr> + * <tr> + * <td>wfl</td> + * <td>OpenWatcom FORTRAN compiler</td> + * </tr> + * </table> + * + */ + public void setName(CompilerEnum name) { + compilerDef.setName(name); + Processor compiler = compilerDef.getProcessor(); + Linker linker = compiler.getLinker(linkType); + linkerDef.setProcessor(linker); + } + /** + * Do not propagate old environment when new environment variables are + * specified. + */ + public void setNewenvironment(boolean newenv) { + compilerDef.setNewenvironment(newenv); + linkerDef.setNewenvironment(newenv); + } + /** + * Sets the destination directory for object files. + * + * Generally this should be a property expression that evaluates to + * distinct debug and release object file directories. + * + * @param dir + * object directory + */ + public void setObjdir(File dir) { + if (dir == null) { + throw new NullPointerException("dir"); + } + _objDir = dir; + } + /** + * Sets the output file name. If not specified, the task will only compile + * files and not attempt to link. If an extension is not specified, the + * task may use a system appropriate extension and prefix, for example, + * outfile="example" may result in "libexample.so" being created. + * + * @param outfile + * output file name + */ + public void setOutfile(File outfile) { + // + // if file name was empty, skip link step + // + if (outfile == null || outfile.toString().length() > 0) { + _outfile = outfile; + } + } + /** + * Specifies the name of a property to set with the physical filename that + * is produced by the linker + */ + public void setOutputFileProperty(String outputFileProperty) { + this.outputFileProperty = outputFileProperty; + } + /** + * Sets the output file type. Supported values "executable", "shared", and + * "static". + */ + public void setOuttype(OutputTypeEnum outputType) { + linkType.setOutputType(outputType); + } + + /** + * Gets output type. + * @return output type + */ + public String getOuttype() { + return linkType.getOutputType(); + } + + /** + * Sets the project. + */ + public void setProject(Project project) { + super.setProject(project); + compilerDef.setProject(project); + linkerDef.setProject(project); + } + /** + * If set to true, all files will be rebuilt. + * + * @param rebuildAll If true, all files will be rebuilt. If false, up to + * date files will not be rebuilt. + */ + public void setRebuild(boolean rebuildAll) { + compilerDef.setRebuild(rebuildAll); + linkerDef.setRebuild(rebuildAll); + } + /** + * If set to true, compilation errors will not stop the task until all + * files have been attempted. + * + * @param relentless + * If true, don't stop on the first compilation error + * + */ + public void setRelentless(boolean relentless) { + this.relentless = relentless; + } + /** + * Sets the type of runtime library, possible values "dynamic", "static". + */ + public void setRuntime(RuntimeType rtlType) { + linkType.setStaticRuntime((rtlType.getIndex() == 1)); + } + /** + * Sets the nature of the subsystem under which that the program will + * execute. + * + * <table width="100%" border="1"> <thead>Supported subsystems </thead> + * <tr> + * <td>gui</td> + * <td>Graphical User Interface</td> + * </tr> + * <tr> + * <td>console</td> + * <td>Command Line Console</td> + * </tr> + * <tr> + * <td>other</td> + * <td>Other</td> + * </tr> + * </table> + * + * @param subsystem + * subsystem + * @throws NullPointerException + * if subsystem is null + */ + public void setSubsystem(SubsystemEnum subsystem) { + if (subsystem == null) { + throw new NullPointerException("subsystem"); + } + linkType.setSubsystem(subsystem); + } + + /** + * Gets subsystem name. + * @return Subsystem name + */ + public String getSubsystem() { + return linkType.getSubsystem(); + } + + /** + * Enumerated attribute with the values "none", "severe", "default", + * "production", "diagnostic", and "aserror". + */ + public void setWarnings(WarningLevelEnum level) { + compilerDef.setWarnings(level); + } + + // BEGINFREEHEP + public void setMaxCores(int maxCores) { + this.maxCores = maxCores; + } + + public int getMaxCores() { + return maxCores; + } + + // ENDFREEHEP + + /** + * Indicates whether the build will continue + * even if there are compilation errors; defaults to true. + * @param fail if true halt the build on failure + */ + public void setFailonerror(boolean fail) { + failOnError = fail; + } + + /** + * Gets the failonerror flag. + * @return the failonerror flag + */ + public boolean getFailonerror() { + return failOnError; + } + /** + * Adds a target definition or reference (Non-functional prototype). + * + * @param target + * target + * @throws NullPointerException + * if compiler is null + */ + public void addConfiguredTarget(TargetDef target) { + if (target == null) { + throw new NullPointerException("target"); + } + target.setProject(getProject()); + targetPlatforms.addElement(target); + } + /** + * Adds a distributer definition or reference (Non-functional prototype). + * + * @param distributer + * distributer + * @throws NullPointerException + * if compiler is null + */ + public void addConfiguredDistributer(DistributerDef distributer) { + if (distributer == null) { + throw new NullPointerException("distributer"); + } + distributer.setProject(getProject()); + distributers.addElement(distributer); + } + /** + * Sets optimization. + * @param optimization + */ + public void setOptimize(OptimizationEnum optimization) { + compilerDef.setOptimize(optimization); + } + + /** + * Adds desriptive version information to be included in the + * generated file. The first active version info block will + * be used. + */ + public void addConfiguredVersioninfo(VersionInfo newVersionInfo) { + newVersionInfo.setProject(this.getProject()); + versionInfos.addElement(newVersionInfo); + } } diff --git a/src/main/java/net/sf/antcontrib/cpptasks/CUtil.java b/src/main/java/net/sf/antcontrib/cpptasks/CUtil.java index 2ac18e5..482593e 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/CUtil.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/CUtil.java @@ -28,10 +28,13 @@ import org.apache.tools.ant.taskdefs.Execute; import org.apache.tools.ant.taskdefs.LogStreamHandler; import org.apache.tools.ant.types.Commandline; import org.apache.tools.ant.types.Environment; +import org.apache.tools.ant.util.StringUtils; + /** * Some utilities used by the CC and Link tasks. * * @author Adam Murdoch + * @author Curt Arnold */ public class CUtil { /** @@ -178,7 +181,6 @@ public class CUtil { * @return relative path of target file. Returns targetFile if there were * no commonalities between the base and the target * - * @author Curt Arnold */ public static String getRelativePath(final String base, final File targetFile) { try { @@ -484,4 +486,38 @@ public class CUtil { public static boolean isSignificantlyAfter(long time1, long time2) { return time1 > (time2 + FILETIME_EPSILON); } + + + public static String toWindowsPath(final String path) { + if (File.separatorChar != '\\' && path.indexOf(File.separatorChar) != -1) { + return StringUtils.replace(path, File.separator, "\\"); + } + return path; + } + + public static String toUnixPath(final String path) { + if (File.separatorChar != '/' && path.indexOf(File.separatorChar) != -1) { + return StringUtils.replace(path, File.separator, "/"); + } + return path; + } + + /** + * Determines if source file has a system path, + * that is part of the compiler or platform. + * @param source source, may not be null. + * @return true is source file appears to be system library + * and its path should be discarded. + */ + public static boolean isSystemPath(final File source) { + String lcPath = source.getAbsolutePath().toLowerCase(java.util.Locale.US); + return lcPath.indexOf("platformsdk") != -1 + || lcPath.indexOf("microsoft") != -1 || + lcPath == "/usr/include" || + lcPath == "/usr/lib" || + lcPath == "/usr/local/include" || + lcPath == "/usr/local/lib"; + } + + } diff --git a/src/main/java/net/sf/antcontrib/cpptasks/CompilerDef.java b/src/main/java/net/sf/antcontrib/cpptasks/CompilerDef.java index 1bbdabf..313d3ac 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/CompilerDef.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/CompilerDef.java @@ -354,7 +354,7 @@ public final class CompilerDef extends ProcessorDef { * Enables or disables generation of multithreaded code. Unless specified, * multithreaded code generation is enabled. * - * @param multi + * @param multithreaded * If true, generated code may be multithreaded. */ public void setMultithreaded(boolean multithreaded) { @@ -483,7 +483,7 @@ public final class CompilerDef extends ProcessorDef { } /** * Enumerated attribute with the values "none", "severe", "default", - * "production", "diagnostic", and "failtask". + * "production", "diagnostic", and "aserror". */ public void setWarnings(WarningLevelEnum level) { warnings = level.getIndex(); diff --git a/src/main/java/net/sf/antcontrib/cpptasks/CompilerEnum.java b/src/main/java/net/sf/antcontrib/cpptasks/CompilerEnum.java index 96723b9..9e00744 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/CompilerEnum.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/CompilerEnum.java @@ -1,6 +1,6 @@ /* * - * Copyright 2002-2004 The Ant-Contrib project + * Copyright 2002-2008 The Ant-Contrib project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,8 +22,10 @@ import net.sf.antcontrib.cpptasks.compaq.CompaqVisualFortranCompiler; import net.sf.antcontrib.cpptasks.compiler.Compiler; import net.sf.antcontrib.cpptasks.devstudio.DevStudioCCompiler; import net.sf.antcontrib.cpptasks.devstudio.DevStudioMIDLCompiler; +import net.sf.antcontrib.cpptasks.devstudio.DevStudio2005CCompiler; import net.sf.antcontrib.cpptasks.devstudio.DevStudioResourceCompiler; import net.sf.antcontrib.cpptasks.gcc.GccCCompiler; +import net.sf.antcontrib.cpptasks.gcc.WindresResourceCompiler; import net.sf.antcontrib.cpptasks.hp.aCCCompiler; import net.sf.antcontrib.cpptasks.ibm.VisualAgeCCompiler; import net.sf.antcontrib.cpptasks.intel.IntelLinux32CCompiler; @@ -72,6 +74,10 @@ import org.apache.tools.ant.types.EnumeratedAttribute; * <td>Microsoft Visual C++</td> * </tr> * <tr> + * <td>msvc8</td> + * <td>Microsoft Visual C++ 8</td> + * </tr> + * <tr> * <td>bcc</td> * <td>Borland C++ Compiler</td> * </tr> @@ -179,6 +185,10 @@ import org.apache.tools.ant.types.EnumeratedAttribute; * <td>wfl</td> * <td>OpenWatcom FORTRAN compiler (experimental)</td> * </tr> + * <tr> + * <td>windres</td> + * <td>GNU windres resource compiler</td> + * </tr> * </table> * * @author Curt Arnold @@ -193,6 +203,7 @@ public class CompilerEnum extends EnumeratedAttribute { // FREEHEP new ProcessorEnumValue("gfortran", GccCCompiler.getGFortranInstance()), new ProcessorEnumValue("msvc", DevStudioCCompiler.getInstance()), + new ProcessorEnumValue("msvc8", DevStudio2005CCompiler.getInstance()), new ProcessorEnumValue("bcc", BorlandCCompiler.getInstance()), new ProcessorEnumValue("msrc", DevStudioResourceCompiler .getInstance()), @@ -260,7 +271,8 @@ public class CompilerEnum extends EnumeratedAttribute { new ProcessorEnumValue("xpidl", XpidlCompiler.getInstance()), new ProcessorEnumValue("wcl", OpenWatcomCCompiler.getInstance()), new ProcessorEnumValue("wfl", OpenWatcomFortranCompiler.getInstance()), - }; + new ProcessorEnumValue("windres", WindresResourceCompiler.getInstance()) + }; public Compiler getCompiler() { return (Compiler) compilers[getIndex()].getProcessor(); } diff --git a/src/main/java/net/sf/antcontrib/cpptasks/DependencyTable.java b/src/main/java/net/sf/antcontrib/cpptasks/DependencyTable.java index ae20496..aaa3881 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/DependencyTable.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/DependencyTable.java @@ -160,7 +160,7 @@ public final class DependencyTable { /** * Visits the dependency info. * - * @returns true to continue towards recursion into included files + * @return true to continue towards recursion into included files */ public abstract boolean visit(DependencyInfo dependInfo); } @@ -248,8 +248,6 @@ public final class DependencyTable { * Creates a target history table from dependencies.xml in the prject * directory, if it exists. Otherwise, initializes the dependencies empty. * - * @param task - * task used for logging history load errors * @param baseDir * output directory for task */ diff --git a/src/main/java/net/sf/antcontrib/cpptasks/LinkerDef.java b/src/main/java/net/sf/antcontrib/cpptasks/LinkerDef.java index af1d307..92595bd 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/LinkerDef.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/LinkerDef.java @@ -23,7 +23,6 @@ import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; import net.sf.antcontrib.cpptasks.compiler.LinkType; import net.sf.antcontrib.cpptasks.compiler.Linker; import net.sf.antcontrib.cpptasks.compiler.Processor; -import net.sf.antcontrib.cpptasks.compiler.ProcessorConfiguration; import net.sf.antcontrib.cpptasks.gcc.GccLinker; import net.sf.antcontrib.cpptasks.types.FlexLong; import net.sf.antcontrib.cpptasks.types.LibrarySet; @@ -115,30 +114,6 @@ public class LinkerDef extends ProcessorDef { sysLibrarySets.addElement(libset); } - - public ProcessorConfiguration createConfiguration(CCTask task, - LinkType linkType, ProcessorDef baseDef, - TargetDef targetPlatform, - VersionInfo versionInfo) { - // - // must combine some local context (the linkType) - // with the referenced element - // - // get a pointer to the definition (either local or referenced) - ProcessorDef thisDef = this; - if (isReference()) { - thisDef = ((ProcessorDef) getCheckedRef(ProcessorDef.class, - "ProcessorDef")); - } - // - // find the appropriate processor (combines local linkType - // with possibly remote linker name) - Processor proc = getProcessor(); - proc = proc.getLinker(linkType); - ProcessorDef[] defaultProviders = getDefaultProviders(baseDef); - return proc.createConfiguration(task, linkType, defaultProviders, - thisDef, targetPlatform, versionInfo); - } public void execute() throws org.apache.tools.ant.BuildException { throw new org.apache.tools.ant.BuildException( "Not an actual task, but looks like one for documentation purposes"); @@ -281,6 +256,12 @@ public class LinkerDef extends ProcessorDef { } return linker; } + + public Processor getProcessor(LinkType linkType) { + Processor proc = getProcessor(); + return proc.getLinker(linkType); + } + public int getStack(LinkerDef[] defaultProviders, int index) { if (isReference()) { return ((LinkerDef) getCheckedRef(LinkerDef.class, "LinkerDef")) @@ -310,7 +291,7 @@ public class LinkerDef extends ProcessorDef { /** * Sets the starting address. * - * @param name + * @param entry * function name */ public void setEntry(String entry) { diff --git a/src/main/java/net/sf/antcontrib/cpptasks/LinkerEnum.java b/src/main/java/net/sf/antcontrib/cpptasks/LinkerEnum.java index 90ee7ca..460860a 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/LinkerEnum.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/LinkerEnum.java @@ -15,6 +15,8 @@ * limitations under the License. */ package net.sf.antcontrib.cpptasks; +import org.apache.tools.ant.types.EnumeratedAttribute; + import net.sf.antcontrib.cpptasks.arm.ADSLinker; import net.sf.antcontrib.cpptasks.borland.BorlandLinker; import net.sf.antcontrib.cpptasks.compaq.CompaqVisualFortranLinker; @@ -39,8 +41,6 @@ import net.sf.antcontrib.cpptasks.sun.C89Linker; import net.sf.antcontrib.cpptasks.sun.ForteCCLinker; import net.sf.antcontrib.cpptasks.ti.ClxxLinker; -import org.apache.tools.ant.types.EnumeratedAttribute; - /** * Enumeration of supported linkers * diff --git a/src/main/java/net/sf/antcontrib/cpptasks/OutputTypeEnum.java b/src/main/java/net/sf/antcontrib/cpptasks/OutputTypeEnum.java index 62941b8..77092fa 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/OutputTypeEnum.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/OutputTypeEnum.java @@ -42,7 +42,7 @@ public class OutputTypeEnum extends EnumeratedAttribute { return new String[]{"executable", // executable program "plugin", // plugin module "shared", // dynamically linkable module - "static", // convenience library + "static", // FREEHEP "jni" // jni module }; diff --git a/src/main/java/net/sf/antcontrib/cpptasks/PrecompileDef.java b/src/main/java/net/sf/antcontrib/cpptasks/PrecompileDef.java index 4dd9831..b642197 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/PrecompileDef.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/PrecompileDef.java @@ -56,9 +56,6 @@ public final class PrecompileDef extends DataType { * Adds filesets that specify files that should not be processed with * precompiled headers enabled. * - * @param exceptSet - * FileSet specify files that should not be processed with - * precompiled headers enabled. */ public PrecompileExceptDef createExcept() { return new PrecompileExceptDef(this); diff --git a/src/main/java/net/sf/antcontrib/cpptasks/ProcessorDef.java b/src/main/java/net/sf/antcontrib/cpptasks/ProcessorDef.java index 24c1a1f..54a3406 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/ProcessorDef.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/ProcessorDef.java @@ -65,7 +65,7 @@ public abstract class ProcessorDef extends DataType { */ private String ifProp; /** - * if true, processor definition inherits values from containing <cc> + * if true, processor definition inherits values from containing cc * element */ private boolean inherit; @@ -126,7 +126,7 @@ public abstract class ProcessorDef extends DataType { /** * Adds a <compilerarg>or <linkerarg> * - * @param arg + * @param param * command line argument, must not be null * @throws NullPointerException * if arg is null @@ -175,7 +175,7 @@ public abstract class ProcessorDef extends DataType { * Creates a configuration * * @param baseDef - * reference to def from containing <cc>element, may be null + * reference to def from containing cc element, may be null * @return configuration * */ @@ -188,11 +188,11 @@ public abstract class ProcessorDef extends DataType { baseDef, targetPlatform, versionInfo); } ProcessorDef[] defaultProviders = getDefaultProviders(baseDef); - Processor proc = getProcessor(); + Processor proc = getProcessor(linkType); return proc.createConfiguration(task, linkType, defaultProviders, this, targetPlatform, versionInfo); } /** - * Prepares list of processor arguments ( <compilerarg>, <linkerarg>) that + * Prepares list of processor arguments ( compilerarg, linkerarg ) that * are active for the current project settings. * * @return active compiler arguments @@ -219,7 +219,7 @@ public abstract class ProcessorDef extends DataType { return array; } /** - * Prepares list of processor arguments ( <compilerarg>, <linkerarg>) that + * Prepares list of processor arguments ( compilerarg, linkerarg) that * are active for the current project settings. * * @return active compiler arguments @@ -315,7 +315,7 @@ public abstract class ProcessorDef extends DataType { } /** * Gets the inherit attribute. If the inherit value is true, this processor - * definition will inherit default values from the containing <cc>element. + * definition will inherit default values from the containing cc element. * * @return if true then properties from the containing <cc>element are * used. @@ -358,6 +358,17 @@ public abstract class ProcessorDef extends DataType { } return processor; } + + /** + * Obtains the appropriate processor (compiler, linker) based on the + * LinkType. + * + * @return processor + */ + protected Processor getProcessor(LinkType linkType) { + // by default ignore the linkType. + return getProcessor(); + } /** * Gets a boolean value indicating whether all targets must be rebuilt * regardless of dependency analysis. @@ -523,7 +534,7 @@ public abstract class ProcessorDef extends DataType { } /** * If inherit has the default value of true, defines, includes and other - * settings from the containing <cc>element will be inherited. + * settings from the containing cc element will be inherited. * * @param inherit * new value diff --git a/src/main/java/net/sf/antcontrib/cpptasks/VersionInfo.java b/src/main/java/net/sf/antcontrib/cpptasks/VersionInfo.java index 3e70707..4ddcd14 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/VersionInfo.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/VersionInfo.java @@ -210,9 +210,9 @@ public final class VersionInfo extends DataType { } /** - * Returns a VersionInfo that reflects the state of - * @return - */ + * Returns a VersionInfo that reflects any inherited version information. + * @return merged version information. +\ */ public VersionInfo merge() { if (isReference()) { VersionInfo refVersion = (VersionInfo) diff --git a/src/main/java/net/sf/antcontrib/cpptasks/WarningLevelEnum.java b/src/main/java/net/sf/antcontrib/cpptasks/WarningLevelEnum.java index 6ba8489..6ba7438 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/WarningLevelEnum.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/WarningLevelEnum.java @@ -19,7 +19,7 @@ import org.apache.tools.ant.types.EnumeratedAttribute; /** * Enumerated attribute with the values "none", "severe", "default", - * "production", "diagnostic", and "failtask". + * "production", "diagnostic", and "aserror". */ public final class WarningLevelEnum extends EnumeratedAttribute { /** diff --git a/src/main/java/net/sf/antcontrib/cpptasks/apple/PropertyListSerialization.java b/src/main/java/net/sf/antcontrib/cpptasks/apple/PropertyListSerialization.java new file mode 100644 index 0000000..6a3c410 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/apple/PropertyListSerialization.java @@ -0,0 +1,235 @@ +/* + * Licensed to the Ant-Contrib Project under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The Ant-Contrib licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.apple; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamResult; + +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +/** + * Static class that provides methods to serialize + * a Map to a Cocoa XML Property List. Does not currently support + * date or data elements. + */ +public final class PropertyListSerialization { + /** + * Private constructor. + */ + private PropertyListSerialization() { + + } + + /** + * Serializes a property list into a Cocoa XML Property List document. + * @param propertyList property list. + * @param file destination. + * @param comments comments to insert into document. + * @throws SAXException if exception during serialization. + * @throws TransformerConfigurationException if exception creating serializer. + */ + public static void serialize(final Map propertyList, + final List comments, + final File file) + throws IOException, SAXException, + TransformerConfigurationException { + SAXTransformerFactory sf = (SAXTransformerFactory) + SAXTransformerFactory.newInstance(); + TransformerHandler handler = sf.newTransformerHandler(); + + FileOutputStream os = new FileOutputStream(file); + StreamResult result = new StreamResult(os); + handler.setResult(result); + + handler.startDocument(); + for(Iterator iter = comments.iterator(); iter.hasNext();) { + char[] comment = String.valueOf(iter.next()).toCharArray(); + handler.comment(comment, 0, comment.length); + } + AttributesImpl attributes = new AttributesImpl(); + handler.startElement(null, "plist", "plist", attributes); + serializeMap(propertyList, handler); + handler.endElement(null, "plist", "plist"); + + handler.endDocument(); + } + + /** + * Serialize a map as a dict element. + * @param map map to serialize. + * @param handler destination of serialization events. + * @throws SAXException if exception during serialization. + */ + private static void serializeMap(final Map map, + final ContentHandler handler) + throws SAXException { + AttributesImpl attributes = new AttributesImpl(); + handler.startElement(null, "dict", "dict", attributes); + + if (map.size() > 0) { + // + // need to output with sorted keys to maintain + // reproducability + // + Object[] keys = map.keySet().toArray(); + Arrays.sort(keys); + for(int i = 0; i < keys.length; i++) { + String key = String.valueOf(keys[i]); + handler.startElement(null, "key", "key", attributes); + handler.characters(key.toCharArray(), 0, key.length()); + handler.endElement(null, "key", "key"); + serializeObject(map.get(keys[i]), handler); + } + } + handler.endElement(null, "dict", "dict"); + } + + /** + * Serialize a list as an array element. + * @param list list to serialize. + * @param handler destination of serialization events. + * @throws SAXException if exception during serialization. + */ + private static void serializeList(final List list, + final ContentHandler handler) + throws SAXException { + AttributesImpl attributes = new AttributesImpl(); + handler.startElement(null, "array", "array", attributes); + for(Iterator iter = list.iterator();iter.hasNext();) { + serializeObject(iter.next(), handler); + } + handler.endElement(null, "array", "array"); + } + + /** + * Creates an element with the specified tag name and character content. + * @param tag tag name. + * @param content character content. + * @param handler destination of serialization events. + * @throws SAXException if exception during serialization. + */ + private static void serializeElement(final String tag, + final String content, + final ContentHandler handler) + throws SAXException { + AttributesImpl attributes = new AttributesImpl(); + handler.startElement(null, tag, tag, attributes); + handler.characters(content.toCharArray(), 0, content.length()); + handler.endElement(null, tag, tag); + } + + + /** + * Serialize a Number as an integer element. + * @param integer number to serialize. + * @param handler destination of serialization events. + * @throws SAXException if exception during serialization. + */ + private static void serializeInteger(final Number integer, + final ContentHandler handler) + throws SAXException { + serializeElement("integer", String.valueOf(integer.longValue()), + handler); + } + + /** + * Serialize a Number as a real element. + * @param real number to serialize. + * @param handler destination of serialization events. + * @throws SAXException if exception during serialization. + */ + private static void serializeReal(final Number real, + final ContentHandler handler) + throws SAXException { + serializeElement("real", + String.valueOf(real.doubleValue()), + handler); + } + + + /** + * Serialize a Boolean as a true or false element. + * @param val boolean to serialize. + * @param handler destination of serialization events. + * @throws SAXException if exception during serialization. + */ + private static void serializeBoolean(final Boolean val, + final ContentHandler handler) + throws SAXException { + String tag = "false"; + if (val.booleanValue()) { + tag = "true"; + } + AttributesImpl attributes = new AttributesImpl(); + handler.startElement(null, tag, tag, attributes); + handler.endElement(null, tag, tag); + } + + /** + * Serialize a string as a string element. + * @param val string to serialize. + * @param handler destination of serialization events. + * @throws SAXException if exception during serialization. + */ + private static void serializeString(final String val, + final ContentHandler handler) + throws SAXException { + serializeElement("string", + val, + handler); + } + + + /** + * Serialize an object using the best available element. + * @param obj object to serialize. + * @param handler destination of serialization events. + * @throws SAXException if exception during serialization. + */ + private static void serializeObject(final Object obj, + final ContentHandler handler) + throws SAXException { + if (obj instanceof Map) { + serializeMap((Map) obj, handler); + } else if (obj instanceof List) { + serializeList((List) obj, handler); + } else if (obj instanceof Number) { + if(obj instanceof Double + ||obj instanceof Float) { + serializeReal((Number) obj, handler); + } else { + serializeInteger((Number) obj, handler); + } + } else if (obj instanceof Boolean) { + serializeBoolean((Boolean) obj, handler); + } else { + serializeString(String.valueOf(obj), handler); + } + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/apple/XcodeProjectWriter.java b/src/main/java/net/sf/antcontrib/cpptasks/apple/XcodeProjectWriter.java index 7f21bec..f901b4d 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/apple/XcodeProjectWriter.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/apple/XcodeProjectWriter.java @@ -16,20 +16,6 @@ */ package net.sf.antcontrib.cpptasks.apple; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.Writer; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.Vector; -import java.util.List; - -import org.apache.tools.ant.BuildException; - import net.sf.antcontrib.cpptasks.CCTask; import net.sf.antcontrib.cpptasks.CUtil; import net.sf.antcontrib.cpptasks.TargetInfo; @@ -37,538 +23,994 @@ import net.sf.antcontrib.cpptasks.compiler.CommandLineCompilerConfiguration; import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; import net.sf.antcontrib.cpptasks.compiler.ProcessorConfiguration; import net.sf.antcontrib.cpptasks.gcc.GccCCompiler; +import net.sf.antcontrib.cpptasks.ide.DependencyDef; import net.sf.antcontrib.cpptasks.ide.ProjectDef; import net.sf.antcontrib.cpptasks.ide.ProjectWriter; +import org.apache.tools.ant.BuildException; +import org.xml.sax.SAXException; + +import javax.xml.transform.TransformerConfigurationException; +import java.io.File; +import java.io.IOException; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; + /** - * Writes a Apple Xcode project directory. - * - * Status: Collects file list but does not pick up libraries and settings from - * project. - * - * @author curta + * Writes a Apple Xcode 2.1+ project directory. XCode stores project + * configuration as a PropertyList. Though it will always write the project + * as a Cocoa Old-Style ASCII property list, it will read projects + * stored using Cocoa's XML Property List format. */ public final class XcodeProjectWriter - implements ProjectWriter { - - /** - * Next object identifier for project file. - */ - private int nextID = 0x08FB7796; - - /** - * Constructor. - * - */ - public XcodeProjectWriter() { - } - - /** - * Get next unique ID. - * @return unique ID - */ - private String getUniqueID() { - return Integer.toString(nextID++, 16) + "FE84155DC02AAC07"; - } - - /** - * Writes a project definition file. - * - * @param fileName - * File name base, writer may append appropriate extension - * @param task - * cc task for which to write project - * @param projectDef - * project element - * @param targets - * compilation targets - * @param linkTarget - * link target - * @throws IOException - * if error writing project file - */ - public void writeProject(final File fileName, - final CCTask task, - final ProjectDef projectDef, - final List sources, - final Hashtable targets, - final TargetInfo linkTarget) throws IOException { - - File xcodeDir = new File(fileName + ".xcode"); - if (!projectDef.getOverwrite() && xcodeDir.exists()) { - throw new BuildException("Not allowed to overwrite project file " - + xcodeDir.toString()); + implements ProjectWriter { + + /** + * Constructor. + */ + public XcodeProjectWriter() { } - CommandLineCompilerConfiguration compilerConfig = - getBaseCompilerConfiguration(targets); - if (compilerConfig == null) { - throw new BuildException( - "Unable to find compilation target using GNU C++ compiler"); + /** + * Writes a project definition file. + * + * @param fileName File name base, writer may append appropriate extension + * @param task cc task for which to write project + * @param projectDef project element + * @param targets compilation targets + * @param linkTarget link target + * @throws IOException if error writing project file + */ + public void writeProject(final File fileName, + final CCTask task, + final ProjectDef projectDef, + final List sources, + final Hashtable targets, + final TargetInfo linkTarget) throws IOException { + + File xcodeDir = new File(fileName + ".xcodeproj"); + if (!projectDef.getOverwrite() && xcodeDir.exists()) { + throw new BuildException("Not allowed to overwrite project file " + + xcodeDir.toString()); + } + + CommandLineCompilerConfiguration compilerConfig = + getBaseCompilerConfiguration(targets); + if (compilerConfig == null) { + throw new BuildException( + "Unable to find compilation target using GNU C++ compiler"); + } + + + CommandLineLinkerConfiguration linkerConfig = null; + if (linkTarget.getConfiguration() instanceof CommandLineLinkerConfiguration) { + linkerConfig = (CommandLineLinkerConfiguration) linkTarget.getConfiguration(); + } + + String projectName = projectDef.getName(); + if (projectName == null) { + projectName = fileName.getName(); + } + final String basePath = fileName.getAbsoluteFile().getParent(); + + xcodeDir.mkdir(); + + File xcodeProj = new File(xcodeDir, "project.pbxproj"); + + // + // create property list + // + Map propertyList = new HashMap(); + propertyList.put("archiveVersion", "1"); + propertyList.put("classes", new HashMap()); + propertyList.put("objectVersion", "42"); + Map objects = new HashMap(); + + final String sourceTree = "<source>"; + + // + // add source files and source group to property list + // + List sourceGroupChildren = + addSources(objects, "SOURCE_ROOT", basePath, targets); + PBXObjectRef sourceGroup = + createPBXGroup("Source", sourceTree, sourceGroupChildren); + objects.put(sourceGroup.getID(), sourceGroup.getProperties()); + + + + + // + // add product to property list + // + PBXObjectRef product = addProduct(objects, linkTarget); + List productsList = new ArrayList(); + productsList.add(product); + PBXObjectRef productsGroup = + createPBXGroup("Products", sourceTree, productsList); + objects.put(productsGroup.getID(), productsGroup.getProperties()); + + // + // add documentation group to property list + // + PBXObjectRef documentationGroup = addDocumentationGroup(objects, sourceTree); + + // + // add main group containing source, products and documentation group + // + ArrayList groups = new ArrayList(3); + groups.add(sourceGroup); + groups.add(documentationGroup); + groups.add(productsGroup); + PBXObjectRef mainGroup = createPBXGroup(projectName, sourceTree, groups); + StringBuffer comments = new StringBuffer(); + for(Iterator iter = projectDef.getComments().iterator(); iter.hasNext();) { + comments.append(iter.next()); + } + if (comments.length() > 0) { + mainGroup.getProperties().put("comments", comments.toString()); + } + objects.put(mainGroup.getID(), mainGroup.getProperties()); + + // + // add project configurations + // + PBXObjectRef compilerConfigurations = + addProjectConfigurationList(objects, + basePath, + projectDef.getDependencies(), + compilerConfig, + linkerConfig); + + String projectDirPath = ""; + List projectTargets = new ArrayList(); + + // + // add project to property list + // + // + // Calculate path (typically several ../..) of the root directory + // (where build.xml lives) relative to the XCode project directory. + // XCode 3.0 will now prompt user to supply the value if not specified. + String projectRoot = CUtil.toUnixPath( + CUtil.getRelativePath(basePath, projectDef.getProject().getBaseDir())); + PBXObjectRef project = createPBXProject(compilerConfigurations, mainGroup, + projectDirPath, projectRoot, projectTargets); + objects.put(project.getID(), project.getProperties()); + + List frameworkBuildFiles = new ArrayList(); + for (Iterator iter = projectDef.getDependencies().iterator(); iter.hasNext();) { + DependencyDef dependency = (DependencyDef) iter.next(); + PBXObjectRef buildFile = addDependency(objects, project, groups, basePath, dependency); + if (buildFile != null) { + frameworkBuildFiles.add(buildFile); + } + } + // + // add description of native target (that is the executable or + // shared library) + // + PBXObjectRef nativeTarget = + addNativeTarget(objects, linkTarget, product, + projectName, sourceGroupChildren, frameworkBuildFiles); + projectTargets.add(nativeTarget); + + + + + + // + // finish up overall property list + // + propertyList.put("objects", objects); + propertyList.put("rootObject", project.getID()); + + + // + // write property list out to XML file + // + try { + PropertyListSerialization.serialize(propertyList, + projectDef.getComments(), xcodeProj); + } catch (TransformerConfigurationException ex) { + throw new IOException(ex.toString()); + } catch (SAXException ex) { + if (ex.getException() instanceof IOException) { + throw (IOException) ex.getException(); + } + throw new IOException(ex.toString()); + } } - String projectName = projectDef.getName(); - if (projectName == null) { - projectName = fileName.getName(); + + /** + * Adds a dependency to the object graph. + * @param objects + * @param project + * @param mainGroupChildren + * @param baseDir + * @param dependency + * @return PBXBuildFile to add to PBXFrameworksBuildPhase. + */ + private PBXObjectRef addDependency(final Map objects, + final PBXObjectRef project, + final List mainGroupChildren, + final String baseDir, + final DependencyDef dependency) { + if (dependency.getFile() != null) { + File xcodeDir = new File(dependency.getFile().getAbsolutePath() + ".xcodeproj"); + if (xcodeDir.exists()) { + PBXObjectRef xcodePrj = createPBXFileReference("SOURCE_ROOT", baseDir, xcodeDir); + mainGroupChildren.add(xcodePrj); + objects.put(xcodePrj.getID(), xcodePrj.getProperties()); + + int proxyType = 2; + PBXObjectRef proxy = createPBXContainerItemProxy( + xcodePrj, proxyType, dependency.getName()); + objects.put(proxy.getID(), proxy.getProperties()); + + PBXObjectRef referenceProxy = createPBXReferenceProxy(proxy, dependency); + objects.put(referenceProxy.getID(), referenceProxy.getProperties()); + + PBXObjectRef buildFile = createPBXBuildFile(referenceProxy, Collections.EMPTY_MAP); + objects.put(buildFile.getID(), buildFile.getProperties()); + + List productsChildren = new ArrayList(); + productsChildren.add(referenceProxy); + PBXObjectRef products = createPBXGroup("Products", "<group>", productsChildren); + objects.put(products.getID(), products.getProperties()); + + Map projectReference = new HashMap(); + projectReference.put("ProductGroup", products); + projectReference.put("ProjectRef", xcodePrj); + + List projectReferences = (List) project.getProperties().get("ProjectReferences"); + if (projectReferences == null) { + projectReferences = new ArrayList(); + project.getProperties().put("ProjectReferences", projectReferences); + } + projectReferences.add(projectReference); + return buildFile; + } + } + return null; } - final String basePath = fileName.getAbsoluteFile().getParent(); - - xcodeDir.mkdir(); - - File xcodeProj = new File(xcodeDir, "project.pbxproj"); - - // - // assume that all C++ compiles can use the - // same settings - // - CommandLineCompilerConfiguration gccConfig = null; - - Vector sourceList = new Vector(targets.size()); - Iterator targetIter = targets.values().iterator(); - while (targetIter.hasNext()) { - TargetInfo info = (TargetInfo) targetIter.next(); - File[] targetsources = info.getSources(); - for (int i = 0; i < targetsources.length; i++) { - sourceList.addElement(new SourceEntry(targetsources[i], - getUniqueID(), getUniqueID())); - } - ProcessorConfiguration procConfig = info.getConfiguration(); - if (procConfig instanceof CommandLineCompilerConfiguration - && gccConfig == null) { - gccConfig = (CommandLineCompilerConfiguration) procConfig; - } + + /** + * Add documentation group to map of objects. + * @param objects object map. + * @param sourceTree source tree description. + * @return documentation group. + */ + private PBXObjectRef addDocumentationGroup(final Map objects, + final String sourceTree) { + List productsList = new ArrayList(); + PBXObjectRef products = + createPBXGroup("Documentation", sourceTree, productsList); + objects.put(products.getID(), products.getProperties()); + return products; } - SourceEntry[] sortedSources = new SourceEntry[sourceList.size()]; - sourceList.copyInto(sortedSources); - Arrays.sort(sortedSources, new Comparator() { - public int compare(final Object o1, final Object o2) { - return ( (SourceEntry) o1).getFile().getName().compareTo( ( ( - SourceEntry) o2).getFile().getName()); - } - }); - File outFile = task.getOutfile(); - - Writer writer = new BufferedWriter(new FileWriter(xcodeProj)); - - writer.write("// !$*UTF8*$!\n"); - writer.write(" {\n"); - writer.write(" archiveVersion = 1;\n"); - writer.write(" classes = {\n"); - writer.write(" };\n"); - writer.write(" objectVersion = 39;\n"); - writer.write(" objects = {\n"); - writer.write(" 014CEA520018CE5811CA2923 = {\n"); - writer.write(" buildRules = (\n"); - writer.write(" );\n"); - writer.write(" buildSettings = {\n"); - writer.write(" COPY_PHASE_STRIP = NO;\n"); - writer.write(" DEBUGGING_SYMBOLS = YES;\n"); - writer.write(" GCC_DYNAMIC_NO_PIC = NO;\n"); - writer.write(" GCC_ENABLE_FIX_AND_CONTINUE = YES;\n"); - writer.write(" GCC_GENERATE_DEBUGGING_SYMBOLS = YES;\n"); - writer.write(" GCC_OPTIMIZATION_LEVEL = 0;\n"); - writer.write(" OPTIMIZATION_CFLAGS = \"-O0\";\n"); - writer.write(" ZERO_LINK = YES;\n"); - writer.write(" };\n"); - writer.write(" isa = PBXBuildStyle;\n"); - writer.write(" name = Development;\n"); - writer.write(" };\n"); - writer.write(" 014CEA530018CE5811CA2923 = {\n"); - writer.write(" buildRules = (\n"); - writer.write(" );\n"); - writer.write(" buildSettings = {\n"); - writer.write(" COPY_PHASE_STRIP = YES;\n"); - writer.write(" GCC_ENABLE_FIX_AND_CONTINUE = NO;\n"); - writer.write(" ZERO_LINK = NO;\n"); - writer.write(" };\n"); - writer.write(" isa = PBXBuildStyle;\n"); - writer.write(" name = Deployment;\n"); - writer.write(" };\n"); - writer.write("// 010\n"); - writer.write("// 011\n"); - writer.write("// 012\n"); - writer.write("// 013\n"); - writer.write("// 014\n"); - writer.write("// 080\n"); - writer.write("// 081\n"); - writer.write("// 082\n"); - writer.write("// 083\n"); - writer.write("// 084\n"); - writer.write(" 08FB7793FE84155DC02AAC07 = {\n"); - writer.write(" buildSettings = {\n"); - writer.write(" };\n"); - writer.write(" buildStyles = (\n"); - writer.write(" 014CEA520018CE5811CA2923,\n"); - writer.write(" 014CEA530018CE5811CA2923,\n"); - writer.write(" );\n"); - writer.write(" hasScannedForEncodings = 1;\n"); - writer.write(" isa = PBXProject;\n"); - writer.write(" mainGroup = 08FB7794FE84155DC02AAC07;\n"); - writer.write(" projectDirPath = \"\";\n"); - writer.write(" targets = (\n"); - writer.write(" D2AAC0620554660B00DB518D,\n"); - writer.write(" );\n"); - writer.write(" };\n"); - writer.write(" 08FB7794FE84155DC02AAC07 = {\n"); - writer.write(" children = (\n"); - writer.write(" 08FB7795FE84155DC02AAC07,\n"); - writer.write(" 1AB674ADFE9D54B511CA2CBB,\n"); - writer.write(" );\n"); - writer.write(" isa = PBXGroup;\n"); - writer.write(" name = "); - writer.write(outFile.getName()); - writer.write(";\n"); - writer.write(" refType = 4;\n"); - writer.write(" sourceTree = \"<group>\";\n"); - writer.write(" };\n"); - writer.write(" 08FB7795FE84155DC02AAC07 = {\n"); - writer.write(" children = (\n"); - - // - // source ID's go here - // - for (int i = 0; i < sortedSources.length; i++) { - writer.write(" "); - writer.write(sortedSources[i].getSourceID()); - writer.write(",\n"); + + /** + * Add file reference of product to map of objects. + * @param objects object map. + * @param linkTarget build description for executable or shared library. + * @return file reference to generated executable or shared library. + */ + private PBXObjectRef addProduct(final Map objects, + final TargetInfo linkTarget) { + + // + // create file reference for executable file + // forget Ant's location, just place in XCode's default location + PBXObjectRef executable = createPBXFileReference("BUILD_PRODUCTS_DIR", + linkTarget.getOutput().getParent(), + linkTarget.getOutput()); + Map executableProperties = executable.getProperties(); + + String fileType = getFileType(linkTarget); + executableProperties.put("explicitFileType", fileType); + executableProperties.put("includeInIndex", "0"); + objects.put(executable.getID(), executableProperties); + + return executable; } - writer.write(" );\n"); - writer.write(" isa = PBXGroup;\n"); - writer.write(" name = Source;\n"); - writer.write(" refType = 4;\n"); - writer.write(" sourceTree = \"<group>\";\n"); - writer.write(" };\n"); - - for (int i = 0; i < sortedSources.length; i++) { - // - // source definition - // - SourceEntry entry = sortedSources[i]; - writer.write(" "); - writer.write(entry.getSourceID()); - writer.write(" = {\n"); - writer.write(" fileEncoding = 4;\n"); - writer.write(" isa = PBXFileReference;\n"); - String sourceName = entry.getFile().getName(); - if (sourceName.endsWith(".c")) { - writer.write(" lastKnownFileType = sourcecode.c.c;\n"); - } else { - writer.write(" lastKnownFileType = sourcecode.cpp.cpp;\n"); - } - - String relativePath = CUtil.getRelativePath(basePath, entry.getFile()); - if (!relativePath.equals(sourceName)) { - writer.write(" name = "); - writer.write(sourceName); - writer.write(";\n"); - } - writer.write(" path = "); - writer.write(relativePath); - writer.write(";\n"); - writer.write(" refType = 4;\n"); - writer.write(" sourceTree = \"<group>\";\n"); - writer.write(" };\n"); - - // - // build definition - // - writer.write(" "); - writer.write(entry.getBuildID()); - writer.write(" = {\n"); - writer.write(" fileRef = "); - writer.write(entry.getSourceID()); - writer.write(";\n"); - writer.write(" isa = PBXBuildFile;\n"); - writer.write(" settings = {\n"); - writer.write(" };\n"); - writer.write(" };\n"); + /** + * Add file references for all source files to map of objects. + * @param objects map of objects. + * @param sourceTree source tree. + * @param basePath parent of XCode project dir + * @param targets build targets. + * @return list containing file references of source files. + */ + private List addSources(final Map objects, + final String sourceTree, + final String basePath, + final Hashtable targets) { + List sourceGroupChildren = new ArrayList(); + + ArrayList sourceList = new ArrayList(targets.size()); + Iterator targetIter = targets.values().iterator(); + while (targetIter.hasNext()) { + TargetInfo info = (TargetInfo) targetIter.next(); + File[] targetsources = info.getSources(); + for (int i = 0; i < targetsources.length; i++) { + sourceList.add(targetsources[i]); + } + } + Object[] sortedSources = sourceList.toArray(); + Arrays.sort(sortedSources, new Comparator() { + public int compare(final Object o1, final Object o2) { + return (((File) o1).getName().compareTo( + ((File) o2).getName())); + } + }); + for (int i = 0; i < sortedSources.length; i++) { + PBXObjectRef fileRef = createPBXFileReference(sourceTree, + basePath, (File) sortedSources[i]); + sourceGroupChildren.add(fileRef); + objects.put(fileRef.getID(), fileRef.getProperties()); + } + + return sourceGroupChildren; } - writer.write("// 080\n"); - writer.write("// 081\n"); - writer.write("// 082\n"); - writer.write("// 083\n"); - writer.write("// 084\n"); - writer.write("// 1A0\n"); - writer.write("// 1A1\n"); - writer.write("// 1A2\n"); - writer.write("// 1A3\n"); - writer.write("// 1A4\n"); - writer.write(" 1AB674ADFE9D54B511CA2CBB = {\n"); - writer.write(" children = (\n"); - writer.write(" D2AAC0630554660B00DB518D,\n"); - writer.write(" );\n"); - writer.write(" isa = PBXGroup;\n"); - writer.write(" name = Products;\n"); - writer.write(" refType = 4;\n"); - writer.write(" sourceTree = \"<group>\";\n"); - writer.write(" };\n"); - writer.write("// 1A0\n"); - writer.write("// 1A1\n"); - writer.write("// 1A2\n"); - writer.write("// 1A3\n"); - writer.write("// 1A4\n"); - writer.write("// D20\n"); - writer.write("// D21\n"); - writer.write("// D22\n"); - writer.write("// D23\n"); - writer.write("// D24\n"); - writer.write(" D2AAC0600554660B00DB518D = {\n"); - writer.write(" buildActionMask = 2147483647;\n"); - writer.write(" files = (\n"); - writer.write(" );\n"); - writer.write(" isa = PBXHeadersBuildPhase;\n"); - writer.write(" runOnlyForDeploymentPostprocessing = 0;\n"); - writer.write(" };\n"); - writer.write(" D2AAC0610554660B00DB518D = {\n"); - writer.write(" buildActionMask = 2147483647;\n"); - writer.write(" files = (\n"); - - // - // build ID's - // - for (int i = 0; i < sortedSources.length; i++) { - writer.write(" "); - writer.write(sortedSources[i].getBuildID()); - writer.write(",\n"); + + /** + * Add native target configuration list. + * @param objects map of objects. + * @param projectName project name. + * @return build configurations for native target. + */ + private PBXObjectRef addNativeTargetConfigurationList(final Map objects, + final String projectName) { + + // + // Create a configuration list with + // two stock configurations: Debug and Release + // + List configurations = new ArrayList(); + Map debugSettings = new HashMap(); + debugSettings.put("COPY_PHASE_STRIP", "NO"); + debugSettings.put("GCC_DYNAMIC_NO_PIC", "NO"); + debugSettings.put("GCC_ENABLE_FIX_AND_CONTINUE", "YES"); + debugSettings.put("GCC_MODEL_TUNING", "G5"); + debugSettings.put("GCC_OPTIMIZATION_LEVEL", "0"); + debugSettings.put("INSTALL_PATH", "$(HOME)/bin"); + debugSettings.put("PRODUCT_NAME", projectName); + debugSettings.put("ZERO_LINK", "YES"); + PBXObjectRef debugConfig = createXCBuildConfiguration("Debug", + debugSettings); + objects.put(debugConfig.getID(), debugConfig.getProperties()); + configurations.add(debugConfig); + + Map releaseSettings = new HashMap(); + List archs = new ArrayList(); + archs.add("ppc"); + archs.add("i386"); + releaseSettings.put("ARCHS", archs); + releaseSettings.put("GCC_GENERATE_DEBUGGING_SYMBOLS", "NO"); + releaseSettings.put("GCC_MODEL_TUNING", "G5"); + releaseSettings.put("INSTALL_PATH", "$(HOME)/bin"); + releaseSettings.put("PRODUCT_NAME", projectName); + PBXObjectRef releaseConfig = createXCBuildConfiguration("Release", + releaseSettings); + objects.put(releaseConfig.getID(), releaseConfig.getProperties()); + configurations.add(releaseConfig); + + PBXObjectRef configurationList = createXCConfigurationList(configurations); + objects.put(configurationList.getID(), configurationList.getProperties()); + return configurationList; } - writer.write(" );\n"); - writer.write(" isa = PBXSourcesBuildPhase;\n"); - writer.write(" runOnlyForDeploymentPostprocessing = 0;\n"); - writer.write(" };\n"); - writer.write(" D2AAC0620554660B00DB518D = {\n"); - writer.write(" buildPhases = (\n"); - writer.write(" D2AAC0600554660B00DB518D,\n"); - writer.write(" D2AAC0610554660B00DB518D,\n"); - writer.write(" );\n"); - writer.write(" buildRules = (\n"); - writer.write(" );\n"); - writer.write(" buildSettings = {\n"); - writer.write(" DYLIB_COMPATIBILITY_VERSION = 1;\n"); - writer.write(" DYLIB_CURRENT_VERSION = 1;\n"); - // - // write preprocessor macros - // - if (gccConfig != null) { - String[] options = gccConfig.getPreArguments(); - boolean hasD = false; - for (int i = 0; i < options.length; i++) { - if (options[i].startsWith("-D")) { - if (!hasD) { - writer.write(" GCC_PREPROCESSOR_DEFINITIONS = \""); - hasD = true; - } else { - writer.write(" "); - } - writer.write(options[i].substring(2)); + + + + /** + * Add project configuration list. + * @param objects map of objects. + * @param baseDir base directory. + * @param compilerConfig compiler configuration. + * @return project configuration object. + */ + private PBXObjectRef addProjectConfigurationList(final Map objects, + final String baseDir, + final List dependencies, + final CommandLineCompilerConfiguration compilerConfig, + final CommandLineLinkerConfiguration linkerConfig) { + // + // Create a configuration list with + // two stock configurations: Debug and Release + // + List configurations = new ArrayList(); + Map debugSettings = new HashMap(); + debugSettings.put("GCC_WARN_ABOUT_RETURN_TYPE", "YES"); + debugSettings.put("GCC_WARN_UNUSED_VARIABLE", "YES"); + debugSettings.put("PREBINDING", "NO"); + debugSettings.put("SDKROOT", "/Developer/SDKs/MacOSX10.4u.sdk"); + + + PBXObjectRef debugConfig = createXCBuildConfiguration("Debug", debugSettings); + objects.put(debugConfig.getID(), debugConfig.getProperties()); + configurations.add(debugConfig); + + Map releaseSettings = new HashMap(); + releaseSettings.put("GCC_WARN_ABOUT_RETURN_TYPE", "YES"); + releaseSettings.put("GCC_WARN_UNUSED_VARIABLE", "YES"); + releaseSettings.put("PREBINDING", "NO"); + releaseSettings.put("SDKROOT", "/Developer/SDKs/MacOSX10.4u.sdk"); + PBXObjectRef releaseConfig = + createXCBuildConfiguration("Release", releaseSettings); + objects.put(releaseConfig.getID(), releaseConfig.getProperties()); + configurations.add(releaseConfig); + PBXObjectRef configurationList = createXCConfigurationList(configurations); + Map projectConfigurationListProperties = configurationList.getProperties(); + projectConfigurationListProperties.put("defaultConfigurationIsVisible", "0"); + projectConfigurationListProperties.put("defaultConfigurationName", "Debug"); + objects.put(configurationList.getID(), configurationList.getProperties()); + + // + // add include paths to both configurations + // + File[] includeDirs = compilerConfig.getIncludePath(); + if (includeDirs.length > 0) { + ArrayList includePaths = new ArrayList(); + Map includePathMap = new HashMap(); + for (int i = 0; i < includeDirs.length; i++) { + if(!CUtil.isSystemPath(includeDirs[i])) { + String absPath = includeDirs[i].getAbsolutePath(); + if (!includePathMap.containsKey(absPath)) { + if(absPath.startsWith("/usr/")) { + includePaths.add(CUtil.toUnixPath(absPath)); + } else { + String relPath = CUtil.toUnixPath( + CUtil.getRelativePath(baseDir, includeDirs[i])); + includePaths.add(relPath); + } + includePathMap.put(absPath, absPath); + } + } + } + includePaths.add("${inherited)"); + debugSettings.put("HEADER_SEARCH_PATHS", includePaths); + releaseSettings.put("HEADER_SEARCH_PATHS", includePaths); + } + + // + // add preprocessor definitions to both configurations + // + // + String[] preArgs = compilerConfig.getPreArguments(); + List defines = new ArrayList(); + for (int i = 0; i < preArgs.length; i++) { + if (preArgs[i].startsWith("-D")) { + defines.add(preArgs[i].substring(2)); + } } - } - if (hasD) { - writer.write("\";\n"); - } + if (defines.size() > 0) { + defines.add("$(inherited)"); + debugSettings.put("GCC_PREPROCESSOR_DEFINITIONS", defines); + releaseSettings.put("GCC_PREPROCESSOR_DEFINITIONS", defines); + } + + + if (linkerConfig != null) { + Map librarySearchMap = new HashMap(); + List librarySearchPaths = new ArrayList(); + List otherLdFlags = new ArrayList(); + String[] linkerArgs = linkerConfig.getEndArguments(); + for (int i = 0; i < linkerArgs.length; i++) { + if (linkerArgs[i].startsWith("-L")) { + String libDir = linkerArgs[i].substring(2); + if (!librarySearchMap.containsKey(libDir)) { + if (!libDir.equals("/usr/lib")) { + librarySearchPaths.add( + CUtil.toUnixPath(CUtil.getRelativePath(baseDir, + new File(libDir)))); + } + librarySearchMap.put(libDir, libDir); + + } + } else if (linkerArgs[i].startsWith("-l")) { + // + // check if library is in dependencies list + // + String libName = linkerArgs[i].substring(2); + boolean found = false; + for(Iterator iter = dependencies.iterator();iter.hasNext();) { + DependencyDef dependency = (DependencyDef) iter.next(); + if (libName.startsWith(dependency.getName())) { + File dependencyFile = dependency.getFile(); + if (dependencyFile != null && + new File(dependencyFile.getAbsolutePath() + ".xcodeproj").exists()) { + found = true; + break; + } + } + } + if (!found) { + otherLdFlags.add(linkerArgs[i]); + } + } + } + + + debugSettings.put("LIBRARY_SEARCH_PATHS", librarySearchPaths); + debugSettings.put("OTHER_LDFLAGS", otherLdFlags); + releaseSettings.put("LIBRARY_SEARCH_PATHS", librarySearchPaths); + releaseSettings.put("OTHER_LDFLAGS", otherLdFlags); + } + return configurationList; } - writer.write(" GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;\n"); - writer.write(" GCC_WARN_UNKNOWN_PRAGMAS = NO;\n"); - if (gccConfig != null) { - File[] includes = gccConfig.getIncludePath(); - if (includes.length > 0) { - writer.write(" HEADER_SEARCH_PATHS = \""); - for (int i = 0; i < includes.length; i++) { - if (i > 0) { - writer.write(" "); - } - writer.write(CUtil.getRelativePath(basePath, includes[i])); + + /** + * Add native target to map of objects. + * @param objects map of objects. + * @param linkTarget description of executable or shared library. + * @param product product. + * @param projectName project name. + * @param sourceGroupChildren source files needed to build product. + * @return native target. + */ + private PBXObjectRef addNativeTarget(final Map objects, + final TargetInfo linkTarget, + final PBXObjectRef product, + final String projectName, + final List sourceGroupChildren, + final List frameworkBuildFiles) { + + PBXObjectRef buildConfigurations = + addNativeTargetConfigurationList(objects, projectName); + + int buildActionMask = 2147483647; + List buildPhases = new ArrayList(); + + Map settings = new HashMap(); + settings.put("ATTRIBUTES", new ArrayList()); + List buildFiles = new ArrayList(); + for (Iterator iter = sourceGroupChildren.iterator(); + iter.hasNext();) { + PBXObjectRef sourceFile = (PBXObjectRef) iter.next(); + PBXObjectRef buildFile = createPBXBuildFile(sourceFile, settings); + buildFiles.add(buildFile); + objects.put(buildFile.getID(), buildFile.getProperties()); } - writer.write("\";\n"); - } + + + PBXObjectRef sourcesBuildPhase = createPBXSourcesBuildPhase(buildActionMask, + buildFiles, false); + objects.put(sourcesBuildPhase.getID(), sourcesBuildPhase.getProperties()); + buildPhases.add(sourcesBuildPhase); + + + buildActionMask = 8; + PBXObjectRef frameworksBuildPhase = + createPBXFrameworksBuildPhase(buildActionMask, + frameworkBuildFiles, false); + objects.put(frameworksBuildPhase.getID(), frameworksBuildPhase.getProperties()); + buildPhases.add(frameworksBuildPhase); + + PBXObjectRef copyFilesBuildPhase = createPBXCopyFilesBuildPhase(8, + "/usr/share/man/man1", "0", new ArrayList(), true); + objects.put(copyFilesBuildPhase.getID(), copyFilesBuildPhase.getProperties()); + buildPhases.add(copyFilesBuildPhase); + + List buildRules = new ArrayList(); + + List dependencies = new ArrayList(); + + String productInstallPath = "$(HOME)/bin"; + + String productType = getProductType(linkTarget); + + PBXObjectRef nativeTarget = createPBXNativeTarget(projectName, + buildConfigurations, buildPhases, buildRules, dependencies, + productInstallPath, projectName, product, productType); + objects.put(nativeTarget.getID(), nativeTarget.getProperties()); + + return nativeTarget; } - - - String[] linkerArgs = null; - ProcessorConfiguration linkConfig = linkTarget.getConfiguration(); - if (linkConfig instanceof CommandLineLinkerConfiguration) { - linkerArgs = ((CommandLineLinkerConfiguration) linkConfig).getPreArguments(); + + private int getProductTypeIndex(final TargetInfo linkTarget) { + String outPath = linkTarget.getOutput().getPath(); + String outExtension = null; + int lastDot = outPath.lastIndexOf('.'); + if (lastDot != -1) { + outExtension = outPath.substring(lastDot); + } + if (".a".equalsIgnoreCase(outExtension) || ".lib".equalsIgnoreCase(outExtension)) { + return 1; + } else if (".dylib".equalsIgnoreCase(outExtension) || + ".so".equalsIgnoreCase(outExtension) || + ".dll".equalsIgnoreCase(outExtension)) { + return 2; + } + return 0; } - - writer.write(" INSTALL_PATH = /usr/local/lib;\n"); - if (linkerArgs != null) { - boolean hasLibPath = false; - for (int i = 0; i < linkerArgs.length; i++) { - if (linkerArgs[i].startsWith("-L")) { - if (!hasLibPath) { - writer.write(" LIBRARY_SEARCH_PATHS = \""); - hasLibPath = true; - } else { - writer.write(" "); - } - writer.write(linkerArgs[i].substring(2)); - } + private String getProductType(final TargetInfo linkTarget) { + switch(getProductTypeIndex(linkTarget)) { + case 1: + return "com.apple.product-type.library.static"; + case 2: + return "com.apple.product-type.library.dynamic"; + default: + return "com.apple.product-type.tool"; } - if (hasLibPath) { - writer.write("\";\n"); + } + + private String getFileType(final TargetInfo linkTarget) { + switch(getProductTypeIndex(linkTarget)) { + case 1: + return "archive.ar"; + case 2: + return "compiled.mach-o.dylib"; + default: + return "compiled.mach-o.executable"; } - } - writer.write(" LIBRARY_STYLE = DYNAMIC;\n"); - writer.write(" OTHER_CFLAGS = \"\";\n"); - writer.write(" OTHER_LDFLAGS = \""); - if (linkerArgs != null) { - String prepend = ""; - for (int i = 0; i < linkerArgs.length; i++) { - if (!linkerArgs[i].startsWith("-L")) { - writer.write(prepend); - writer.write(linkerArgs[i]); - prepend = " "; - } - } } - writer.write("\";\n"); - writer.write(" OTHER_REZFLAGS = \"\";\n"); - writer.write(" PRODUCT_NAME = testbsd;\n"); - writer.write(" SECTORDER_FLAGS = \"\";\n"); - writer.write(" WARNING_CFLAGS = \"-Wmost\";\n"); - writer.write(" };\n"); - writer.write(" dependencies = (\n"); - writer.write(" );\n"); - writer.write(" isa = PBXNativeTarget;\n"); - - writer.write(" name = "); - writer.write(outFile.getName()); - writer.write(";\n"); - writer.write(" productName = "); - writer.write(outFile.getName()); - writer.write(";\n"); - writer.write(" productReference = D2AAC0630554660B00DB518D;\n"); - - String productType = "com.apple.product-type.library.dynamic"; - String prefix = "lib"; - String suffix = ".dylib"; - String explicitFileType = "compiled.mach-o.dylib"; - String outType = task.getOuttype(); - if ("executable".equals(outType)) { - productType = "com.apple.product-type.tool"; - prefix = ""; - suffix = ""; - explicitFileType = "compiled.mach-o.executable"; - } else if ("static".equals(outType)) { - productType = "com.apple.product-type.library.static"; - suffix = ".a"; - explicitFileType = "archive.ar"; + + + /** + * Create PBXFileReference. + * @param sourceTree source tree. + * @param baseDir base directory. + * @param file file. + * @return PBXFileReference object. + */ + private static PBXObjectRef createPBXFileReference(final String sourceTree, + final String baseDir, + final File file) { + Map map = new HashMap(); + map.put("isa", "PBXFileReference"); + + String relPath = CUtil.toUnixPath(CUtil.getRelativePath(baseDir, file)); + map.put("path", relPath); + map.put("name", file.getName()); + map.put("sourceTree", sourceTree); + return new PBXObjectRef(map); + } + + /** + * Create PBXGroup. + * @param name group name. + * @param sourceTree source tree. + * @param children list of PBXFileReferences. + * @return group. + */ + private static PBXObjectRef createPBXGroup(final String name, + final String sourceTree, + final List children) { + Map map = new HashMap(); + map.put("isa", "PBXGroup"); + map.put("name", name); + map.put("sourceTree", sourceTree); + map.put("children", children); + return new PBXObjectRef(map); } - writer.write(" productType = \""); - writer.write(productType); - writer.write("\";\n"); - writer.write(" };\n"); - writer.write(" D2AAC0630554660B00DB518D = {\n"); - - writer.write(" explicitFileType = \""); - writer.write(explicitFileType); - writer.write("\";\n"); - writer.write(" includeInIndex = 0;\n"); - writer.write(" isa = PBXFileReference;\n"); - writer.write(" path = "); - writer.write(outFile.getName()); - writer.write(suffix); - writer.write(";\n"); - writer.write(" refType = 3;\n"); - writer.write(" sourceTree = BUILT_PRODUCTS_DIR;\n"); - writer.write(" };\n"); - writer.write(" };\n"); - writer.write(" rootObject = 08FB7793FE84155DC02AAC07;\n"); - writer.write(" }\n"); - - writer.close(); - } - - /** - * Gets the first recognized compiler from the - * compilation targets. - * @param targets compilation targets - * @return representative (hopefully) compiler configuration - */ - private CommandLineCompilerConfiguration - getBaseCompilerConfiguration(Hashtable targets) { - // - // find first target with an GNU C++ compilation - // - CommandLineCompilerConfiguration compilerConfig = null; - // - // get the first target and assume that it is representative - // - Iterator targetIter = targets.values().iterator(); - while (targetIter.hasNext()) { - TargetInfo targetInfo = (TargetInfo) targetIter.next(); - ProcessorConfiguration config = targetInfo.getConfiguration(); - String identifier = config.getIdentifier(); - // - // for the first cl compiler - // - if (config instanceof CommandLineCompilerConfiguration) { - compilerConfig = (CommandLineCompilerConfiguration) config; - if (compilerConfig.getCompiler() instanceof GccCCompiler) { - return compilerConfig; + + /** + * Create PBXProject. + * @param buildConfigurationList build configuration list. + * @param mainGroup main group. + * @param projectDirPath project directory path. + * @param targets targets. + * @param projectRoot projectRoot directory relative to + * @return project. + */ + private static PBXObjectRef createPBXProject(final PBXObjectRef buildConfigurationList, + final PBXObjectRef mainGroup, + final String projectDirPath, + final String projectRoot, + final List targets) { + Map map = new HashMap(); + map.put("isa", "PBXProject"); + map.put("buildConfigurationList", buildConfigurationList.getID()); + map.put("hasScannedForEncodings", "0"); + map.put("mainGroup", mainGroup.getID()); + map.put("projectDirPath", projectDirPath); + map.put("targets", targets); + map.put("projectRoot", projectRoot); + return new PBXObjectRef(map); + } + + /** + * Create XCConfigurationList. + * @param buildConfigurations build configurations. + * @return configuration list. + */ + private static PBXObjectRef createXCConfigurationList(final List buildConfigurations) { + Map map = new HashMap(); + map.put("isa", "XCConfigurationList"); + map.put("buildConfigurations", buildConfigurations); + return new PBXObjectRef(map); + } + + + /** + * Create XCBuildConfiguration. + * @param name name. + * @param buildSettings build settings. + * @return build configuration. + */ + private static PBXObjectRef createXCBuildConfiguration(final String name, + final Map buildSettings) { + Map map = new HashMap(); + map.put("isa", "XCBuildConfiguration"); + map.put("buildSettings", buildSettings); + map.put("name", name); + return new PBXObjectRef(map); + } + + /** + * Create PBXNativeTarget. + * @param name name. + * @param buildConfigurationList build configuration list. + * @param buildPhases build phases. + * @param buildRules build rules. + * @param dependencies dependencies. + * @param productInstallPath product install path. + * @param productName product name. + * @param productReference file reference for product. + * @param productType product type. + * @return native target. + */ + private static PBXObjectRef createPBXNativeTarget(final String name, + final PBXObjectRef buildConfigurationList, + final List buildPhases, + final List buildRules, + final List dependencies, + final String productInstallPath, + final String productName, + final PBXObjectRef productReference, + final String productType) { + Map map = new HashMap(); + map.put("isa", "PBXNativeTarget"); + map.put("buildConfigurationList", buildConfigurationList); + map.put("buildPhases", buildPhases); + map.put("buildRules", buildRules); + map.put("dependencies", dependencies); + map.put("name", name); + map.put("productInstallPath", productInstallPath); + map.put("productName", productName); + map.put("productReference", productReference); + map.put("productType", productType); + return new PBXObjectRef(map); + } + + /** + * Create PBXSourcesBuildPhase. + * @param buildActionMask build action mask. + * @param files source files. + * @param runOnly if true, phase should only be run on deployment. + * @return PBXSourcesBuildPhase. + */ + private static PBXObjectRef createPBXSourcesBuildPhase(int buildActionMask, + List files, + boolean runOnly) { + Map map = new HashMap(); + map.put("buildActionMask", + String.valueOf(buildActionMask)); + map.put("files", files); + map.put("isa", "PBXSourcesBuildPhase"); + map.put("runOnlyForDeploymentPostprocessing", toString(runOnly)); + return new PBXObjectRef(map); + } + + /** + * Create PBXBuildFile. + * @param fileRef source file. + * @param settings build settings. + * @return PBXBuildFile. + */ + private static PBXObjectRef createPBXBuildFile(PBXObjectRef fileRef, + Map settings) { + Map map = new HashMap(); + map.put("fileRef", fileRef); + map.put("isa", "PBXBuildFile"); + if (settings != null) { + map.put("settings", settings); } - } + return new PBXObjectRef(map); } - return null; - } - /** - * Source file with 96-bit source and build ID's. - */ - private static final class SourceEntry { /** - * Source file. + * Create PBXFrameworksBuildPhase. + * @param buildActionMask build action mask. + * @param files files. + * @param runOnly if true, phase should only be run on deployment. + * @return PBXFrameworkBuildPhase. */ - private final File file; + private static PBXObjectRef createPBXFrameworksBuildPhase( + final int buildActionMask, + final List files, + final boolean runOnly) { + Map map = new HashMap(); + map.put("isa", "PBXFrameworksBuildPhase"); + map.put("buildActionMask", NumberFormat.getIntegerInstance(Locale.US).format(buildActionMask)); + map.put("files", files); + map.put("runOnlyForDeploymentPostprocessing", toString(runOnly)); + return new PBXObjectRef(map); + } /** - * Source ID. + * Create a build phase that copies files to a destination. + * @param buildActionMask build action mask. + * @param dstPath destination path. + * @param dstSubfolderSpec subfolder spec. + * @param files files. + * @param runOnly if true, phase should only be run on deployment. + * @return PBXCopyFileBuildPhase. */ - private final String sourceID; + private static PBXObjectRef createPBXCopyFilesBuildPhase( + final int buildActionMask, + final String dstPath, + final String dstSubfolderSpec, + final List files, + final boolean runOnly) { + Map map = new HashMap(); + map.put("isa", "PBXCopyFilesBuildPhase"); + map.put("buildActionMask", NumberFormat.getIntegerInstance(Locale.US).format(buildActionMask)); + map.put("dstPath", dstPath); + map.put("dstSubfolderSpec", dstSubfolderSpec); + map.put("files", files); + map.put("runOnlyForDeploymentPostprocessing", toString(runOnly)); + return new PBXObjectRef(map); + } + /** - * Build step ID. + * Create a proxy for a file in a different project. + * @param containerPortal XcodeProject containing file. + * @param proxyType proxy type. + * @return PBXContainerItemProxy. */ - private final String buildID; + private static PBXObjectRef createPBXContainerItemProxy( + final PBXObjectRef containerPortal, + final int proxyType, + final String remoteInfo) { + Map map = new HashMap(); + map.put("isa", "PBXContainerItemProxy"); + map.put("containerPortal", containerPortal); + map.put("proxyType", NumberFormat.getIntegerInstance(Locale.US).format(proxyType)); + map.put("remoteInfo", remoteInfo); + return new PBXObjectRef(map); + } + /** - * Constructor. - * @param fileArg source file - * @param sourceIDArg source ID - * @param buildIDArg build step ID + * Create a proxy for a file in a different project. + * @param remoteRef PBXContainerItemProxy for reference. + * @param dependency dependency. + * @return PBXContainerItemProxy. */ - public SourceEntry(final File fileArg, - final String sourceIDArg, - final String buildIDArg) { - file = fileArg; - sourceID = sourceIDArg; - buildID = buildIDArg; + private static PBXObjectRef createPBXReferenceProxy( + final PBXObjectRef remoteRef, + final DependencyDef dependency) { + Map map = new HashMap(); + map.put("isa", "PBXReferenceProxy"); + String fileType = "compiled.mach-o.dylib"; + map.put("fileType", fileType); + map.put("remoteRef", remoteRef); + map.put("path", dependency.getFile().getName() + ".dylib"); + map.put("sourceTree", "BUILT_PRODUCTS_DIR"); + return new PBXObjectRef(map); } /** - * Get source file. - * @return source file + * Method returns "1" for true, "0" for false. + * @param b boolean value. + * @return "1" for true, "0" for false. */ - public File getFile() { - return file; + private static String toString(boolean b) { + if (b) { + return "1"; + } else { + return "0"; + } } /** - * Get source ID. - * @return source ID + * Represents a property map with an 96 bit identity. + * When placed in a property list, this object will + * output the string representation of the identity + * which XCode uses to find the corresponding property + * bag in the "objects" property of the top-level property list. */ - public String getSourceID() { - return sourceID; + private static final class PBXObjectRef { + /** + * Identifier. + */ + private final String id; + /** + * Properties. + */ + private final Map properties; + /** + * Next available identifier. + */ + private static int nextID = 0; + + /** + * Create reference. + * @param props properties. + */ + public PBXObjectRef(final Map props) { + if (props == null) { + throw new NullPointerException("props"); + } + StringBuffer buf = new StringBuffer("000000000000000000000000"); + String idStr = Integer.toHexString(nextID++); + buf.replace(buf.length() - idStr.length(), buf.length(), idStr); + id = buf.toString(); + properties = props; + } + + /** + * Get object identifier. + * @return identifier. + */ + public String toString() { + return id; + } + + /** + * Get object identifier. + * @return object identifier. + */ + public String getID() { + return id; + } + + /** + * Get properties. + * @return properties. + */ + public Map getProperties() { + return properties; + } } /** - * Get build step ID. - * @return build step ID + * Gets the first recognized compiler from the + * compilation targets. + * + * @param targets compilation targets + * @return representative (hopefully) compiler configuration */ - public String getBuildID() { - return buildID; + private CommandLineCompilerConfiguration + getBaseCompilerConfiguration(Hashtable targets) { + // + // find first target with an GNU C++ compilation + // + CommandLineCompilerConfiguration compilerConfig; + // + // get the first target and assume that it is representative + // + Iterator targetIter = targets.values().iterator(); + while (targetIter.hasNext()) { + TargetInfo targetInfo = (TargetInfo) targetIter.next(); + ProcessorConfiguration config = targetInfo.getConfiguration(); + // + // for the first cl compiler + // + if (config instanceof CommandLineCompilerConfiguration) { + compilerConfig = (CommandLineCompilerConfiguration) config; + if (compilerConfig.getCompiler() instanceof GccCCompiler) { + return compilerConfig; + } + } + } + return null; } - } + } diff --git a/src/main/java/net/sf/antcontrib/cpptasks/arm/ADSCCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/arm/ADSCCompiler.java index c7e12d5..11004ad 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/arm/ADSCCompiler.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/arm/ADSCCompiler.java @@ -112,11 +112,7 @@ public class ADSCCompiler extends CommandLineCCompiler { null, newEnvironment, env); } /** - * Adds command switches for generic configuration options - * - * @see net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler#addImpliedArgs(java.util.Vector, - * boolean, boolean, boolean, - * net.sf.antcontrib.cpptasks.compiler.LinkType) + * {@inheritDoc} */ protected void addImpliedArgs(Vector args, final boolean debug, diff --git a/src/main/java/net/sf/antcontrib/cpptasks/borland/BorlandLibrarian.java b/src/main/java/net/sf/antcontrib/cpptasks/borland/BorlandLibrarian.java index 6ec9212..703ddd3 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/borland/BorlandLibrarian.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/borland/BorlandLibrarian.java @@ -100,12 +100,12 @@ public class BorlandLibrarian extends CommandLineLinker { /** * Prepares argument list for exec command. * - * @param outputFile - * linker output file + * @param outputDir linker output directory + * @param outputName linker output name * @param sourceFiles * linker input files (.obj, .o, .res) - * @param args - * linker arguments + * @param config + * linker configuration * @return arguments for runTask */ protected String[] prepareArguments( @@ -208,7 +208,7 @@ public class BorlandLibrarian extends CommandLineLinker { * Encloses problematic file names within quotes. * @param buf string buffer * @param filename source file name - * @returns filename potentially enclosed in quotes. + * @return filename potentially enclosed in quotes. */ protected String quoteFilename(StringBuffer buf,String filename) { buf.setLength(0); diff --git a/src/main/java/net/sf/antcontrib/cpptasks/borland/BorlandLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/borland/BorlandLinker.java index 315761f..6a28805 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/borland/BorlandLinker.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/borland/BorlandLinker.java @@ -136,12 +136,12 @@ public final class BorlandLinker extends CommandLineLinker { /** * Prepares argument list for exec command. * - * @param outputFile - * linker output file + * @param outputDir linker output directory + * @param outputName linker output name * @param sourceFiles * linker input files (.obj, .o, .res) - * @param args - * linker arguments + * @param config + * linker configuration * @return arguments for runTask */ protected String[] prepareArguments( @@ -277,7 +277,7 @@ public final class BorlandLinker extends CommandLineLinker { * @param versionInfo version information * @param linkType link type * @param isDebug true if debug build - * @param executableName name of generated executable + * @param outputFile name of generated executable * @param objDir directory for generated files * @param matcher bidded fileset */ diff --git a/src/main/java/net/sf/antcontrib/cpptasks/borland/BorlandProcessor.java b/src/main/java/net/sf/antcontrib/cpptasks/borland/BorlandProcessor.java index 6143bda..b14c854 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/borland/BorlandProcessor.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/borland/BorlandProcessor.java @@ -61,8 +61,8 @@ public final class BorlandProcessor { * Tool name, for example, "bcc32", "brc32", "ilink32" * @param switchChar * Command line switch character, for example "L" for libraries - * @param defaultRelativePaths - * default paths relative to executable directory + * @param defaultRelativePath + * default path relative to executable directory * @return path */ public static File[] getEnvironmentPath(String toolName, char switchChar, diff --git a/src/main/java/net/sf/antcontrib/cpptasks/compiler/AbstractCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/compiler/AbstractCompiler.java index e61bd64..2d1401f 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/compiler/AbstractCompiler.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/compiler/AbstractCompiler.java @@ -129,7 +129,6 @@ public abstract class AbstractCompiler extends AbstractProcessor * used to distinguish DependencyInfo's from different include * path settings * - * @author Curt Arnold */ public final DependencyInfo parseIncludes(CCTask task, File source, File[] includePath, File[] sysIncludePath, File[] envIncludePath, diff --git a/src/main/java/net/sf/antcontrib/cpptasks/compiler/AbstractLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/compiler/AbstractLinker.java index 9de9491..5d9cefa 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/compiler/AbstractLinker.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/compiler/AbstractLinker.java @@ -95,7 +95,7 @@ public abstract class AbstractLinker extends AbstractProcessor * @param versionInfo version information * @param linkType link type * @param isDebug true if debug build - * @param executableName name of generated executable + * @param outputFile name of generated executable * @param objDir directory for generated files * @param matcher bidded fileset */ diff --git a/src/main/java/net/sf/antcontrib/cpptasks/compiler/CaptureStreamHandler.java b/src/main/java/net/sf/antcontrib/cpptasks/compiler/CaptureStreamHandler.java index f58ed8e..24a0193 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/compiler/CaptureStreamHandler.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/compiler/CaptureStreamHandler.java @@ -26,7 +26,6 @@ import java.util.Vector; import org.apache.tools.ant.taskdefs.Execute; import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; - /** * Implements ExecuteStreamHandler to capture the output of a Execute to an * array of strings diff --git a/src/main/java/net/sf/antcontrib/cpptasks/compiler/CommandLineCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/compiler/CommandLineCompiler.java index a8b7691..46ec59a 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/compiler/CommandLineCompiler.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/compiler/CommandLineCompiler.java @@ -73,9 +73,7 @@ public abstract class CommandLineCompiler extends AbstractCompiler { * include switches to that vector (for use in building a configuration * identifier that is consistent between machines). * - * @param baseDirPaths - * A vector containing the parts of the working directory, - * produced by CUtil.DecomposeFile. + * @param baseDirPath Base directory path. * @param includeDirs * Array of include directory paths * @param args @@ -131,7 +129,6 @@ public abstract class CommandLineCompiler extends AbstractCompiler { /** * Compiles a source file. * - * @author Curt Arnold */ public void compile(CCTask task, File outputDir, String[] sourceFiles, String[] args, String[] endArgs, boolean relentless, @@ -285,6 +282,32 @@ public abstract class CommandLineCompiler extends AbstractCompiler { // add all appropriate defines and undefines // buildDefineArguments(defaultProviders, args); + int warnings = specificDef.getWarnings(defaultProviders, 0); + addWarningSwitch(args, warnings); + Enumeration argEnum = cmdArgs.elements(); + int endCount = 0; + while (argEnum.hasMoreElements()) { + CommandLineArgument arg = (CommandLineArgument) argEnum + .nextElement(); + switch (arg.getLocation()) { + case 1 : + args.addElement(arg.getValue()); + break; + case 2 : + endCount++; + break; + } + } + String[] endArgs = new String[endCount]; + argEnum = cmdArgs.elements(); + int index = 0; + while (argEnum.hasMoreElements()) { + CommandLineArgument arg = (CommandLineArgument) argEnum + .nextElement(); + if (arg.getLocation() == 2) { + endArgs[index++] = arg.getValue(); + } + } // // Want to have distinct set of arguments with relative // path names for includes that are used to build @@ -327,37 +350,14 @@ public abstract class CommandLineCompiler extends AbstractCompiler { addIncludes(baseDirPath, sysIncPath, args, null, null); StringBuffer buf = new StringBuffer(getIdentifier()); for (int i = 0; i < relativeArgs.size(); i++) { + buf.append(' '); buf.append(relativeArgs.elementAt(i)); + } + for (int i = 0; i < endArgs.length; i++) { buf.append(' '); + buf.append(endArgs[i]); } - buf.setLength(buf.length() - 1); String configId = buf.toString(); - int warnings = specificDef.getWarnings(defaultProviders, 0); - addWarningSwitch(args, warnings); - Enumeration argEnum = cmdArgs.elements(); - int endCount = 0; - while (argEnum.hasMoreElements()) { - CommandLineArgument arg = (CommandLineArgument) argEnum - .nextElement(); - switch (arg.getLocation()) { - case 1 : - args.addElement(arg.getValue()); - break; - case 2 : - endCount++; - break; - } - } - String[] endArgs = new String[endCount]; - argEnum = cmdArgs.elements(); - int index = 0; - while (argEnum.hasMoreElements()) { - CommandLineArgument arg = (CommandLineArgument) argEnum - .nextElement(); - if (arg.getLocation() == 2) { - endArgs[index++] = arg.getValue(); - } - } String[] argArray = new String[args.size()]; args.copyInto(argArray); boolean rebuild = specificDef.getRebuild(baseDefs, 0); diff --git a/src/main/java/net/sf/antcontrib/cpptasks/compiler/CommandLineLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/compiler/CommandLineLinker.java index aeed2bb..93c3e1e 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/compiler/CommandLineLinker.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/compiler/CommandLineLinker.java @@ -286,9 +286,10 @@ public abstract class CommandLineLinker extends AbstractLinker * Prepares argument list for exec command. Will return null * if command line would exceed allowable command line buffer. * + * @param task compilation task. * @param outputFile linker output file * @param sourceFiles linker input files (.obj, .o, .res) - * @param args linker arguments + * @param config linker configuration * @return arguments for runTask */ protected String[] prepareArguments( @@ -324,7 +325,7 @@ public abstract class CommandLineLinker extends AbstractLinker } for (int i = 0; i < endargs.length; i++) { allArgs[index++] = decorateLinkerOption(buf, endargs[i]); - } + } return allArgs; } @@ -338,7 +339,7 @@ public abstract class CommandLineLinker extends AbstractLinker new File(sourceFile)); // FREEHEP, return the shortest // return quoteFilename(buf, sourceFile.length() > relativePath.length() ? relativePath : sourceFile); -// FREEHEP trying with always absolute paths... +// FREEHEP trying with always absolute paths, as Windows relPaths have a tighter restriction on length than absPaths... return quoteFilename(buf, sourceFile); } diff --git a/src/main/java/net/sf/antcontrib/cpptasks/compiler/LinkType.java b/src/main/java/net/sf/antcontrib/cpptasks/compiler/LinkType.java index 7df5d98..67d7e6b 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/compiler/LinkType.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/compiler/LinkType.java @@ -113,8 +113,7 @@ public class LinkType { /** * Sets the output type (execuable, shared, etc). * - * @param outputType, - * may not be null + * @param outputType may not be null */ public void setOutputType(OutputTypeEnum outputType) { if (outputType == null) { diff --git a/src/main/java/net/sf/antcontrib/cpptasks/compiler/Linker.java b/src/main/java/net/sf/antcontrib/cpptasks/compiler/Linker.java index 672a0e3..0638a70 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/compiler/Linker.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/compiler/Linker.java @@ -67,7 +67,7 @@ public interface Linker extends Processor { * @param versionInfo version information * @param linkType link type * @param isDebug true if debug build - * @param executableName name of generated executable + * @param outputFile name of generated executable * @param objDir directory for generated files * @param matcher bidded fileset */ diff --git a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudio2005CCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudio2005CCompiler.java new file mode 100644 index 0000000..8df73bd --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudio2005CCompiler.java @@ -0,0 +1,62 @@ +/* + * + * Copyright 2002-2007 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; + +import org.apache.tools.ant.types.Environment; + +/** + * Adapter for the Microsoft(r) C/C++ 8 Optimizing Compiler + * + * @author David Haney + */ +public final class DevStudio2005CCompiler extends DevStudioCompatibleCCompiler { + private static final DevStudio2005CCompiler instance = new DevStudio2005CCompiler( + "cl", false, null); + public static DevStudio2005CCompiler getInstance() { + return instance; + } + private DevStudio2005CCompiler(String command, boolean newEnvironment, + Environment env) { + super(command, "/bogus", newEnvironment, env); + } + /** + * Override the default debug flags to use VC 8 compatible versions. + */ + protected void addDebugSwitch(Vector args) { + args.addElement("/Zi"); + args.addElement("/Od"); + args.addElement("/RTC1"); + args.addElement("/D_DEBUG"); + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new DevStudio2005CCompiler(getCommand(), newEnvironment, env); + } + return this; + } + public Linker getLinker(LinkType type) { + return DevStudioLinker.getInstance().getLinker(type); + } + public int getMaximumCommandLength() { + return 32767; + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleCCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleCCompiler.java index dc1afb3..cc4493d 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleCCompiler.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleCCompiler.java @@ -72,11 +72,7 @@ public abstract class DevStudioCompatibleCCompiler } if (debug) { mindex += 1; -// FREEHEP changed /Zi into /Z7 - args.addElement("/Zi"); - args.addElement("/Od"); - args.addElement("/GZ"); - args.addElement("/D_DEBUG"); + addDebugSwitch(args); } else { if (optimization != null) { if (optimization.isSize()) { @@ -98,6 +94,12 @@ public abstract class DevStudioCompatibleCCompiler args.addElement("/GR"); } } + protected void addDebugSwitch(Vector args) { + args.addElement("/Zi"); + args.addElement("/Od"); + args.addElement("/GZ"); + args.addElement("/D_DEBUG"); + } protected void addWarningSwitch(Vector args, int level) { DevStudioProcessor.addWarningSwitch(args, level); } diff --git a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLinker.java index 88ecd78..987948b 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLinker.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLinker.java @@ -134,7 +134,7 @@ public abstract class DevStudioCompatibleLinker extends CommandLineLinker { * @param versionInfo version information * @param linkType link type * @param isDebug true if debug build - * @param executableName name of generated executable + * @param outputFile name of generated executable * @param objDir directory for generated files * @param matcher bidded fileset */ diff --git a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioProjectWriter.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioProjectWriter.java index 94030fb..51ab1dd 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioProjectWriter.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioProjectWriter.java @@ -1,6 +1,6 @@ /* * - * Copyright 2004 The Ant-Contrib project + * Copyright 2004-2008 The Ant-Contrib project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,27 +16,26 @@ */ package net.sf.antcontrib.cpptasks.devstudio; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.Writer; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.List; - import net.sf.antcontrib.cpptasks.CCTask; import net.sf.antcontrib.cpptasks.CUtil; import net.sf.antcontrib.cpptasks.TargetInfo; import net.sf.antcontrib.cpptasks.compiler.CommandLineCompilerConfiguration; import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; import net.sf.antcontrib.cpptasks.compiler.ProcessorConfiguration; +import net.sf.antcontrib.cpptasks.ide.DependencyDef; import net.sf.antcontrib.cpptasks.ide.ProjectDef; import net.sf.antcontrib.cpptasks.ide.ProjectWriter; +import net.sf.antcontrib.cpptasks.ide.CommentDef; import org.apache.tools.ant.BuildException; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.*; +import java.text.MessageFormat; + /** * Writes a Microsoft Visual Studio 97 or Visual Studio 6 project file. * @@ -60,6 +59,24 @@ public final class DevStudioProjectWriter this.version = versionArg; } + private static String toProjectName(final String name) { + // + // some characters are apparently not allowed in VS project names + // but have not been able to find them documented + // limiting characters to alphas, numerics and hyphens + StringBuffer projectNameBuf = new StringBuffer(name); + for (int i = 0; i < projectNameBuf.length(); i++) { + final char ch = projectNameBuf.charAt(i); + if (!((ch >= 'a' && ch <= 'z') + || (ch >= 'A' && ch <= 'Z') + || (ch >= '0' && ch <= '9'))) { + projectNameBuf.setCharAt(i, '_'); + } + } + return projectNameBuf.toString(); + + } + /** * Writes a project definition file. * @param fileName File name base, writer may append appropriate extension @@ -81,22 +98,12 @@ public final class DevStudioProjectWriter // some characters are apparently not allowed in VS project names // but have not been able to find them documented // limiting characters to alphas, numerics and hyphens - StringBuffer projectNameBuf; String projectName = projectDef.getName(); if (projectName != null) { - projectNameBuf = new StringBuffer(projectName); + projectName = toProjectName(projectName); } else { - projectNameBuf = new StringBuffer(fileName.getName()); - } - for (int i = 0; i < projectNameBuf.length(); i++) { - final char ch = projectNameBuf.charAt(i); - if (!((ch >= 'a' && ch <= 'z') - || (ch >= 'A' && ch <= 'Z') - || (ch >= '0' && ch <= '9'))) { - projectNameBuf.setCharAt(i, '_'); - } + projectName = toProjectName(fileName.getName()); } - projectName = projectNameBuf.toString(); final String basePath = fileName.getAbsoluteFile().getParent(); @@ -128,15 +135,11 @@ public final class DevStudioProjectWriter writer.write(this.version); writer.write("\r\n"); writer.write("# ** DO NOT EDIT **\r\n\r\n"); + + writeComments(writer, projectDef.getComments()); + String outputType = task.getOuttype(); String subsystem = task.getSubsystem(); - String configName = projectName; - final boolean isDebug = task.getDebug(); - if (isDebug) { - configName += " - Win32 Debug"; - } else { - configName += " - Win32 Release"; - } String targtype = "Win32 (x86) Dynamic-Link Library"; String targid = "0x0102"; if ("executable".equals(outputType)) { @@ -156,10 +159,11 @@ public final class DevStudioProjectWriter writer.write("\" "); writer.write(targid); writer.write("\r\n\r\nCFG="); - writer.write(configName); + + writer.write(projectName + " - Win32 Debug"); writer.write("\r\n"); - writeMessage(writer, projectName, configName, targtype); + writeMessage(writer, projectName, targtype); writer.write("# Begin Project\r\n"); if (version.equals("6.00")) { @@ -170,59 +174,22 @@ public final class DevStudioProjectWriter writer.write("CPP=cl.exe\r\n"); writer.write("MTL=midl.exe\r\n"); writer.write("RSC=rc.exe\r\n"); - writer.write("# PROP BASE Use_MFC 0\r\n"); - writer.write("# PROP BASE Use_Debug_Libraries "); - if (isDebug) { - writer.write("1\r\n"); - } else { - writer.write("0\r\n"); - } + writer.write("\r\n!IF \"$(CFG)\" == \"" + projectName + " - Win32 Release\"\r\n"); + + writeConfig(writer, false, projectDef.getDependencies(), basePath, compilerConfig, linkTarget, targets); + + writer.write("\r\n!ELSEIF \"$(CFG)\" == \"" + projectName + " - Win32 Debug\"\r\n"); + + writeConfig(writer, true, projectDef.getDependencies(), basePath, compilerConfig, linkTarget, targets); + + writer.write("\r\n!ENDIF\r\n"); - File objDir = task.getObjdir(); - String objDirPath = CUtil.getRelativePath(basePath, objDir); - - File outFile = task.getOutfile(); - File buildDir = outFile.getParentFile(); - String buildDirPath = CUtil.getRelativePath(basePath, buildDir); - - writer.write("# PROP BASE Output_Dir \""); - writer.write(buildDirPath); - writer.write("\"\r\n"); - writer.write("# PROP BASE Intermediate_Dir \""); - writer.write(objDirPath); - writer.write("\"\r\n"); - writer.write("# PROP BASE Target_Dir \"\"\r\n"); - writer.write("# PROP Use_MFC 0\r\n"); - writer.write("# PROP Use_Debug_Libraries "); - if (isDebug) { - writer.write("1\r\n"); - } else { - writer.write("0\r\n"); - } - writer.write("# PROP Output_Dir \""); - writer.write(buildDirPath); - writer.write("\"\r\n"); - writer.write("# PROP Intermediate_Dir \""); - writer.write(objDirPath); - writer.write("\"\r\n"); - writer.write("# PROP Target_Dir \"\"\r\n"); - writeCompileOptions(writer, basePath, compilerConfig); - writer.write( - "# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o NUL /win32\r\n"); - writer.write( - "# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o NUL /win32\r\n"); - writer.write("# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\r\n"); - writer.write("# ADD RSC /l 0x409 /d \"_DEBUG\"\r\n"); - writer.write("BSC32=bscmake.exe\r\n"); - writer.write("# ADD BASE BSC32 /nologo\r\n"); - writer.write("# ADD BSC32 /nologo\r\n"); - writer.write("LINK32=link.exe\r\n"); - writeLinkOptions(writer, basePath, linkTarget, targets); writer.write("# Begin Target\r\n\r\n"); - writer.write("# Name \""); - writer.write(configName); - writer.write("\"\r\n"); + writer.write("# Name \"" + projectName + " - Win32 Release\"\r\n"); + writer.write("# Name \"" + projectName + " - Win32 Debug\"\r\n"); + + File[] sortedSources = getSources(files); @@ -277,30 +244,128 @@ public final class DevStudioProjectWriter // write workspace file // writer = new BufferedWriter(new FileWriter(dswFile)); + writeWorkspace(writer, projectDef, projectName, dspFile); + writer.close(); - writer.write("Microsoft Developer Studio Workspace File, Format Version "); - writer.write(version); - writer.write("\r\n"); - writer.write("# WARNING: DO NOT EDIT OR DELETE"); - writer.write(" THIS WORKSPACE FILE!\r\n\r\n"); + } - writer.write("############################################"); - writer.write("###################################\r\n\r\n"); - writer.write("Project: \"" + projectName + "\"=.\\" - + dspFile.getName() - + " - Package Owner=<4>\r\n\r\n"); + private void writeConfig(final Writer writer, + boolean isDebug, + final List dependencies, + final String basePath, + CommandLineCompilerConfiguration compilerConfig, + TargetInfo linkTarget, + Hashtable targets) throws IOException { + writer.write("# PROP BASE Use_MFC 0\r\n"); + + String configType = "Release"; + String configInt = "0"; + String configMacro = "NDEBUG"; + if (isDebug) { + configType = "Debug"; + configInt = "1"; + configMacro = "_DEBUG"; + } - writer.write("Package=<5>\r\n{{{\r\n}}}\r\n\r\n"); - writer.write("Package=<4>\r\n{{{\r\n}}}\r\n\r\n"); - writer.write("######################################"); - writer.write("#########################################\r\n\r\n"); + writer.write("# PROP BASE Use_Debug_Libraries "); + writer.write(configInt); + writer.write("\r\n# PROP BASE Output_Dir \""); + writer.write(configType); + writer.write("\"\r\n"); + writer.write("# PROP BASE Intermediate_Dir \""); + writer.write(configType); + writer.write("\"\r\n"); + writer.write("# PROP BASE Target_Dir \"\"\r\n"); + writer.write("# PROP Use_MFC 0\r\n"); + writer.write("# PROP Use_Debug_Libraries "); + writer.write(configInt); + writer.write("\r\n# PROP Output_Dir \""); + writer.write(configType); + writer.write("\"\r\n"); + writer.write("# PROP Intermediate_Dir \""); + writer.write(configType); + writer.write("\"\r\n"); + writer.write("# PROP Target_Dir \"\"\r\n"); + writeCompileOptions(writer, isDebug, basePath, compilerConfig); + writer.write( + "# ADD BASE MTL /nologo /D \"" + configMacro + "\" /mktyplib203 /o NUL /win32\r\n"); + writer.write( + "# ADD MTL /nologo /D \"" + configMacro + "\" /mktyplib203 /o NUL /win32\r\n"); + writer.write("# ADD BASE RSC /l 0x409 /d \"" + configMacro + "\"\r\n"); + writer.write("# ADD RSC /l 0x409 /d \"" + configMacro + "\"\r\n"); + writer.write("BSC32=bscmake.exe\r\n"); + writer.write("# ADD BASE BSC32 /nologo\r\n"); + writer.write("# ADD BSC32 /nologo\r\n"); + writer.write("LINK32=link.exe\r\n"); + writeLinkOptions(writer, isDebug, dependencies, basePath, linkTarget, targets); + } + private static void writeWorkspaceProject(final Writer writer, + final String projectName, + final String projectFile, + final List dependsOn) throws IOException { + writer.write("############################################"); + writer.write("###################################\r\n\r\n"); + String file = projectFile; + if(!file.startsWith(".") && !file.startsWith("\\") && !file.startsWith("/")) { + file = ".\\" + file; + } + writer.write("Project: \"" + projectName + "\"=\"" + + file + + "\" - Package Owner=<4>\r\n\r\n"); + + writer.write("Package=<5>\r\n{{{\r\n}}}\r\n\r\n"); + writer.write("Package=<4>\r\n{{{\r\n"); + if (dependsOn != null) { + for(Iterator iter = dependsOn.iterator(); iter.hasNext();) { + writer.write(" Begin Project Dependency\r\n"); + writer.write(" Project_Dep_Name " + toProjectName(String.valueOf(iter.next())) + "\r\n"); + writer.write(" End Project Dependency\r\n"); + } + } + writer.write("}}}\r\n\r\n"); - writer.write("Global:\r\n\r\nPackage=<5>\r\n{{{\r\n}}}"); - writer.write("\r\n\r\nPackage=<3>\r\n{{{\r\n}}}\r\n\r\n"); + } + + private void writeWorkspace(final Writer writer, + final ProjectDef project, + final String projectName, + final File dspFile) throws IOException { + + writer.write("Microsoft Developer Studio Workspace File, Format Version "); + writer.write(version); + writer.write("\r\n"); + writer.write("# WARNING: DO NOT EDIT OR DELETE"); + writer.write(" THIS WORKSPACE FILE!\r\n\r\n"); + + writeComments(writer, project.getComments()); + + + List dependencies = project.getDependencies(); + List projectDeps = new ArrayList(); + String basePath = dspFile.getParent(); + for(Iterator iter = dependencies.iterator(); iter.hasNext();) { + DependencyDef dep = (DependencyDef) iter.next(); + if (dep.getFile() != null) { + String projName = toProjectName(dep.getName()); + projectDeps.add(projName); + String depProject = CUtil.toWindowsPath( + CUtil.getRelativePath(basePath, + new File(dep.getFile() + ".dsp"))); + writeWorkspaceProject(writer, projName, depProject, dep.getDependsList()); + } + } + + writeWorkspaceProject(writer, projectName, dspFile.getName(), projectDeps); + + writer.write("############################################"); + writer.write("###################################\r\n\r\n"); - writer.write("########################################"); - writer.write("#######################################\r\n\r\n"); - writer.close(); + + writer.write("Global:\r\n\r\nPackage=<5>\r\n{{{\r\n}}}"); + writer.write("\r\n\r\nPackage=<3>\r\n{{{\r\n}}}\r\n\r\n"); + + writer.write("########################################"); + writer.write("#######################################\r\n\r\n"); } @@ -344,7 +409,7 @@ public final class DevStudioProjectWriter && !relativePath.startsWith("\\")) { relativePath = ".\\" + relativePath; } - writer.write(relativePath); + writer.write(CUtil.toWindowsPath(relativePath)); writer.write("\r\n# End Source File\r\n"); } @@ -368,14 +433,12 @@ public final class DevStudioProjectWriter * Writes "This is not a makefile" warning. * @param writer Writer writer * @param projectName String project name - * @param configName String configuration name * @param targtype String target type * @throws IOException if error writing project */ private void writeMessage(final Writer writer, final String projectName, - final String configName, final String targtype) throws IOException { writer.write( "!MESSAGE This is not a valid makefile. "); @@ -395,16 +458,14 @@ public final class DevStudioProjectWriter writer.write("!MESSAGE NMAKE /f \""); writer.write(projectName); writer.write(".mak\" CFG=\""); - writer.write(configName); - writer.write("\"\r\n"); + writer.write(projectName); + writer.write(" - Win32 Debug\"\r\n"); writer.write("!MESSAGE \r\n"); writer.write("!MESSAGE Possible choices for configuration are:\r\n"); writer.write("!MESSAGE \r\n"); - writer.write("!MESSAGE \""); - writer.write(configName); - writer.write("\" (based on \""); - writer.write(targtype); - writer.write("\")\r\n"); + String pattern = "!MESSAGE \"{0} - Win32 {1}\" (based on \"{2}\")\r\n"; + writer.write(MessageFormat.format(pattern, new Object[] { projectName, "Release", targtype })); + writer.write(MessageFormat.format(pattern, new Object[] { projectName, "Debug", targtype })); writer.write("!MESSAGE \r\n"); writer.write("\r\n"); @@ -421,7 +482,7 @@ public final class DevStudioProjectWriter // // find first target with an DevStudio C compilation // - CommandLineCompilerConfiguration compilerConfig = null; + CommandLineCompilerConfiguration compilerConfig; // // get the first target and assume that it is representative // @@ -429,7 +490,6 @@ public final class DevStudioProjectWriter while (targetIter.hasNext()) { TargetInfo targetInfo = (TargetInfo) targetIter.next(); ProcessorConfiguration config = targetInfo.getConfiguration(); - String identifier = config.getIdentifier(); // // for the first cl compiler // @@ -446,11 +506,13 @@ public final class DevStudioProjectWriter /** * Writes compiler options. * @param writer Writer writer + * @param isDebug true if debug. * @param baseDir String base directory * @param compilerConfig compiler configuration * @throws IOException if error on writing project */ private void writeCompileOptions(final Writer writer, + final boolean isDebug, final String baseDir, final CommandLineCompilerConfiguration compilerConfig) throws IOException { @@ -462,9 +524,34 @@ public final class DevStudioProjectWriter for (int i = 0; i < includePath.length; i++) { options.append(" /I \""); String relPath = CUtil.getRelativePath(baseDir, includePath[i]); - options.append(relPath); + options.append(CUtil.toWindowsPath(relPath)); options.append('"'); } + Hashtable optionMap = new Hashtable(); + + if (isDebug) { + // + // release options that should be mapped to debug counterparts + // + optionMap.put("/MT", "/MTd"); + optionMap.put("/ML", "/MLd"); + optionMap.put("/MD", "/MDd"); + optionMap.put("/O2", "/Od"); + optionMap.put("/O3", "/Od"); + } else { + // + // debug options that should be mapped to release counterparts + // + optionMap.put("/MTD", "/MT"); + optionMap.put("/MLD", "/ML"); + optionMap.put("/MDD", "/MD"); + optionMap.put("/GM", ""); + optionMap.put("/ZI", ""); + optionMap.put("/OD", "/O2"); + optionMap.put("/GZ", ""); + } + + String[] preArgs = compilerConfig.getPreArguments(); for (int i = 0; i < preArgs.length; i++) { @@ -476,15 +563,30 @@ public final class DevStudioProjectWriter options.append(body); baseOptions.append(body); } else { - options.append('"'); - options.append(body); - options.append('"'); + StringBuffer buf = new StringBuffer("\""); + if ("NDEBUG".equals(body) || "_DEBUG".equals(body)) { + if (isDebug) { + buf.append("_DEBUG"); + } else { + buf.append("NDEBUG"); + } + } else { + buf.append(body); + } + buf.append("\""); + options.append(buf); + baseOptions.append(buf); } } else if (!preArgs[i].startsWith("/I")) { + String option = preArgs[i]; + String key = option.toUpperCase(Locale.US); + if (optionMap.containsKey(key)) { + option = optionMap.get(key).toString(); + } options.append(" "); - options.append(preArgs[i]); + options.append(option); baseOptions.append(" "); - baseOptions.append(preArgs[i]); + baseOptions.append(option); } } baseOptions.append("\r\n"); @@ -494,15 +596,22 @@ public final class DevStudioProjectWriter } + + + + /** * Writes link options. * @param writer Writer writer * @param basePath String base path + * @param dependencies project dependencies, used to suppress explicit linking. * @param linkTarget TargetInfo link target * @param targets Hashtable all targets * @throws IOException if unable to write to project file */ private void writeLinkOptions(final Writer writer, + final boolean isDebug, + final List dependencies, final String basePath, final TargetInfo linkTarget, final Hashtable targets) throws IOException { @@ -523,26 +632,51 @@ public final class DevStudioProjectWriter // if file was not compiled or otherwise generated // if (targets.get(linkSources[i].getName()) == null) { - String relPath = CUtil.getRelativePath(basePath, linkSources[i]); // - // if path has an embedded space then - // must quote - if (relPath.indexOf(' ') > 0) { - options.append(" \""); - options.append(relPath); - options.append("\""); - } else { - options.append(' '); - options.append(relPath); + // if source appears to be a system library or object file + // just output the name of the file (advapi.lib for example) + // otherwise construct a relative path. + // + String relPath = linkSources[i].getName(); + // + // check if file comes from a project dependency + // if it does it should not be explicitly linked + boolean fromDependency = false; + if (relPath.indexOf(".") > 0) { + String baseName = relPath.substring(0, relPath.indexOf(".")); + for(Iterator iter = dependencies.iterator(); iter.hasNext(); ) { + DependencyDef depend = (DependencyDef) iter.next(); + if (baseName.compareToIgnoreCase(depend.getName()) == 0) { + fromDependency = true; + } + } } + if (!fromDependency) { + if (!CUtil.isSystemPath(linkSources[i])) { + relPath = CUtil.getRelativePath(basePath, linkSources[i]); + } + // + // if path has an embedded space then + // must quote + if (relPath.indexOf(' ') > 0) { + options.append(" \""); + options.append(CUtil.toWindowsPath(relPath)); + options.append("\""); + } else { + options.append(' '); + options.append(CUtil.toWindowsPath(relPath)); + } + } } } String[] preArgs = linkConfig.getPreArguments(); for (int i = 0; i < preArgs.length; i++) { - options.append(' '); - options.append(preArgs[i]); - baseOptions.append(' '); - baseOptions.append(preArgs[i]); + if (isDebug || !preArgs[i].equals("/DEBUG")) { + options.append(' '); + options.append(preArgs[i]); + baseOptions.append(' '); + baseOptions.append(preArgs[i]); + } } String[] endArgs = linkConfig.getEndArguments(); for (int i = 0; i < endArgs.length; i++) { @@ -557,4 +691,20 @@ public final class DevStudioProjectWriter writer.write(baseOptions.toString()); writer.write(options.toString()); } + + private static void writeComments(final Writer writer, + final List comments) throws IOException { + for(Iterator iter = comments.iterator();iter.hasNext();) { + String comment = ((CommentDef) iter.next()).getText(); + if (comment != null) { + int start = 0; + for(int end = comment.indexOf('\n'); + end != -1; + end = comment.indexOf('\n', start)) { + writer.write("#" + comment.substring(start, end) + "\r\n"); + start = end + 1; + } + } + } + } } diff --git a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/VisualStudioNETProjectWriter.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/VisualStudioNETProjectWriter.java index 898503e..f554e09 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/VisualStudioNETProjectWriter.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/VisualStudioNETProjectWriter.java @@ -1,6 +1,6 @@ /* * - * Copyright 2004-2006 The Ant-Contrib project + * Copyright 2004-2008 The Ant-Contrib project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,10 +23,11 @@ import net.sf.antcontrib.cpptasks.compiler.CommandLineCompilerConfiguration; import net.sf.antcontrib.cpptasks.compiler.ProcessorConfiguration; import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; import net.sf.antcontrib.cpptasks.ide.ProjectDef; +import net.sf.antcontrib.cpptasks.ide.CommentDef; import net.sf.antcontrib.cpptasks.ide.ProjectWriter; +import net.sf.antcontrib.cpptasks.ide.DependencyDef; import org.apache.tools.ant.BuildException; import org.apache.xml.serialize.OutputFormat; -import org.apache.xml.serialize.Serializer; import org.apache.xml.serialize.XMLSerializer; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; @@ -88,18 +89,8 @@ public final class VisualStudioNETProjectWriter this.trueLiteral = trueArg; this.falseLiteral = falseArg; } + - /** - * Get configuration name. - * @param task cc task, may not be null. - * @return configuration name. - */ - private String getConfigurationName(final CCTask task) { - if (task.getDebug()) { - return "Debug|Win32"; - } - return "Release|Win32"; - } /** * Gets the configuration type. @@ -118,30 +109,6 @@ public final class VisualStudioNETProjectWriter return targtype; } - /** - * Get output directory. - * @param basePath path to parent of project file. - * @param task cc task, may not be null. - * @return output directory relative path. - */ - private String getOutputDirectory(final String basePath, - final CCTask task) { - File outFile = task.getOutfile(); - File buildDir = outFile.getParentFile(); - return CUtil.getRelativePath(basePath, buildDir); - } - - /** - * Get object file directory. - * @param basePath path to parent of project file. - * @param task cc task, may not be null. - * @return object file directory relative path. - */ - private String getIntermediateDirectory(final String basePath, - final CCTask task) { - File objDir = task.getObjdir(); - return CUtil.getRelativePath(basePath, objDir); - } /** @@ -167,23 +134,27 @@ public final class VisualStudioNETProjectWriter /** * Write the start tag of the Configuration element. * @param content serialization content handler. - * @param basePath path of directory containing project file. + * @param isDebug if true, write a debug configuration. * @param task cc task. * @param compilerConfig compiler configuration. * @throws SAXException thrown if serialization error. */ private void writeConfigurationStartTag(final ContentHandler content, - final String basePath, + final boolean isDebug, final CCTask task, final CommandLineCompilerConfiguration compilerConfig) throws SAXException { AttributesImpl attributes = new AttributesImpl(); - addAttribute(attributes, "Name", - getConfigurationName(task)); - addAttribute(attributes, "OutputDirectory", - getOutputDirectory(basePath, task)); - addAttribute(attributes, "IntermediateDirectory", - getIntermediateDirectory(basePath, task)); + if (isDebug) { + addAttribute(attributes, "Name", "Debug|Win32"); + addAttribute(attributes, "OutputDirectory", "Debug"); + addAttribute(attributes, "IntermediateDirectory", "Debug"); + } else { + addAttribute(attributes, "Name", "Release|Win32"); + addAttribute(attributes, "OutputDirectory", "Release"); + addAttribute(attributes, "IntermediateDirectory", "Release"); + + } addAttribute(attributes, "ConfigurationType", getConfigurationType(task)); addAttribute(attributes, "CharacterSet", @@ -221,19 +192,21 @@ public final class VisualStudioNETProjectWriter /** * Get value of AdditionalIncludeDirectories property. * @param compilerConfig compiler configuration. + * @param baseDir base for relative paths. * @return value of AdditionalIncludeDirectories property. */ private String getAdditionalIncludeDirectories( + final String baseDir, final CommandLineCompilerConfiguration compilerConfig) { + File[] includePath = compilerConfig.getIncludePath(); StringBuffer includeDirs = new StringBuffer(); - String[] args = compilerConfig.getPreArguments(); - for (int i = 0; i < args.length; i++) { - if (args[i].startsWith("/I")) { - includeDirs.append(args[i].substring(2)); - includeDirs.append(';'); - } + for (int i = 0; i < includePath.length; i++) { + String relPath = CUtil.getRelativePath(baseDir, includePath[i]); + includeDirs.append(CUtil.toWindowsPath(relPath)); + includeDirs.append(';'); } + if (includeDirs.length() > 0) { includeDirs.setLength(includeDirs.length() - 1); } @@ -243,15 +216,27 @@ public final class VisualStudioNETProjectWriter /** * Get value of PreprocessorDefinitions property. * @param compilerConfig compiler configuration. + * @param isDebug true if generating debug configuration. * @return value of PreprocessorDefinitions property. */ private String getPreprocessorDefinitions( - final CommandLineCompilerConfiguration compilerConfig) { + final CommandLineCompilerConfiguration compilerConfig, + final boolean isDebug) { StringBuffer defines = new StringBuffer(); String[] args = compilerConfig.getPreArguments(); for (int i = 0; i < args.length; i++) { if (args[i].startsWith("/D")) { - defines.append(args[i].substring(2)); + String macro = args[i].substring(2); + if (isDebug) { + if (macro.equals("NDEBUG")) { + macro = "_DEBUG"; + } + } else { + if (macro.equals("_DEBUG")) { + macro = "NDEBUG"; + } + } + defines.append(macro); defines.append(";"); } } @@ -265,24 +250,27 @@ public final class VisualStudioNETProjectWriter /** * Get value of RuntimeLibrary property. * @param compilerConfig compiler configuration. + * @param isDebug true if generating debug configuration. * @return value of RuntimeLibrary property. */ private String getRuntimeLibrary( - final CommandLineCompilerConfiguration compilerConfig) { + final CommandLineCompilerConfiguration compilerConfig, + final boolean isDebug) { String rtl = null; String[] args = compilerConfig.getPreArguments(); for (int i = 0; i < args.length; i++) { - if ("/MT".equals(args[i])) { - rtl = "0"; - } - if ("/MTd".equals(args[i])) { - rtl = "1"; - } - if ("/MD".equals(args[i])) { - rtl = "2"; - } - if ("/MDd".equals(args[i])) { - rtl = "3"; + if (args[i].startsWith("/MT")) { + if (isDebug) { + rtl = "1"; + } else { + rtl = "0"; + } + } else if (args[i].startsWith("/MD")) { + if (isDebug) { + rtl = "3"; + } else { + rtl = "2"; + } } } return rtl; @@ -326,15 +314,6 @@ public final class VisualStudioNETProjectWriter } - /** - * Get value of MinimalRebuild property. - * @param compilerConfig compiler configuration. - * @return value of MinimalRebuild property. - */ - private String getMinimalRebuild( - final CommandLineCompilerConfiguration compilerConfig) { - return trueLiteral; - } /** * Get value of BasicRuntimeChecks property. @@ -415,6 +394,9 @@ public final class VisualStudioNETProjectWriter if ("/Z7".equals(args[i])) { format = "1"; } + if ("/Zd".equals(args[i])) { + format = "2"; + } if ("/Zi".equals(args[i])) { format = "3"; } @@ -428,26 +410,41 @@ public final class VisualStudioNETProjectWriter /** * write the Compiler element. * @param content serialization content handler. + * @param isDebug true if generating debug configuration. + * @param basePath base for relative file paths. * @param compilerConfig compiler configuration. * @throws SAXException thrown if error during serialization. */ private void writeCompilerElement(final ContentHandler content, + final boolean isDebug, + final String basePath, final CommandLineCompilerConfiguration compilerConfig) throws SAXException { AttributesImpl attributes = new AttributesImpl(); addAttribute(attributes, "Name", "VCCLCompilerTool"); - addAttribute(attributes, "Optimization", - getOptimization(compilerConfig)); + String optimization = getOptimization(compilerConfig); + String debugFormat = getDebugInformationFormat(compilerConfig); + if(isDebug) { + optimization = "0"; + if ("0".equals(debugFormat)) { + debugFormat = "4"; + } + } else { + if ("0".equals(optimization)) { + optimization = "2"; + } + debugFormat = "0"; + } + addAttribute(attributes, "Optimization", optimization); addAttribute(attributes, "AdditionalIncludeDirectories", - getAdditionalIncludeDirectories(compilerConfig)); + getAdditionalIncludeDirectories(basePath, compilerConfig)); addAttribute(attributes, "PreprocessorDefinitions", - getPreprocessorDefinitions(compilerConfig)); - addAttribute(attributes, "MinimalRebuild", - getMinimalRebuild(compilerConfig)); + getPreprocessorDefinitions(compilerConfig, isDebug)); + addAttribute(attributes, "MinimalRebuild", trueLiteral); addAttribute(attributes, "BasicRuntimeChecks", getBasicRuntimeChecks(compilerConfig)); addAttribute(attributes, "RuntimeLibrary", - getRuntimeLibrary(compilerConfig)); + getRuntimeLibrary(compilerConfig, isDebug)); addAttribute(attributes, "UsePrecompiledHeader", getUsePrecompiledHeader(compilerConfig)); addAttribute(attributes, "PrecompiledHeaderFile", @@ -457,7 +454,7 @@ public final class VisualStudioNETProjectWriter addAttribute(attributes, "Detect64BitPortabilityProblems", getDetect64BitPortabilityProblems(compilerConfig)); addAttribute(attributes, "DebugInformationFormat", - getDebugInformationFormat(compilerConfig)); + debugFormat); content.startElement(null, "Tool", "Tool", attributes); content.endElement(null, "Tool", "Tool"); @@ -484,22 +481,6 @@ public final class VisualStudioNETProjectWriter return incremental; } - /** - * Get value of GenerateDebugInformation property. - * @param linkerConfig linker configuration. - * @return value of GenerateDebugInformation property - */ - private String getGenerateDebugInformation( - final CommandLineLinkerConfiguration linkerConfig) { - String debug = falseLiteral; - String[] args = linkerConfig.getPreArguments(); - for (int i = 0; i < args.length; i++) { - if ("/DEBUG".equals(args[i])) { - debug = trueLiteral; - } - } - return debug; - } /** * Get value of Subsystem property. @@ -544,11 +525,13 @@ public final class VisualStudioNETProjectWriter /** * Get value of AdditionalDependencies property. * @param linkTarget link target. + * @param projectDependencies dependencies declared in project. * @param targets all targets. * @param basePath path to directory containing project file. * @return value of AdditionalDependencies property. */ private String getAdditionalDependencies(final TargetInfo linkTarget, + final List projectDependencies, final Map targets, final String basePath) { String dependencies = null; @@ -559,19 +542,43 @@ public final class VisualStudioNETProjectWriter // if file was not compiled or otherwise generated // if (targets.get(linkSources[i].getName()) == null) { - String relPath = CUtil.getRelativePath(basePath, linkSources[i]); // - // if path has an embedded space then - // must quote - if (relPath.indexOf(' ') > 0) { - buf.append('\"'); - buf.append(relPath); - buf.append('\"'); - } else { - buf.append(relPath); - } - buf.append(';'); - } + // if source appears to be a system library or object file + // just output the name of the file (advapi.lib for example) + // otherwise construct a relative path. + // + String relPath = linkSources[i].getName(); + // + // check if file comes from a project dependency + // if it does it should not be explicitly linked + boolean fromDependency = false; + if (relPath.indexOf(".") > 0) { + String baseName = relPath.substring(0, relPath.indexOf(".")); + for(Iterator iter = projectDependencies.iterator(); iter.hasNext(); ) { + DependencyDef depend = (DependencyDef) iter.next(); + if (baseName.compareToIgnoreCase(depend.getName()) == 0) { + fromDependency = true; + } + } + } + + if (!fromDependency) { + if (!CUtil.isSystemPath(linkSources[i])) { + relPath = CUtil.getRelativePath(basePath, linkSources[i]); + } + // + // if path has an embedded space then + // must quote + if (relPath.indexOf(' ') > 0) { + buf.append('\"'); + buf.append(CUtil.toWindowsPath(relPath)); + buf.append('\"'); + } else { + buf.append(relPath); + } + buf.append(' '); + } + } } if (buf.length() > 0) { buf.setLength(buf.length() - 1); @@ -584,12 +591,16 @@ public final class VisualStudioNETProjectWriter /** * Write Tool element for linker. * @param content serialization content handler. + * @param isDebug true if generating debug configuration. + * @param dependencies project dependencies. * @param basePath path to directory containing project file. * @param linkTarget link target. * @param targets all targets. * @throws SAXException thrown if error during serialization. */ private void writeLinkerElement(final ContentHandler content, + final boolean isDebug, + final List dependencies, final String basePath, final TargetInfo linkTarget, final Map targets) throws SAXException { @@ -603,8 +614,11 @@ public final class VisualStudioNETProjectWriter if (linkerConfig.getLinker() instanceof DevStudioCompatibleLinker) { addAttribute(attributes, "LinkIncremental", getLinkIncremental(linkerConfig)); - addAttribute(attributes, "GenerateDebugInformation", - getGenerateDebugInformation(linkerConfig)); + if (isDebug) { + addAttribute(attributes, "GenerateDebugInformation", trueLiteral); + } else { + addAttribute(attributes, "GenerateDebugInformation", falseLiteral); + } addAttribute(attributes, "SubSystem", getSubsystem(linkerConfig)); addAttribute(attributes, "TargetMachine", @@ -612,7 +626,7 @@ public final class VisualStudioNETProjectWriter } } addAttribute(attributes, "AdditionalDependencies", - getAdditionalDependencies(linkTarget, targets, basePath)); + getAdditionalDependencies(linkTarget, dependencies, targets, basePath)); content.startElement(null, "Tool", "Tool", attributes); content.endElement(null, "Tool", "Tool"); } @@ -665,10 +679,16 @@ public final class VisualStudioNETProjectWriter OutputStream outStream = new FileOutputStream(fileName + ".vcproj"); OutputFormat format = new OutputFormat("xml", "UTF-8", true); - Serializer serializer = new XMLSerializer(outStream, format); + XMLSerializer serializer = new XMLSerializer(outStream, format); ContentHandler content = serializer.asContentHandler(); String basePath = fileName.getParentFile().getAbsolutePath(); content.startDocument(); + + for(Iterator iter = projectDef.getComments().iterator(); iter.hasNext(); ) { + String comment = ((CommentDef) iter.next()).getText(); + serializer.comment(comment); + } + AttributesImpl emptyAttrs = new AttributesImpl(); AttributesImpl attributes = new AttributesImpl(); @@ -687,13 +707,22 @@ public final class VisualStudioNETProjectWriter content.startElement(null, "Configurations", "Configurations", emptyAttrs); - writeConfigurationStartTag(content, basePath, task, compilerConfig); - - writeCompilerElement(content, compilerConfig); - - writeLinkerElement(content, basePath, linkTarget, targets); + // + // write debug configuration + // + writeConfigurationStartTag(content, true, task, compilerConfig); + writeCompilerElement(content, true, basePath, compilerConfig); + writeLinkerElement(content, true, projectDef.getDependencies(), basePath, linkTarget, targets); + content.endElement(null, "Configuration", "Configuration"); + // + // write release configuration + // + writeConfigurationStartTag(content, false, task, compilerConfig); + writeCompilerElement(content, false, basePath, compilerConfig); + writeLinkerElement(content, false, projectDef.getDependencies(), basePath, linkTarget, targets); content.endElement(null, "Configuration", "Configuration"); + content.endElement(null, "Configurations", "Configurations"); content.startElement(null, "References", "References", emptyAttrs); content.endElement(null, "References", "References"); diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/AbstractLdLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/AbstractLdLinker.java index 32e6e7e..f1eb2d7 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/gcc/AbstractLdLinker.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/AbstractLdLinker.java @@ -108,12 +108,18 @@ public abstract class AbstractLdLinker extends CommandLineLinker { File libdir = set.getDir(null); String[] libs = set.getLibs(); if (libdir != null) { + String relPath = libdir.getAbsolutePath(); + File outputFile = task.getOutfile(); + if (outputFile != null && outputFile.getParentFile() != null) { + relPath = CUtil.getRelativePath( + outputFile.getParentFile().getAbsolutePath(), libdir); + } if (set.getType() != null && "framework".equals(set.getType().getValue()) && isDarwin()) { - endargs.addElement("-F" + libdir.getAbsolutePath()); + endargs.addElement("-F" + relPath); } else { - endargs.addElement("-L" + libdir.getAbsolutePath()); + endargs.addElement("-L" + relPath); } } // @@ -123,7 +129,7 @@ public abstract class AbstractLdLinker extends CommandLineLinker { if (set.getType() != null && "static".equals(set.getType().getValue())) { // BEGINFREEHEP not on MacOS X if (!isDarwin()) { - endargs.addElement("-Bstatic"); + endargs.addElement(getStaticLibFlag()); previousLibraryType = set.getType(); } //ENDFREEHEP @@ -132,7 +138,7 @@ public abstract class AbstractLdLinker extends CommandLineLinker { if (set.getType() == null || !"framework".equals(set.getType().getValue()) && !isDarwin()) { - endargs.addElement("-Bdynamic"); + endargs.addElement(getDynamicLibFlag()); previousLibraryType = set.getType(); } } @@ -163,7 +169,7 @@ public abstract class AbstractLdLinker extends CommandLineLinker { // BEGINFREEHEP if last was -Bstatic reset it to -Bdynamic so that libc and libm can be found as shareables if ((previousLibraryType != null) && previousLibraryType.getValue().equals("static") && !isDarwin()) { - endargs.addElement("-Bdynamic"); + endargs.addElement(getDynamicLibFlag()); } // ENDFREEHEP @@ -286,8 +292,8 @@ public abstract class AbstractLdLinker extends CommandLineLinker { * linker output file * @param sourceFiles * linker input files (.obj, .o, .res) - * @param args - * linker arguments + * @param config + * linker configuration * @return arguments for runTask */ public String[] prepareArguments(CCTask task, String outputDir, @@ -342,4 +348,12 @@ public abstract class AbstractLdLinker extends CommandLineLinker { return super.prepareArguments(task, outputDir, outputFile, finalSources, config); } + + protected String getDynamicLibFlag() { + return "-Bdynamic"; + } + + protected String getStaticLibFlag() { + return "-Bstatic"; + } } diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccCCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccCCompiler.java index 1abdbec..f9e4c0b 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccCCompiler.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccCCompiler.java @@ -256,7 +256,6 @@ public final class GccCCompiler extends GccCompatibleCCompiler { return GccLinker.getInstance().getLinker(linkType); } public int getMaximumCommandLength() { -// FREEHEP return isWindows() ? 20000 : Integer.MAX_VALUE; } } diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccCompatibleCCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccCompatibleCCompiler.java index fa134f0..fc7bbfc 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccCompatibleCCompiler.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccCompatibleCCompiler.java @@ -98,7 +98,7 @@ public abstract class GccCompatibleCCompiler extends CommandLineCCompiler { args.addElement("-mwindows"); } } -// BEGINFREEHEP +// BEGINFREEHEP, tests have been modified if (!exceptions) { args.addElement("-fno-exceptions"); } diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccProcessor.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccProcessor.java index 058ef12..988848d 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccProcessor.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccProcessor.java @@ -117,7 +117,7 @@ public class GccProcessor { * -dumpversion. Attempts to use gcc -dumpspecs to provide this information * resulted in stalling on the Execute.run * - * @returns contents of the specs file + * @return contents of the specs file */ public static String[] getSpecs() { if (specs == null) { diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/GppLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GppLinker.java index 097f96b..043720d 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/gcc/GppLinker.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GppLinker.java @@ -15,7 +15,6 @@ * limitations under the License. */ package net.sf.antcontrib.cpptasks.gcc; - import java.io.File; import java.util.Vector; @@ -25,245 +24,236 @@ import net.sf.antcontrib.cpptasks.compiler.CaptureStreamHandler; import net.sf.antcontrib.cpptasks.compiler.LinkType; import net.sf.antcontrib.cpptasks.compiler.Linker; import net.sf.antcontrib.cpptasks.types.LibrarySet; - /** * Adapter for the g++ variant of the GCC linker * * @author Stephen M. Webb <stephen.webb@bregmasoft.com> */ public class GppLinker extends AbstractLdLinker { - protected static final String[] discardFiles = new String[0]; - protected static final String[] objFiles = new String[] { ".o", ".a", - ".lib", ".dll", ".so", ".sl" }; - // FREEHEP refactored dllLinker into soLinker - private static final GppLinker soLinker = new GppLinker("gcc", objFiles, - discardFiles, "lib", ".so", false, new GppLinker("gcc", objFiles, - discardFiles, "lib", ".so", true, null)); - private final static String libPrefix = "libraries: ="; - protected static final String[] libtoolObjFiles = new String[] { ".fo", - ".a", ".lib", ".dll", ".so", ".sl" }; - private static String[] linkerOptions = new String[] { "-bundle", "-dylib", - "-dynamic", "-dynamiclib", "-nostartfiles", "-nostdlib", - "-prebind", "-s", "-static", "-shared", "-symbolic", "-Xlinker", - // FREEHEP - "-static-libgcc", "-shared-libgcc" }; - private static final GppLinker instance = new GppLinker("gcc", objFiles, - discardFiles, "", "", false, null); - private static final GppLinker machDllLinker = new GppLinker("gcc", - objFiles, discardFiles, "lib", ".dylib", false, null); - private static final GppLinker machPluginLinker = new GppLinker("gcc", - objFiles, discardFiles, "lib", ".bundle", false, null); - // FREEHEP - private static final GppLinker machJNILinker = new GppLinker("gcc", - objFiles, discardFiles, "lib", ".jnilib", false, null); - // FREEHEP added dllLinker for windows - private static final GppLinker dllLinker = new GppLinker("gcc", objFiles, - discardFiles, "", ".dll", false, null); - - public static GppLinker getInstance() { - return instance; - } - - private File[] libDirs; - private String runtimeLibrary; - // FREEEHEP - private String gccLibrary, gfortranLibrary; - - protected GppLinker(String command, String[] extensions, - String[] ignoredExtensions, String outputPrefix, - String outputSuffix, boolean isLibtool, GppLinker libtoolLinker) { - super(command, "-dumpversion", extensions, ignoredExtensions, - outputPrefix, outputSuffix, isLibtool, libtoolLinker); - } - - protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args) { - super.addImpliedArgs(debug, linkType, args); - if (getIdentifier().indexOf("mingw") >= 0) { - if (linkType.isSubsystemConsole()) { - args.addElement("-mconsole"); - } - if (linkType.isSubsystemGUI()) { - args.addElement("-mwindows"); - } - } - - // BEGINFREEHEP link or not with libstdc++ - // for MacOS X see: - // http://developer.apple.com/documentation/DeveloperTools/Conceptual/CppRuntimeEnv/Articles/LibCPPDeployment.html - gfortranLibrary = null; - if (linkType.linkFortran()) { - if (linkType.isStaticRuntime()) { - String[] cmdin = new String[] { "gfortran", - "-print-file-name=libgfortran.a" }; - String[] cmdout = CaptureStreamHandler.run(cmdin); - if ((cmdout.length > 0) && (cmdout[0].indexOf('/') >= 0)) { - gfortranLibrary = cmdout[0]; - } - } else { - gfortranLibrary = "-lgfortran"; - } - } - - runtimeLibrary = null; - if (linkType.linkCPP()) { - if (linkType.isStaticRuntime()) { - if (isDarwin()) { - runtimeLibrary = "-lstdc++-static"; - } else { - String[] cmdin = new String[] { "g++", - "-print-file-name=libstdc++.a" }; - String[] cmdout = CaptureStreamHandler.run(cmdin); - if ((cmdout.length > 0) && (cmdout[0].indexOf('/') >= 0)) { - runtimeLibrary = cmdout[0]; - } - } - } else { - runtimeLibrary = "-lstdc++"; - } - } - - gccLibrary = null; - if (linkType.isStaticRuntime()) { - gccLibrary = "-static-libgcc"; - } else { - if (linkType.linkCPP()) { - // NOTE: added -fexceptions here for MacOS X - gccLibrary = "-fexceptions"; - } else { - gccLibrary = "-shared-libgcc"; - } - } - // ENDFREEHEP - } - - public String[] addLibrarySets(CCTask task, LibrarySet[] libsets, - Vector preargs, Vector midargs, Vector endargs) { - String[] rs = super.addLibrarySets(task, libsets, preargs, midargs, - endargs); - // BEGINFREEHEP - if (gfortranLibrary != null) { - endargs.addElement(gfortranLibrary); - } - if (gccLibrary != null) { - endargs.addElement(gccLibrary); - } - // ENDFREEHEP - if (runtimeLibrary != null) { - endargs.addElement(runtimeLibrary); - } - return rs; - } + protected static final String[] discardFiles = new String[0]; + protected static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + // FREEHEP refactored dllLinker into soLinker + private static final GppLinker soLinker = new GppLinker("gcc", objFiles, + discardFiles, "lib", ".so", false, new GppLinker("gcc", objFiles, + discardFiles, "lib", ".so", true, null)); + private final static String libPrefix = "libraries: ="; + protected static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static String[] linkerOptions = new String[]{"-bundle", "-dylib", + "-dynamic", "-dynamiclib", "-nostartfiles", "-nostdlib", + "-prebind", "-s", "-static", "-shared", "-symbolic", "-Xlinker", + // FREEHEP + "-static-libgcc", "-shared-libgcc" }; + private static final GppLinker instance = new GppLinker("gcc", objFiles, + discardFiles, "", "", false, null); + private static final GppLinker machDllLinker = new GppLinker("gcc", + objFiles, discardFiles, "lib", ".dylib", false, null); + private static final GppLinker machPluginLinker = new GppLinker("gcc", + objFiles, discardFiles, "lib", ".bundle", false, null); + // FREEHEP + private static final GppLinker machJNILinker = new GppLinker("gcc", + objFiles, discardFiles, "lib", ".jnilib", false, null); + // FREEHEP added dllLinker for windows + private static final GppLinker dllLinker = new GppLinker("gcc", objFiles, + discardFiles, "", ".dll", false, null); + public static GppLinker getInstance() { + return instance; + } + private File[] libDirs; + private String runtimeLibrary; + // FREEEHEP + private String gccLibrary, gfortranLibrary; - /** - * Allows drived linker to decorate linker option. Override by GppLinker to - * prepend a "-Wl," to pass option to through gcc to linker. - * - * @param buf - * buffer that may be used and abused in the decoration process, - * must not be null. - * @param arg - * linker argument - */ - public String decorateLinkerOption(StringBuffer buf, String arg) { - String decoratedArg = arg; - if (arg.length() > 1 && arg.charAt(0) == '-') { - switch (arg.charAt(1)) { - // - // passed automatically by GCC - // - case 'g': - case 'f': - case 'F': - /* Darwin */ - case 'm': - case 'O': - case 'W': - case 'l': - case 'L': - case 'u': - break; - default: - boolean known = false; - for (int i = 0; i < linkerOptions.length; i++) { - if (linkerOptions[i].equals(arg)) { - known = true; - break; - } - } - if (!known) { - buf.setLength(0); - buf.append("-Wl,"); - buf.append(arg); - decoratedArg = buf.toString(); - } - break; - } - } - return decoratedArg; - } + protected GppLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, GppLinker libtoolLinker) { + super(command, "-dumpversion", extensions, ignoredExtensions, + outputPrefix, outputSuffix, isLibtool, libtoolLinker); + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args) { + super.addImpliedArgs(debug, linkType, args); + if (getIdentifier().indexOf("mingw") >= 0) { + if (linkType.isSubsystemConsole()) { + args.addElement("-mconsole"); + } + if (linkType.isSubsystemGUI()) { + args.addElement("-mwindows"); + } + } + // BEGINFREEHEP link or not with libstdc++ + // for MacOS X see: + // http://developer.apple.com/documentation/DeveloperTools/Conceptual/CppRuntimeEnv/Articles/LibCPPDeployment.html + gfortranLibrary = null; + if (linkType.linkFortran()) { + if (linkType.isStaticRuntime()) { + String[] cmdin = new String[] { "gfortran", + "-print-file-name=libgfortran.a" }; + String[] cmdout = CaptureStreamHandler.run(cmdin); + if ((cmdout.length > 0) && (cmdout[0].indexOf('/') >= 0)) { + gfortranLibrary = cmdout[0]; + } + } else { + gfortranLibrary = "-lgfortran"; + } + } - /** - * Returns library path. - * - */ - public File[] getLibraryPath() { - if (libDirs == null) { - Vector dirs = new Vector(); - // Ask GCC where it will look for its libraries. - String[] args = new String[] { "g++", "-print-search-dirs" }; - String[] cmdout = CaptureStreamHandler.run(args); - for (int i = 0; i < cmdout.length; ++i) { - int prefixIndex = cmdout[i].indexOf(libPrefix); - if (prefixIndex >= 0) { - // Special case DOS-type GCCs like MinGW or Cygwin - int s = prefixIndex + libPrefix.length(); - int t = cmdout[i].indexOf(';', s); - while (t > 0) { - dirs.addElement(cmdout[i].substring(s, t)); - s = t + 1; - t = cmdout[i].indexOf(';', s); - } - dirs.addElement(cmdout[i].substring(s)); - ++i; - for (; i < cmdout.length; ++i) { - dirs.addElement(cmdout[i]); - } - } - } - // Eliminate all but actual directories. - String[] libpath = new String[dirs.size()]; - dirs.copyInto(libpath); - int count = CUtil.checkDirectoryArray(libpath); - // Build return array. - libDirs = new File[count]; - int index = 0; - for (int i = 0; i < libpath.length; ++i) { - if (libpath[i] != null) { - libDirs[index++] = new File(libpath[i]); - } - } - } - return libDirs; - } + runtimeLibrary = null; + if (linkType.linkCPP()) { + if (linkType.isStaticRuntime()) { + if (isDarwin()) { + runtimeLibrary = "-lstdc++-static"; + } else { + String[] cmdin = new String[] { "g++", + "-print-file-name=libstdc++.a" }; + String[] cmdout = CaptureStreamHandler.run(cmdin); + if ((cmdout.length > 0) && (cmdout[0].indexOf('/') >= 0)) { + runtimeLibrary = cmdout[0]; + } + } + } else { + runtimeLibrary = "-lstdc++"; + } + } - public Linker getLinker(LinkType type) { - if (type.isStaticLibrary()) { - return GccLibrarian.getInstance(); - } - // BEGINFREEHEP - if (type.isJNIModule()) { - return isDarwin() ? machJNILinker : isWindows() ? dllLinker - : soLinker; - } - if (type.isPluginModule()) { - return isDarwin() ? machPluginLinker : isWindows() ? dllLinker - : soLinker; - } - if (type.isSharedLibrary()) { - return isDarwin() ? machDllLinker : isWindows() ? dllLinker - : soLinker; - } - // ENDFREEHEP - return instance; - } + gccLibrary = null; + if (linkType.isStaticRuntime()) { + gccLibrary = "-static-libgcc"; + } else { + if (linkType.linkCPP()) { + // NOTE: added -fexceptions here for MacOS X + gccLibrary = "-fexceptions"; + } else { + gccLibrary = "-shared-libgcc"; + } + } + // ENDFREEHEP + } + public String[] addLibrarySets(CCTask task, LibrarySet[] libsets, + Vector preargs, Vector midargs, Vector endargs) { + String[] rs = super.addLibrarySets(task, libsets, preargs, midargs, + endargs); + // BEGINFREEHEP + if (gfortranLibrary != null) { + endargs.addElement(gfortranLibrary); + } + if (gccLibrary != null) { + endargs.addElement(gccLibrary); + } + // ENDFREEHEP + if (runtimeLibrary != null) { + endargs.addElement(runtimeLibrary); + } + return rs; + } + /** + * Allows drived linker to decorate linker option. Override by GppLinker to + * prepend a "-Wl," to pass option to through gcc to linker. + * + * @param buf + * buffer that may be used and abused in the decoration process, + * must not be null. + * @param arg + * linker argument + */ + public String decorateLinkerOption(StringBuffer buf, String arg) { + String decoratedArg = arg; + if (arg.length() > 1 && arg.charAt(0) == '-') { + switch (arg.charAt(1)) { + // + // passed automatically by GCC + // + case 'g' : + case 'f' : + case 'F' : + /* Darwin */ + case 'm' : + case 'O' : + case 'W' : + case 'l' : + case 'L' : + case 'u' : + break; + default : + boolean known = false; + for (int i = 0; i < linkerOptions.length; i++) { + if (linkerOptions[i].equals(arg)) { + known = true; + break; + } + } + if (!known) { + buf.setLength(0); + buf.append("-Wl,"); + buf.append(arg); + decoratedArg = buf.toString(); + } + break; + } + } + return decoratedArg; + } + /** + * Returns library path. + * + */ + public File[] getLibraryPath() { + if (libDirs == null) { + Vector dirs = new Vector(); + // Ask GCC where it will look for its libraries. + String[] args = new String[]{"g++", "-print-search-dirs"}; + String[] cmdout = CaptureStreamHandler.run(args); + for (int i = 0; i < cmdout.length; ++i) { + int prefixIndex = cmdout[i].indexOf(libPrefix); + if (prefixIndex >= 0) { + // Special case DOS-type GCCs like MinGW or Cygwin + int s = prefixIndex + libPrefix.length(); + int t = cmdout[i].indexOf(';', s); + while (t > 0) { + dirs.addElement(cmdout[i].substring(s, t)); + s = t + 1; + t = cmdout[i].indexOf(';', s); + } + dirs.addElement(cmdout[i].substring(s)); + ++i; + for (; i < cmdout.length; ++i) { + dirs.addElement(cmdout[i]); + } + } + } + // Eliminate all but actual directories. + String[] libpath = new String[dirs.size()]; + dirs.copyInto(libpath); + int count = CUtil.checkDirectoryArray(libpath); + // Build return array. + libDirs = new File[count]; + int index = 0; + for (int i = 0; i < libpath.length; ++i) { + if (libpath[i] != null) { + libDirs[index++] = new File(libpath[i]); + } + } + } + return libDirs; + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + // BEGINFREEHEP + if (type.isJNIModule()) { + return isDarwin() ? machJNILinker : isWindows() ? dllLinker + : soLinker; + } + if (type.isPluginModule()) { + return isDarwin() ? machPluginLinker : isWindows() ? dllLinker + : soLinker; + } + if (type.isSharedLibrary()) { + return isDarwin() ? machDllLinker : isWindows() ? dllLinker + : soLinker; + } + // ENDFREEHEP + return instance; + } } diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/WindresResourceCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/WindresResourceCompiler.java new file mode 100644 index 0000000..a617024 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/WindresResourceCompiler.java @@ -0,0 +1,121 @@ +/* + * + * Copyright 2008 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.parser.CParser; +import net.sf.antcontrib.cpptasks.parser.Parser; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +import org.apache.tools.ant.types.Environment; +/** + * Adapter for the GNU windres resource compiler. + * + * @author Curt Arnold + */ +public final class WindresResourceCompiler extends CommandLineCompiler { + private static final WindresResourceCompiler instance = new WindresResourceCompiler( + false, null); + public static WindresResourceCompiler getInstance() { + return instance; + } + private WindresResourceCompiler(boolean newEnvironment, Environment env) { + super("windres", null, new String[]{".rc"}, new String[]{".h", ".hpp", + ".inl"}, ".o", false, null, newEnvironment, env); + } + protected void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization) { + if (debug) { + args.addElement("-D_DEBUG"); + } else { + args.addElement("-DNDEBUG"); + } + } + protected void addWarningSwitch(Vector args, int level) { + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new WindresResourceCompiler(newEnvironment, env); + } + return this; + } + /** + * The include parser for C will work just fine, but we didn't want to + * inherit from CommandLineCCompiler + */ + protected Parser createParser(File source) { + return new CParser(); + } + protected int getArgumentCountPerInputFile() { + return 2; + } + protected void getDefineSwitch(StringBuffer buffer, String define, + String value) { + buffer.append("-D"); + buffer.append(define); + if (value != null && value.length() > 0) { + buffer.append('='); + buffer.append(value); + } + } + protected File[] getEnvironmentIncludePath() { + return new File[0]; + } + protected String getIncludeDirSwitch(String includeDir) { + return "-I" + includeDir; + } + protected String getInputFileArgument(File outputDir, String filename, + int index) { + if (index == 0) { + String outputFileName = getOutputFileNames(filename, null)[0]; + return "-o" + outputFileName; + } + return filename; + } + public Linker getLinker(LinkType type) { + return GccLinker.getInstance().getLinker(type); + } + public int getMaximumCommandLength() { + return 32767; + } + protected int getMaximumInputFilesPerCommand() { + return 1; + } + protected int getTotalArgumentLengthForInputFile(File outputDir, + String inputFile) { + String arg1 = getInputFileArgument(outputDir, inputFile, 0); + String arg2 = getInputFileArgument(outputDir, inputFile, 1); + return arg1.length() + arg2.length() + 2; + } + protected void getUndefineSwitch(StringBuffer buffer, String define) { + buffer.append("-U"); + buffer.append(define); + } + public String getIdentifier() { + return "GNU windres"; + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GccProcessor.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GccProcessor.java index 8e35995..728cd47 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GccProcessor.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/GccProcessor.java @@ -106,7 +106,7 @@ public class GccProcessor { * -dumpversion. Attempts to use gcc -dumpspecs to provide this information * resulted in stalling on the Execute.run * - * @returns contents of the specs file + * @return contents of the specs file */ public static String[] getSpecs() { if (specs == null) { diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccProcessor.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccProcessor.java index 8a7a26e..bbcd13d 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccProcessor.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccProcessor.java @@ -121,7 +121,7 @@ public class GccProcessor { * -dumpversion. Attempts to use gcc -dumpspecs to provide this information * resulted in stalling on the Execute.run * - * @returns contents of the specs file + * @return contents of the specs file */ public static String[] getSpecs() { if (specs == null) { diff --git a/src/main/java/net/sf/antcontrib/cpptasks/hp/aCCCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/hp/aCCCompiler.java index e556e6b..b978f67 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/hp/aCCCompiler.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/hp/aCCCompiler.java @@ -1,6 +1,6 @@ /* * - * Copyright 2001-2004 The Ant-Contrib project + * Copyright 2001-2007 The Ant-Contrib project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,8 +31,13 @@ import org.apache.tools.ant.types.Environment; * @author Curt Arnold */ public final class aCCCompiler extends GccCompatibleCCompiler { - private static final aCCCompiler instance = new aCCCompiler("aCC", false, - null); + private final static String[] headerExtensions = new String[]{".h", ".hpp", + ".inl"}; + private final static String[] sourceExtensions = new String[]{".c", ".cc", + ".cxx", ".cpp", ".c++", ".i", ".s"}; + + private static final aCCCompiler instance = new aCCCompiler("aCC", + sourceExtensions, headerExtensions, false, null); /** * Gets singleton instance of this class */ @@ -45,8 +50,11 @@ public final class aCCCompiler extends GccCompatibleCCompiler { * Private constructor. Use GccCCompiler.getInstance() to get singleton * instance of this class. */ - private aCCCompiler(String command, boolean newEnvironment, Environment env) { - super(command, "-help", false, null, newEnvironment, env); + private aCCCompiler(String command, String[] sourceExtensions, + String[] headerExtensions, boolean newEnvironment, + Environment env) { + super(command, "-help", sourceExtensions, headerExtensions, false, + null, newEnvironment, env); } public void addImpliedArgs(Vector args, boolean debug, boolean multithreaded, boolean exceptions, LinkType linkType, diff --git a/src/main/java/net/sf/antcontrib/cpptasks/ibm/VisualAgeCCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/ibm/VisualAgeCCompiler.java index 56b7674..781b6de 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/ibm/VisualAgeCCompiler.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/ibm/VisualAgeCCompiler.java @@ -30,8 +30,13 @@ import org.apache.tools.ant.types.Environment; * @author Curt Arnold */ public final class VisualAgeCCompiler extends GccCompatibleCCompiler { + private final static String[] headerExtensions = new String[]{".h", ".hpp", + ".inl"}; + private final static String[] sourceExtensions = new String[]{".c", ".cc", + ".cxx", ".cpp", ".i", ".s"}; + private static final VisualAgeCCompiler instance = new VisualAgeCCompiler( - "xlC", false, null); + "xlC", sourceExtensions, headerExtensions, false, null); /** * Gets singleton instance of this class */ @@ -44,9 +49,11 @@ public final class VisualAgeCCompiler extends GccCompatibleCCompiler { * Private constructor. Use getInstance() to get singleton instance of this * class. */ - private VisualAgeCCompiler(String command, boolean newEnvironment, + private VisualAgeCCompiler(String command, String[] sourceExtensions, + String[] headerExtensions, boolean newEnvironment, Environment env) { - super(command, "-help", false, null, newEnvironment, env); + super(command, "-help", sourceExtensions, headerExtensions, false, + null, newEnvironment, env); } public void addImpliedArgs(final Vector args, final boolean debug, diff --git a/src/main/java/net/sf/antcontrib/cpptasks/ibm/VisualAgeLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/ibm/VisualAgeLinker.java index 8e614b3..59ad6a3 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/ibm/VisualAgeLinker.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/ibm/VisualAgeLinker.java @@ -31,7 +31,7 @@ public final class VisualAgeLinker extends AbstractLdLinker { private static final String[] objFiles = new String[]{".o", ".a", ".lib", ".dll", ".so", ".sl"}; private static final VisualAgeLinker dllLinker = new VisualAgeLinker( - "makeC++SharedLib", objFiles, discardFiles, "lib", ".so"); + "xlC", objFiles, discardFiles, "lib", ".a"); private static final VisualAgeLinker instance = new VisualAgeLinker("xlC", objFiles, discardFiles, "", ""); public static VisualAgeLinker getInstance() { @@ -50,7 +50,7 @@ public final class VisualAgeLinker extends AbstractLdLinker { //args.addElement("-g"); } if (linkType.isSharedLibrary()) { - //args.addElement("-G"); + args.addElement("-qmkshrobj"); } } public Linker getLinker(LinkType type) { @@ -69,7 +69,15 @@ public final class VisualAgeLinker extends AbstractLdLinker { * would lock up. Using a stock response. */ public String getIdentifier() { - return "VisualAge linker - unidentified version"; + return "VisualAge linker - unidentified version"; + } + + protected String getDynamicLibFlag() { + return "-bdynamic"; + } + + protected String getStaticLibFlag() { + return "-bstatic"; } } diff --git a/src/main/java/net/sf/antcontrib/cpptasks/ide/CommentDef.java b/src/main/java/net/sf/antcontrib/cpptasks/ide/CommentDef.java new file mode 100644 index 0000000..3a6f19f --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/ide/CommentDef.java @@ -0,0 +1,42 @@ +/* + * + * Copyright 2008 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.ide; + + +/** + * Defines a comment to place in the generated project files. + * + */ +public final class CommentDef { + private String text; + + public CommentDef() { + text = ""; + } + + + public String getText() { + return text; + } + public void addText(final String newText) { + text += newText; + } + + public String toString() { + return text; + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/ide/DependencyDef.java b/src/main/java/net/sf/antcontrib/cpptasks/ide/DependencyDef.java new file mode 100644 index 0000000..a04cad1 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/ide/DependencyDef.java @@ -0,0 +1,77 @@ +/* + * + * Copyright 2004-2006 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.ide; + +import org.apache.tools.ant.util.StringUtils; + +import java.io.File; +import java.util.Collections; +import java.util.List; + +/** + * Defines a dependency + * + */ +public final class DependencyDef { + private String id; + private File file; + private String name; + private String depends; + + public DependencyDef() { + } + + + public void setID(final String val) { + id = val; + } + public File getFile() { + return file; + } + public void setFile(final File val) { + file = val; + } + public void setName(final String val) { + name = val; + } + public String getName() { + if (name != null) { + return name; + } else if(file != null) { + return file.getName(); + } + return "null"; + } + public String getID() { + if (id != null) { + return id; + } + return getName(); + } + public String getDepends() { + return depends; + } + public void setDepends(final String val) { + depends = val; + } + public List getDependsList() { + if (depends != null) { + return StringUtils.split(depends, ','); + } + return Collections.EMPTY_LIST; + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/ide/ProjectDef.java b/src/main/java/net/sf/antcontrib/cpptasks/ide/ProjectDef.java index df0177c..8883ebb 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/ide/ProjectDef.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/ide/ProjectDef.java @@ -1,6 +1,6 @@ /* * - * Copyright 2004-2006 The Ant-Contrib project + * Copyright 2004-2008 The Ant-Contrib project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import org.apache.tools.ant.types.DataType; import java.io.File; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Hashtable; import java.util.List; @@ -83,6 +84,16 @@ public final class ProjectDef */ private File objDir; + /** + * List of dependency definitions. + */ + private List dependencies = new ArrayList(); + + /** + * List of comments. + */ + private List comments = new ArrayList(); + /** * Constructor. * @@ -120,6 +131,10 @@ public final class ProjectDef * <td>Microsoft Visual C++ 2005</td> * </tr> * <tr> + * <td>msvc9</td> + * <td>Microsoft Visual C++ 2008</td> + * </tr> + * <tr> * <td>xcode</td> * <td>Apple Xcode</td> * </tr> @@ -319,6 +334,33 @@ public final class ProjectDef this.objDir = oDir; } + /** + * Add a dependency definition to the project. + * @param dependency dependency. + */ + public void addDependency(final DependencyDef dependency) { + dependencies.add(dependency); + + } + + public List getDependencies() { + return new ArrayList(dependencies); + } + + + /** + * Add comment for the generated project file. + * @param comment comment, may not be null. + */ + public void addComment(final CommentDef comment) { + comments.add(comment); + + } + + public List getComments() { + return new ArrayList(comments); + } + /** * Required by documentation generator. */ diff --git a/src/main/java/net/sf/antcontrib/cpptasks/ide/ProjectWriterEnum.java b/src/main/java/net/sf/antcontrib/cpptasks/ide/ProjectWriterEnum.java index e100dbc..a50a7b2 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/ide/ProjectWriterEnum.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/ide/ProjectWriterEnum.java @@ -1,6 +1,6 @@ /* * - * Copyright 2004-2006 The Ant-Contrib project + * Copyright 2004-2008 The Ant-Contrib project * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of @@ -51,6 +51,10 @@ import org.apache.tools.ant.types.EnumeratedAttribute; * <td>Microsoft Visual C++ 2005</td> * </tr> * <tr> + * <td>msvc9</td> + * <td>Microsoft Visual C++ 2008</td> + * </tr> + * <tr> * <td>xcode</td> * <td>Apple Xcode</td> * </tr> @@ -66,7 +70,7 @@ public final class ProjectWriterEnum */ private static String[] values = new String[] { "cbuilderx", "msvc5", - "msvc6", "msvc7", "msvc71", "msvc8", "xcode"}; + "msvc6", "msvc7", "msvc71", "msvc8", "msvc9", "xcode"}; /** * Project writers associated with enumeration values. @@ -77,6 +81,7 @@ public final class ProjectWriterEnum new VisualStudioNETProjectWriter("7.00", "TRUE", "FALSE"), new VisualStudioNETProjectWriter("7.10", "TRUE", "FALSE"), new VisualStudioNETProjectWriter("8.00", "true", "false"), + new VisualStudioNETProjectWriter("9.00", "true", "false"), new XcodeProjectWriter()}; /** diff --git a/src/main/java/net/sf/antcontrib/cpptasks/sun/ForteCCCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/sun/ForteCCCompiler.java index 2c37eff..9422e49 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/sun/ForteCCCompiler.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/sun/ForteCCCompiler.java @@ -1,6 +1,6 @@ /* * - * Copyright 2001-2004 The Ant-Contrib project + * Copyright 2001-2007 The Ant-Contrib project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,13 @@ import net.sf.antcontrib.cpptasks.OptimizationEnum; * @author Curt Arnold */ public final class ForteCCCompiler extends GccCompatibleCCompiler { - private static final ForteCCCompiler instance = new ForteCCCompiler("CC"); + private final static String[] headerExtensions = new String[]{".h", ".hpp", + ".inl"}; + private final static String[] sourceExtensions = new String[]{".c", ".cc", + ".cxx", ".cpp", ".c++", ".i", ".s"}; + + private static final ForteCCCompiler instance = new ForteCCCompiler("CC", + sourceExtensions, headerExtensions); /** * Gets singleton instance of this class */ @@ -42,8 +48,10 @@ public final class ForteCCCompiler extends GccCompatibleCCompiler { * Private constructor. Use ForteCCCompiler.getInstance() to get singleton * instance of this class. */ - private ForteCCCompiler(String command) { - super(command, "-V", false, null, false, null); + private ForteCCCompiler(String command, String[] sourceExtensions, + String[] headerExtensions) { + super(command, "-V", sourceExtensions, headerExtensions, false, null, + false, null); } public void addImpliedArgs(final Vector args, final boolean debug, @@ -83,13 +91,16 @@ public final class ForteCCCompiler extends GccCompatibleCCompiler { break; case 1 : case 2 : - args.addElement("+w"); break; case 3 : + args.addElement("+w"); + break; case 4 : - case 5 : args.addElement("+w2"); break; + case 5 : + args.addElement("+w2"); + args.addElement("-xwe"); } } public File[] getEnvironmentIncludePath() { diff --git a/src/main/resources/net/sf/antcontrib/cpptasks/antlib.xml b/src/main/resources/net/sf/antcontrib/cpptasks/antlib.xml new file mode 100644 index 0000000..5f8af42 --- /dev/null +++ b/src/main/resources/net/sf/antcontrib/cpptasks/antlib.xml @@ -0,0 +1,22 @@ +<?xml version="1.0"?> + <!-- + * + * Copyright 2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + --> + <antlib> + <taskdef resource="cpptasks.tasks" /> + <typedef resource="cpptasks.types" /> + </antlib> +
\ No newline at end of file |