diff options
Diffstat (limited to 'src/main/java/net/sf/antcontrib/cpptasks/devstudio')
13 files changed, 2480 insertions, 0 deletions
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/DevStudioCCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCCompiler.java new file mode 100644 index 0000000..1281046 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCCompiler.java @@ -0,0 +1,50 @@ +/* + * + * Copyright 2002-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. + */ +package net.sf.antcontrib.cpptasks.devstudio; +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++ Optimizing Compiler + * + * @author Adam Murdoch + */ +public final class DevStudioCCompiler extends DevStudioCompatibleCCompiler { + private static final DevStudioCCompiler instance = new DevStudioCCompiler( + "cl", false, null); + public static DevStudioCCompiler getInstance() { + return instance; + } + private DevStudioCCompiler(String command, boolean newEnvironment, + Environment env) { + super(command, "/bogus", newEnvironment, env); + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new DevStudioCCompiler(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 new file mode 100644 index 0000000..5f37855 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleCCompiler.java @@ -0,0 +1,136 @@ +/* + * + * Copyright 2002-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. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import java.io.File; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineCompilerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.CompilerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.PrecompilingCommandLineCCompiler; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.Environment; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +/** + * An abstract base class for compilers that are basically command line + * compatible with Microsoft(r) C/C++ Optimizing Compiler + * + * @author Curt Arnold + */ +public abstract class DevStudioCompatibleCCompiler + extends + PrecompilingCommandLineCCompiler { + private static String[] mflags = new String[]{ + // + // first four are single-threaded + // (runtime=static,debug=false), (..,debug=true), + // (runtime=dynamic,debug=true), (..,debug=false), (not supported) + // next four are multi-threaded, same sequence + "/ML", "/MLd", null, null, "/MT", "/MTd", "/MD", "/MDd"}; + protected DevStudioCompatibleCCompiler(String command, + String identifierArg, boolean newEnvironment, Environment env) { + super(command, identifierArg, new String[]{".c", ".cc", ".cpp", ".cxx", + ".c++"}, new String[]{".h", ".hpp", ".inl"}, ".obj", 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) { + args.addElement("/c"); + args.addElement("/nologo"); + if (exceptions) { + // changed to eliminate warning on VC 2005, should support VC 6 and later + // use /GX to support VC5 - 2005 (with warning) + args.addElement("/EHsc"); + } + int mindex = 0; + if (multithreaded) { + mindex += 4; + } + boolean staticRuntime = linkType.isStaticRuntime(); + if (!staticRuntime) { + mindex += 2; + } + if (debug) { + mindex += 1; + addDebugSwitch(args); + } else { + if (optimization != null) { + if (optimization.isSize()) { + args.addElement("/O1"); + } + if (optimization.isSpeed()) { + args.addElement("/O2"); + } + } + args.addElement("/DNDEBUG"); + } + String mflag = mflags[mindex]; + if (mflag == null) { + throw new BuildException( + "multithread='false' and runtime='dynamic' not supported"); + } + args.addElement(mflag); + if (rtti != null && rtti.booleanValue()) { + 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); + } + protected CompilerConfiguration createPrecompileGeneratingConfig( + CommandLineCompilerConfiguration baseConfig, File prototype, + String lastInclude) { + String[] additionalArgs = new String[]{ + "/Fp" + CUtil.getBasename(prototype) + ".pch", "/Yc"}; + return new CommandLineCompilerConfiguration(baseConfig, additionalArgs, + null, true); + } + protected CompilerConfiguration createPrecompileUsingConfig( + CommandLineCompilerConfiguration baseConfig, File prototype, + String lastInclude, String[] exceptFiles) { + String[] additionalArgs = new String[]{ + "/Fp" + CUtil.getBasename(prototype) + ".pch", + "/Yu" + lastInclude}; + return new CommandLineCompilerConfiguration(baseConfig, additionalArgs, + exceptFiles, false); + } + protected void getDefineSwitch(StringBuffer buffer, String define, + String value) { + DevStudioProcessor.getDefineSwitch(buffer, define, value); + } + protected File[] getEnvironmentIncludePath() { + return CUtil.getPathFromEnvironment("INCLUDE", ";"); + } + protected String getIncludeDirSwitch(String includeDir) { + return DevStudioProcessor.getIncludeDirSwitch(includeDir); + } + protected void getUndefineSwitch(StringBuffer buffer, String define) { + DevStudioProcessor.getUndefineSwitch(buffer, define); + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLibrarian.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLibrarian.java new file mode 100644 index 0000000..985dfcf --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLibrarian.java @@ -0,0 +1,80 @@ +/* + * + * Copyright 2002-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. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; +/** + * Abstract base adapter for librarians with command line options compatible + * with the Microsoft(r) Library Manager + * + * @author Curt Arnold + */ +public abstract class DevStudioCompatibleLibrarian extends CommandLineLinker { + public DevStudioCompatibleLibrarian(String command, String identifierArg) { + super(command, identifierArg, new String[]{".obj"}, new String[0], + ".lib", false, null); + } + protected void addBase(long base, Vector args) { + } + protected void addFixed(Boolean fixed, Vector args) { + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args) { + args.addElement("/nologo"); + } + protected void addIncremental(boolean incremental, Vector args) { + } + protected void addMap(boolean map, Vector args) { + } + protected void addStack(int stack, Vector args) { + } + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addEntry(int, java.util.Vector) + */ + protected void addEntry(String entry, Vector args) { + } + + protected String getCommandFileSwitch(String cmdFile) { + return "@" + cmdFile; + } + public File[] getLibraryPath() { + return new File[0]; + } + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + return new String[0]; + } + public int getMaximumCommandLength() { + return 32767; + } + public String[] getOutputFileSwitch(String outFile) { + StringBuffer buf = new StringBuffer("/OUT:"); + if (outFile.indexOf(' ') >= 0) { + buf.append('"'); + buf.append(outFile); + buf.append('"'); + } else { + buf.append(outFile); + } + return new String[]{buf.toString()}; + } + public boolean isCaseSensitive() { + return false; + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLinker.java new file mode 100644 index 0000000..80d2aac --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLinker.java @@ -0,0 +1,148 @@ +/* + * + * Copyright 2002-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. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import java.io.File; +import java.io.IOException; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.TargetMatcher; +import net.sf.antcontrib.cpptasks.VersionInfo; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.platforms.WindowsPlatform; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +/** + * Abstract base class for linkers that try to mimic the command line arguments + * for the Microsoft (r) Incremental Linker + * + * @author Curt Arnold + */ +public abstract class DevStudioCompatibleLinker extends CommandLineLinker { + public DevStudioCompatibleLinker(String command, String identifierArg, + String outputSuffix) { + super(command, identifierArg, new String[]{".obj", ".lib", ".res"}, + new String[]{".map", ".pdb", ".lnk", ".dll"}, outputSuffix, + false, null); + } + protected void addBase(long base, Vector args) { + if (base >= 0) { + String baseAddr = Long.toHexString(base); + args.addElement("/BASE:0x" + baseAddr); + } + } + protected void addFixed(Boolean fixed, Vector args) { + if (fixed != null) { + if (fixed.booleanValue()) { + args.addElement("/FIXED"); + } else { + args.addElement("/FIXED:NO"); + } + } + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args) { + args.addElement("/NOLOGO"); + if (debug) { + args.addElement("/DEBUG"); + } + if (linkType.isSharedLibrary()) { + args.addElement("/DLL"); + } + // + // The following lines were commented out + // from v 1.5 to v 1.12 with no explanation + // + if(linkType.isSubsystemGUI()) { + args.addElement("/SUBSYSTEM:WINDOWS"); } else { + if(linkType.isSubsystemConsole()) { + args.addElement("/SUBSYSTEM:CONSOLE"); } } + } + protected void addIncremental(boolean incremental, Vector args) { + if (incremental) { + args.addElement("/INCREMENTAL:YES"); + } else { + args.addElement("/INCREMENTAL:NO"); + } + } + protected void addMap(boolean map, Vector args) { + if (map) { + args.addElement("/MAP"); + } + } + protected void addStack(int stack, Vector args) { + if (stack >= 0) { + String stackStr = Integer.toHexString(stack); + args.addElement("/STACK:0x" + stackStr); + } + } + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addEntry(int, java.util.Vector) + */ + protected void addEntry(String entry, Vector args) { + if (entry != null) { + args.addElement("/ENTRY:" + entry); + } + } + + public String getCommandFileSwitch(String commandFile) { + return "@" + commandFile; + } + public File[] getLibraryPath() { + return CUtil.getPathFromEnvironment("LIB", ";"); + } + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + StringBuffer buf = new StringBuffer(); + String[] patterns = new String[libnames.length]; + for (int i = 0; i < libnames.length; i++) { + buf.setLength(0); + buf.append(libnames[i]); + buf.append(".lib"); + patterns[i] = buf.toString(); + } + return patterns; + } + public int getMaximumCommandLength() { + return 32767; + } + public String[] getOutputFileSwitch(String outputFile) { + return new String[]{"/OUT:" + outputFile}; + } + public boolean isCaseSensitive() { + return false; + } + + /** + * Adds source or object files to the bidded fileset to + * support version information. + * + * @param versionInfo version information + * @param linkType link type + * @param isDebug true if debug build + * @param outputFile name of generated executable + * @param objDir directory for generated files + * @param matcher bidded fileset + */ + public void addVersionFiles(final VersionInfo versionInfo, + final LinkType linkType, + final File outputFile, + final boolean isDebug, + final File objDir, + final TargetMatcher matcher) throws IOException { + WindowsPlatform.addVersionFiles(versionInfo, linkType, outputFile, isDebug, objDir, matcher); + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioLibrarian.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioLibrarian.java new file mode 100644 index 0000000..bd63f42 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioLibrarian.java @@ -0,0 +1,36 @@ +/* + * + * Copyright 2002-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. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +/** + * Adapter for the Microsoft (r) Library Manager + * + * @author Curt Arnold + */ +public final class DevStudioLibrarian extends DevStudioCompatibleLibrarian { + private static final DevStudioLibrarian instance = new DevStudioLibrarian(); + public static DevStudioLibrarian getInstance() { + return instance; + } + private DevStudioLibrarian() { + super("lib", "/bogus"); + } + public Linker getLinker(LinkType type) { + return DevStudioLinker.getInstance().getLinker(type); + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioLinker.java new file mode 100644 index 0000000..826074b --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioLinker.java @@ -0,0 +1,44 @@ +/* + * + * Copyright 2001-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. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +/** + * Adapter for the Microsoft (r) Incremental Linker + * + * @author Adam Murdoch + * @author Curt Arnold + */ +public final class DevStudioLinker extends DevStudioCompatibleLinker { + private static final DevStudioLinker dllLinker = new DevStudioLinker(".dll"); + private static final DevStudioLinker instance = new DevStudioLinker(".exe"); + public static DevStudioLinker getInstance() { + return instance; + } + private DevStudioLinker(String outputSuffix) { + super("link", "/DLL", outputSuffix); + } + public Linker getLinker(LinkType type) { + if (type.isSharedLibrary()) { + return dllLinker; + } + if (type.isStaticLibrary()) { + return DevStudioLibrarian.getInstance(); + } + return instance; + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioMIDLCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioMIDLCompiler.java new file mode 100644 index 0000000..fa2e414 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioMIDLCompiler.java @@ -0,0 +1,112 @@ +/* + * + * Copyright 2002-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. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import java.io.File; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.CUtil; +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 org.apache.tools.ant.types.Environment; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +/** + * Adapter for the Microsoft (r) MIDL Compiler + * + * @author Curt Arnold + */ +public final class DevStudioMIDLCompiler extends CommandLineCompiler { + private static final DevStudioMIDLCompiler instance = new DevStudioMIDLCompiler( + false, null); + public static DevStudioMIDLCompiler getInstance() { + return instance; + } + private DevStudioMIDLCompiler(boolean newEnvironment, Environment env) { + super("midl", null, new String[]{".idl", ".odl"}, new String[]{}, + ".tlb", 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) { + } + protected void addWarningSwitch(Vector args, int level) { + DevStudioProcessor.addWarningSwitch(args, level); + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new DevStudioMIDLCompiler(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 3; + } + protected void getDefineSwitch(StringBuffer buffer, String define, + String value) { + DevStudioProcessor.getDefineSwitch(buffer, define, value); + } + protected File[] getEnvironmentIncludePath() { + return CUtil.getPathFromEnvironment("INCLUDE", ";"); + } + protected String getIncludeDirSwitch(String includeDir) { + return DevStudioProcessor.getIncludeDirSwitch(includeDir); + } + protected String getInputFileArgument(File outputDir, String filename, + int index) { + switch (index) { + case 0 : + return "/tlb"; + case 1 : + return new File(outputDir, getOutputFileNames(filename, null)[0]) + .getAbsolutePath(); + } + return filename; + } + public Linker getLinker(LinkType type) { + return DevStudioLinker.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); + String arg3 = getInputFileArgument(outputDir, inputFile, 2); + return arg1.length() + arg2.length() + arg3.length() + 3; + } + protected void getUndefineSwitch(StringBuffer buffer, String define) { + DevStudioProcessor.getUndefineSwitch(buffer, define); + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioProcessor.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioProcessor.java new file mode 100644 index 0000000..8257c09 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioProcessor.java @@ -0,0 +1,90 @@ +/* + * + * Copyright 2002-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. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import java.util.Vector; +/** + * A add-in class for Microsoft Developer Studio processors + * + * + */ +public class DevStudioProcessor { + public static void addWarningSwitch(Vector args, int level) { + switch (level) { + case 0 : + args.addElement("/W0"); + break; + case 1 : + args.addElement("/W1"); + break; + case 2 : + break; + case 3 : + args.addElement("/W3"); + break; + case 4 : + args.addElement("/W4"); + break; + case 5 : + args.addElement("/WX"); + break; + } + } + public static String getCommandFileSwitch(String cmdFile) { + StringBuffer buf = new StringBuffer("@"); + if (cmdFile.indexOf(' ') >= 0) { + buf.append('\"'); + buf.append(cmdFile.replace('/', '\\')); + buf.append('\"'); + } else { + buf.append(cmdFile); + } + return buf.toString(); + } + public static 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); + } + } + public static String getIncludeDirSwitch(String includeDir) { + return "/I" + includeDir.replace('/', '\\'); + } + public static String[] getOutputFileSwitch(String outPath) { + StringBuffer buf = new StringBuffer("/Fo"); + if (outPath.indexOf(' ') >= 0) { + buf.append('\"'); + buf.append(outPath); + buf.append('\"'); + } else { + buf.append(outPath); + } + String[] retval = new String[]{buf.toString()}; + return retval; + } + public static void getUndefineSwitch(StringBuffer buffer, String define) { + buffer.append("/U"); + buffer.append(define); + } + public static boolean isCaseSensitive() { + return false; + } + private DevStudioProcessor() { + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioProjectWriter.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioProjectWriter.java new file mode 100644 index 0000000..51ab1dd --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioProjectWriter.java @@ -0,0 +1,710 @@ +/* + * + * 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 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 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. + * + * Status: Collects file list but does not pick + * up libraries and settings from project. + * + * @author curta + */ +public final class DevStudioProjectWriter + implements ProjectWriter { + /** + * Visual Studio version. + */ + private String version; + + /** + * Constructor. + * @param versionArg String Visual Studio version. + */ + public DevStudioProjectWriter(final String versionArg) { + 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 + * @param task cc task for which to write project + * @param projectDef project element + * @param files source files + * @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 files, + final Hashtable targets, + final TargetInfo linkTarget) throws IOException { + + // + // 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 + String projectName = projectDef.getName(); + if (projectName != null) { + projectName = toProjectName(projectName); + } else { + projectName = toProjectName(fileName.getName()); + } + + final String basePath = fileName.getAbsoluteFile().getParent(); + + File dspFile = new File(fileName + ".dsp"); + if (!projectDef.getOverwrite() && dspFile.exists()) { + throw new BuildException("Not allowed to overwrite project file " + + dspFile.toString()); + } + File dswFile = new File(fileName + ".dsw"); + if (!projectDef.getOverwrite() && dswFile.exists()) { + throw new BuildException("Not allowed to overwrite project file " + + dswFile.toString()); + } + + CommandLineCompilerConfiguration compilerConfig = + getBaseCompilerConfiguration(targets); + if (compilerConfig == null) { + throw new BuildException( + "Unable to generate Visual Studio project " + + "when Microsoft C++ is not used."); + } + + Writer writer = new BufferedWriter(new FileWriter(dspFile)); + writer.write("# Microsoft Developer Studio Project File - Name=\""); + writer.write(projectName); + writer.write("\" - Package Owner=<4>\r\n"); + writer.write( + "# Microsoft Developer Studio Generated Build File, Format Version "); + 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 targtype = "Win32 (x86) Dynamic-Link Library"; + String targid = "0x0102"; + if ("executable".equals(outputType)) { + if ("console".equals(subsystem)) { + targtype = "Win32 (x86) Console Application"; + targid = "0x0103"; + } else { + targtype = "Win32 (x86) Application"; + targid = "0x0101"; + } + } else if ("static".equals(outputType)) { + targtype = "Win32 (x86) Static Library"; + targid = "0x0104"; + } + writer.write("# TARGTYPE \""); + writer.write(targtype); + writer.write("\" "); + writer.write(targid); + writer.write("\r\n\r\nCFG="); + + writer.write(projectName + " - Win32 Debug"); + writer.write("\r\n"); + + writeMessage(writer, projectName, targtype); + + writer.write("# Begin Project\r\n"); + if (version.equals("6.00")) { + writer.write("# PROP AllowPerConfigDependencies 0\r\n"); + } + writer.write("# PROP Scc_ProjName \"\"\r\n"); + writer.write("# PROP Scc_LocalPath \"\"\r\n"); + writer.write("CPP=cl.exe\r\n"); + writer.write("MTL=midl.exe\r\n"); + writer.write("RSC=rc.exe\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"); + + writer.write("# Begin Target\r\n\r\n"); + writer.write("# Name \"" + projectName + " - Win32 Release\"\r\n"); + writer.write("# Name \"" + projectName + " - Win32 Debug\"\r\n"); + + + + File[] sortedSources = getSources(files); + + if (version.equals("6.00")) { + final String sourceFilter = "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"; + final String headerFilter = "h;hpp;hxx;hm;inl"; + final String resourceFilter = + "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"; + + writer.write("# Begin Group \"Source Files\"\r\n\r\n"); + writer.write("# PROP Default_Filter \"" + sourceFilter + "\"\r\n"); + + for (int i = 0; i < sortedSources.length; i++) { + if (!isGroupMember(headerFilter, sortedSources[i]) + && !isGroupMember(resourceFilter, sortedSources[i])) { + writeSource(writer, basePath, sortedSources[i]); + } + } + writer.write("# End Group\r\n"); + + writer.write("# Begin Group \"Header Files\"\r\n\r\n"); + writer.write("# PROP Default_Filter \"" + headerFilter + "\"\r\n"); + + for (int i = 0; i < sortedSources.length; i++) { + if (isGroupMember(headerFilter, sortedSources[i])) { + writeSource(writer, basePath, sortedSources[i]); + } + } + writer.write("# End Group\r\n"); + + writer.write("# Begin Group \"Resource Files\"\r\n\r\n"); + writer.write("# PROP Default_Filter \"" + resourceFilter + "\"\r\n"); + + for (int i = 0; i < sortedSources.length; i++) { + if (isGroupMember(resourceFilter, sortedSources[i])) { + writeSource(writer, basePath, sortedSources[i]); + } + } + writer.write("# End Group\r\n"); + + } else { + for (int i = 0; i < sortedSources.length; i++) { + writeSource(writer, basePath, sortedSources[i]); + } + } + + writer.write("# End Target\r\n"); + writer.write("# End Project\r\n"); + writer.close(); + + // + // write workspace file + // + writer = new BufferedWriter(new FileWriter(dswFile)); + writeWorkspace(writer, projectDef, projectName, dspFile); + writer.close(); + + } + + 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("# 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"); + + } + + 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("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"); + + } + + /** + * Returns true if the file has an extension that appears in the group filter. + * @param filter String group filter + * @param candidate File file + * @return boolean true if member of group + */ + private boolean isGroupMember(final String filter, final File candidate) { + String fileName = candidate.getName(); + int lastDot = fileName.lastIndexOf('.'); + if (lastDot >= 0 && lastDot < fileName.length() - 1) { + String extension = + ";" + fileName.substring(lastDot + 1).toLowerCase() + ";"; + String semiFilter = ";" + filter + ";"; + return semiFilter.indexOf(extension) >= 0; + } + return false; + } + + /** + * Writes the entry for one source file in the project. + * @param writer Writer writer + * @param basePath String base path for project + * @param groupMember File project source file + * @throws IOException if error writing project file + */ + private void writeSource(final Writer writer, + final String basePath, + final File groupMember) + throws IOException { + writer.write("# Begin Source File\r\n\r\nSOURCE="); + String relativePath = CUtil.getRelativePath(basePath, + groupMember); + // + // if relative path is just a name (hello.c) then + // make it .\hello.c + if (!relativePath.startsWith(".") + && relativePath.indexOf(":") < 0 + && !relativePath.startsWith("\\")) { + relativePath = ".\\" + relativePath; + } + writer.write(CUtil.toWindowsPath(relativePath)); + writer.write("\r\n# End Source File\r\n"); + } + + /** + * Get alphabetized array of source files. + * @param sourceList list of source files + * @return File[] source files + */ + private File[] getSources(final List sourceList) { + File[] sortedSources = new File[sourceList.size()]; + sourceList.toArray(sortedSources); + Arrays.sort(sortedSources, new Comparator() { + public int compare(final Object o1, final Object o2) { + return ((File) o1).getName().compareTo(((File) o2).getName()); + } + }); + return sortedSources; + } + + /** + * Writes "This is not a makefile" warning. + * @param writer Writer writer + * @param projectName String project name + * @param targtype String target type + * @throws IOException if error writing project + */ + + private void writeMessage(final Writer writer, + final String projectName, + final String targtype) throws IOException { + writer.write( + "!MESSAGE This is not a valid makefile. "); + writer.write("To build this project using NMAKE,\r\n"); + writer.write("!MESSAGE use the Export Makefile command and run\r\n"); + writer.write("!MESSAGE \r\n"); + writer.write("!MESSAGE NMAKE /f \""); + writer.write(projectName); + writer.write(".mak\".\r\n"); + writer.write("!MESSAGE \r\n"); + writer.write( + "!MESSAGE You can specify a configuration when running NMAKE\r\n"); + writer.write( + "!MESSAGE by defining the macro CFG on the command line. "); + writer.write("For example:\r\n"); + writer.write("!MESSAGE \r\n"); + writer.write("!MESSAGE NMAKE /f \""); + writer.write(projectName); + writer.write(".mak\" CFG=\""); + 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"); + 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"); + + } + + /** + * Gets the first recognized compiler from the + * compilation targets. + * @param targets compilation targets + * @return representative (hopefully) compiler configuration + */ + private CommandLineCompilerConfiguration + getBaseCompilerConfiguration(final Hashtable targets) { + // + // find first target with an DevStudio 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 DevStudioCCompiler) { + return compilerConfig; + } + } + } + return null; + } + + /** + * 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 { + StringBuffer baseOptions = new StringBuffer(50); + baseOptions.append("# ADD BASE CPP"); + StringBuffer options = new StringBuffer(50); + options.append("# ADD CPP"); + File[] includePath = compilerConfig.getIncludePath(); + for (int i = 0; i < includePath.length; i++) { + options.append(" /I \""); + String relPath = CUtil.getRelativePath(baseDir, includePath[i]); + 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++) { + if (preArgs[i].startsWith("/D")) { + options.append(" /D "); + baseOptions.append(" /D "); + String body = preArgs[i].substring(2); + if (preArgs[i].indexOf('=') >= 0) { + options.append(body); + baseOptions.append(body); + } else { + 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(option); + baseOptions.append(" "); + baseOptions.append(option); + } + } + baseOptions.append("\r\n"); + options.append("\r\n"); + writer.write(baseOptions.toString()); + writer.write(options.toString()); + + } + + + + + + /** + * 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 { + + StringBuffer baseOptions = new StringBuffer(100); + StringBuffer options = new StringBuffer(100); + baseOptions.append("# ADD BASE LINK32"); + options.append("# ADD LINK32"); + + ProcessorConfiguration config = linkTarget.getConfiguration(); + if (config instanceof CommandLineLinkerConfiguration) { + CommandLineLinkerConfiguration linkConfig = + (CommandLineLinkerConfiguration) config; + + File[] linkSources = linkTarget.getAllSources(); + for (int i = 0; i < linkSources.length; i++) { + // + // if file was not compiled or otherwise generated + // + if (targets.get(linkSources[i].getName()) == null) { + // + // 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++) { + 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++) { + options.append(' '); + options.append(endArgs[i]); + baseOptions.append(' '); + baseOptions.append(endArgs[i]); + } + } + baseOptions.append("\r\n"); + options.append("\r\n"); + 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/DevStudioResourceCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioResourceCompiler.java new file mode 100644 index 0000000..6f8360b --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioResourceCompiler.java @@ -0,0 +1,119 @@ +/* + * + * Copyright 2002-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. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +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 Microsoft (r) Windows 32 Resource Compiler + * + * @author Curt Arnold + */ +public final class DevStudioResourceCompiler extends CommandLineCompiler { + private static final DevStudioResourceCompiler instance = new DevStudioResourceCompiler( + false, null); + public static DevStudioResourceCompiler getInstance() { + return instance; + } + private String identifier; + private DevStudioResourceCompiler(boolean newEnvironment, Environment env) { + super("rc", null, new String[]{".rc"}, new String[]{".h", ".hpp", + ".inl"}, ".res", 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 DevStudioResourceCompiler(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) { + DevStudioProcessor.getDefineSwitch(buffer, define, value); + } + protected File[] getEnvironmentIncludePath() { + return CUtil.getPathFromEnvironment("INCLUDE", ";"); + } + protected String getIncludeDirSwitch(String includeDir) { + return DevStudioProcessor.getIncludeDirSwitch(includeDir); + } + protected String getInputFileArgument(File outputDir, String filename, + int index) { + if (index == 0) { + String outputFileName = getOutputFileNames(filename, null)[0]; + String fullOutputName = new File(outputDir, outputFileName) + .toString(); + return "/fo" + fullOutputName; + } + return filename; + } + public Linker getLinker(LinkType type) { + return DevStudioLinker.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) { + DevStudioProcessor.getUndefineSwitch(buffer, define); + } + public String getIdentifier() { + return "Microsoft (R) Windows (R) Resource Compiler"; + } +} diff --git a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/VisualStudioNETProjectWriter.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/VisualStudioNETProjectWriter.java new file mode 100644 index 0000000..f554e09 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/VisualStudioNETProjectWriter.java @@ -0,0 +1,866 @@ +/* + * + * 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 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 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.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.XMLSerializer; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Writes a Visual Studio.NET project file. + * + * @author curta + */ +public final class VisualStudioNETProjectWriter + implements ProjectWriter { + /** + * Version of VisualStudio.NET. + */ + private final String version; + + /** + * Literal to represent a true value. + */ + private final String trueLiteral; + + /** + * Literal to represent a false value. + */ + private final String falseLiteral; + + /** + * Constructor. + * + * @param versionArg String VisualStudio.NET version + * @param trueArg literal to represent true, "true" in VC 2005. + * @param falseArg literal to represent false, "false" in VC 2005. + */ + public VisualStudioNETProjectWriter(final String versionArg, + final String trueArg, + final String falseArg) { + if (versionArg == null) { + throw new IllegalArgumentException("versionArg"); + } + if (trueArg == null) { + throw new IllegalArgumentException("trueArg"); + } + if (falseArg == null) { + throw new IllegalArgumentException("falseArg"); + } + this.version = versionArg; + this.trueLiteral = trueArg; + this.falseLiteral = falseArg; + } + + + + /** + * Gets the configuration type. + * + * @param task cc task, may not be null. + * @return configuration type + */ + private String getConfigurationType(final CCTask task) { + String outputType = task.getOuttype(); + String targtype = "2"; // Win32 (x86) Dynamic-Link Library"; + if ("executable".equals(outputType)) { + targtype = "1"; // "Win32 (x86) Console Application"; + } else if ("static".equals(outputType)) { + targtype = "4"; //"Win32 (x86) Static Library"; + } + return targtype; + } + + + + /** + * Get character set for Windows API. + * @param compilerConfig compiler configuration, may not be null. + * @return "1" is TCHAR is unicode, "0" if TCHAR is multi-byte. + */ + private String getCharacterSet( + final CommandLineCompilerConfiguration compilerConfig) { + String[] args = compilerConfig.getPreArguments(); + String charset = "0"; + for (int i = 0; i < args.length; i++) { + if ("/D_UNICODE".equals(args[i]) || "/DUNICODE".equals(args[i])) { + charset = "1"; + } + if ("/D_MBCS".equals(args[i])) { + charset = "2"; + } + } + return charset; + } + + /** + * Write the start tag of the Configuration element. + * @param content serialization content handler. + * @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 boolean isDebug, + final CCTask task, + final CommandLineCompilerConfiguration compilerConfig) + throws SAXException { + AttributesImpl attributes = new AttributesImpl(); + 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", + getCharacterSet(compilerConfig)); + content.startElement(null, + "Configuration", "Configuration", attributes); + } + + /** + * Get value of Optimization property. + * @param compilerConfig compiler configuration, may not be null. + * @return value of Optimization property. + */ + private String getOptimization( + final CommandLineCompilerConfiguration compilerConfig) { + String[] args = compilerConfig.getPreArguments(); + String opt = "0"; + for (int i = 0; i < args.length; i++) { + if ("/Od".equals(args[i])) { + opt = "0"; + } + if ("/O1".equals(args[i])) { + opt = "1"; + } + if ("/O2".equals(args[i])) { + opt = "2"; + } + if ("/Ox".equals(args[i])) { + opt = "3"; + } + } + return opt; + } + + /** + * 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(); + 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); + } + return includeDirs.toString(); + } + + /** + * 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 boolean isDebug) { + StringBuffer defines = new StringBuffer(); + String[] args = compilerConfig.getPreArguments(); + for (int i = 0; i < args.length; i++) { + if (args[i].startsWith("/D")) { + 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(";"); + } + } + + if (defines.length() > 0) { + defines.setLength(defines.length() - 1); + } + return defines.toString(); + } + + /** + * 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 boolean isDebug) { + String rtl = null; + String[] args = compilerConfig.getPreArguments(); + for (int i = 0; i < args.length; i++) { + 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; + } + + /** + * Get value of UsePrecompiledHeader property. + * @param compilerConfig compiler configuration. + * @return value of UsePrecompiledHeader property. + */ + private String getUsePrecompiledHeader( + final CommandLineCompilerConfiguration compilerConfig) { + String usePCH = "0"; + String[] args = compilerConfig.getPreArguments(); + for (int i = 0; i < args.length; i++) { + if ("/Yc".equals(args[i])) { + usePCH = "1"; + } + if ("/Yu".equals(args[i])) { + usePCH = "2"; + } + } + return usePCH; + } + + /** + * Get value of PrecompiledHeaderFile property. + * @param compilerConfig compiler configuration. + * @return value of PrecompiledHeaderFile property. + */ + private String getPrecompiledHeaderFile( + final CommandLineCompilerConfiguration compilerConfig) { + String pch = null; + String[] args = compilerConfig.getPreArguments(); + for (int i = 0; i < args.length; i++) { + if (args[i].startsWith("/Fp")) { + pch = args[i].substring(3); + } + } + return pch; + } + + + + /** + * Get value of BasicRuntimeChecks property. + * @param compilerConfig compiler configuration. + * @return value of BasicRuntimeChecks property. + */ + private String getBasicRuntimeChecks( + final CommandLineCompilerConfiguration compilerConfig) { + String checks = "0"; + String[] args = compilerConfig.getPreArguments(); + for (int i = 0; i < args.length; i++) { + if ("/RTCs".equals(args[i])) { + checks = "1"; + } + if ("/RTCu".equals(args[i])) { + checks = "2"; + } + if ("/RTC1".equals(args[i]) || "/GZ".equals(args[i])) { + checks = "3"; + } + } + return checks; + } + + /** + * Get value of WarningLevel property. + * @param compilerConfig compiler configuration. + * @return value of WarningLevel property. + */ + private String getWarningLevel( + final CommandLineCompilerConfiguration compilerConfig) { + String warn = null; + String[] args = compilerConfig.getPreArguments(); + for (int i = 0; i < args.length; i++) { + if ("/W0".equals(args[i])) { + warn = "0"; + } + if ("/W1".equals(args[i])) { + warn = "1"; + } + if ("/W2".equals(args[i])) { + warn = "2"; + } + if ("/W3".equals(args[i])) { + warn = "3"; + } + } + return warn; + } + + /** + * Get value of Detect64BitPortabilityProblems property. + * @param compilerConfig compiler configuration. + * @return value of Detect64BitPortabilityProblems property. + */ + private String getDetect64BitPortabilityProblems( + final CommandLineCompilerConfiguration compilerConfig) { + String warn64 = null; + String[] args = compilerConfig.getPreArguments(); + for (int i = 0; i < args.length; i++) { + if ("/Wp64".equals(args[i])) { + warn64 = trueLiteral; + } + } + return warn64; + } + + /** + * Get value of DebugInformationFormat property. + * @param compilerConfig compiler configuration. + * @return value of DebugInformationFormat property. + */ + private String getDebugInformationFormat( + final CommandLineCompilerConfiguration compilerConfig) { + String format = "0"; + String[] args = compilerConfig.getPreArguments(); + for (int i = 0; i < args.length; i++) { + if ("/Z7".equals(args[i])) { + format = "1"; + } + if ("/Zd".equals(args[i])) { + format = "2"; + } + if ("/Zi".equals(args[i])) { + format = "3"; + } + if ("/ZI".equals(args[i])) { + format = "4"; + } + } + return format; + } + + /** + * 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"); + 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(basePath, compilerConfig)); + addAttribute(attributes, "PreprocessorDefinitions", + getPreprocessorDefinitions(compilerConfig, isDebug)); + addAttribute(attributes, "MinimalRebuild", trueLiteral); + addAttribute(attributes, "BasicRuntimeChecks", + getBasicRuntimeChecks(compilerConfig)); + addAttribute(attributes, "RuntimeLibrary", + getRuntimeLibrary(compilerConfig, isDebug)); + addAttribute(attributes, "UsePrecompiledHeader", + getUsePrecompiledHeader(compilerConfig)); + addAttribute(attributes, "PrecompiledHeaderFile", + getPrecompiledHeaderFile(compilerConfig)); + addAttribute(attributes, "WarningLevel", + getWarningLevel(compilerConfig)); + addAttribute(attributes, "Detect64BitPortabilityProblems", + getDetect64BitPortabilityProblems(compilerConfig)); + addAttribute(attributes, "DebugInformationFormat", + debugFormat); + content.startElement(null, "Tool", "Tool", attributes); + content.endElement(null, "Tool", "Tool"); + + } + + + /** + * Get value of LinkIncremental property. + * @param linkerConfig linker configuration. + * @return value of LinkIncremental property + */ + private String getLinkIncremental( + final CommandLineLinkerConfiguration linkerConfig) { + String incremental = "0"; + String[] args = linkerConfig.getPreArguments(); + for (int i = 0; i < args.length; i++) { + if ("/INCREMENTAL:NO".equals(args[i])) { + incremental = "1"; + } + if ("/INCREMENTAL:YES".equals(args[i])) { + incremental = "2"; + } + } + return incremental; + } + + + /** + * Get value of Subsystem property. + * @param linkerConfig linker configuration. + * @return value of Subsystem property + */ + private String getSubsystem( + final CommandLineLinkerConfiguration linkerConfig) { + String subsystem = "0"; + String[] args = linkerConfig.getPreArguments(); + for (int i = 0; i < args.length; i++) { + if ("/SUBSYSTEM:CONSOLE".equals(args[i])) { + subsystem = "1"; + } + if ("/SUBSYSTEM:WINDOWS".equals(args[i])) { + subsystem = "2"; + } + if ("/SUBSYSTEM:WINDOWSCE".equals(args[i])) { + subsystem = "9"; + } + } + return subsystem; + } + + /** + * Get value of TargetMachine property. + * @param linkerConfig linker configuration. + * @return value of TargetMachine property + */ + private String getTargetMachine( + final CommandLineLinkerConfiguration linkerConfig) { + String subsystem = "0"; + String[] args = linkerConfig.getPreArguments(); + for (int i = 0; i < args.length; i++) { + if ("/MACHINE:X86".equals(args[i])) { + subsystem = "1"; + } + } + return subsystem; + } + + /** + * 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; + File[] linkSources = linkTarget.getAllSources(); + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < linkSources.length; i++) { + // + // if file was not compiled or otherwise generated + // + if (targets.get(linkSources[i].getName()) == null) { + // + // 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); + dependencies = buf.toString(); + } + return dependencies; + + } + + /** + * 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 { + AttributesImpl attributes = new AttributesImpl(); + addAttribute(attributes, "Name", "VCLinkerTool"); + + ProcessorConfiguration config = linkTarget.getConfiguration(); + if (config instanceof CommandLineLinkerConfiguration) { + CommandLineLinkerConfiguration linkerConfig = + (CommandLineLinkerConfiguration) config; + if (linkerConfig.getLinker() instanceof DevStudioCompatibleLinker) { + addAttribute(attributes, "LinkIncremental", + getLinkIncremental(linkerConfig)); + if (isDebug) { + addAttribute(attributes, "GenerateDebugInformation", trueLiteral); + } else { + addAttribute(attributes, "GenerateDebugInformation", falseLiteral); + } + addAttribute(attributes, "SubSystem", + getSubsystem(linkerConfig)); + addAttribute(attributes, "TargetMachine", + getTargetMachine(linkerConfig)); + } + } + addAttribute(attributes, "AdditionalDependencies", + getAdditionalDependencies(linkTarget, dependencies, targets, basePath)); + content.startElement(null, "Tool", "Tool", attributes); + content.endElement(null, "Tool", "Tool"); + } + + /** + * Writes a project definition file. + * + * @param fileName project name for file, should has .cbx extension + * @param task cc task for which to write project + * @param projectDef project element + * @param sources source files + * @param targets compilation targets + * @param linkTarget link target + * @throws IOException if I/O error + * @throws SAXException if XML serialization error + */ + public void writeProject(final File fileName, + final CCTask task, + final ProjectDef projectDef, + final List sources, + final Hashtable targets, + final TargetInfo linkTarget) throws + IOException, + SAXException { + + String projectName = projectDef.getName(); + if (projectName == null) { + projectName = fileName.getName(); + } + + + File vcprojFile = new File(fileName + ".vcproj"); + if (!projectDef.getOverwrite() && vcprojFile.exists()) { + throw new BuildException("Not allowed to overwrite project file " + + vcprojFile.toString()); + } + File slnFile = new File(fileName + ".sln"); + if (!projectDef.getOverwrite() && slnFile.exists()) { + throw new BuildException("Not allowed to overwrite project file " + + slnFile.toString()); + } + + CommandLineCompilerConfiguration compilerConfig = + getBaseCompilerConfiguration(targets); + if (compilerConfig == null) { + throw new BuildException( + "Unable to generate Visual Studio.NET project " + + "when Microsoft C++ is not used."); + } + + OutputStream outStream = new FileOutputStream(fileName + ".vcproj"); + OutputFormat format = new OutputFormat("xml", "UTF-8", true); + 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(); + addAttribute(attributes, "ProjectType", "Visual C++"); + addAttribute(attributes, "Version", version); + addAttribute(attributes, "Name", projectName); + content.startElement(null, "VisualStudioProject", + "VisualStudioProject", attributes); + + content.startElement(null, "Platforms", "Platforms", emptyAttrs); + attributes.clear(); + addAttribute(attributes, "Name", "Win32"); + content.startElement(null, "Platform", "Platform", attributes); + content.endElement(null, "Platform", "Platform"); + content.endElement(null, "Platforms", "Platforms"); + content.startElement(null, "Configurations", + "Configurations", emptyAttrs); + + // + // 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"); + content.startElement(null, "Files", "Files", emptyAttrs); + + + File[] sortedSources = new File[sources.size()]; + sources.toArray(sortedSources); + Arrays.sort(sortedSources, new Comparator() { + public int compare(final Object o1, final Object o2) { + return ((File) o1).getName().compareTo(((File) o2).getName()); + } + }); + + writeFilteredSources("Source Files", + "cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx", + basePath, sortedSources, content); + + writeFilteredSources("Header Files", "h;hpp;hxx;hm;inl;inc;xsd", + basePath, sortedSources, content); + + writeFilteredSources("Resource Files", + "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx", + basePath, sortedSources, content); + + content.endElement(null, "Files", "Files"); + content.startElement(null, "Globals", "Globals", emptyAttrs); + content.endElement(null, "Globals", "Globals"); + content.endElement(null, "VisualStudioProject", "VisualStudioProject"); + content.endDocument(); + } + + /** + * Writes a cluster of source files to the project. + * + * @param name name of filter + * @param filter file extensions + * @param basePath base path for files + * @param sortedSources array of source files + * @param content generated project + * @throws SAXException if invalid content + */ + private void writeFilteredSources(final String name, final String filter, + final String basePath, + final File[] sortedSources, + final ContentHandler content) + throws SAXException { + AttributesImpl filterAttrs = new AttributesImpl(); + filterAttrs.addAttribute(null, "Name", "Name", "#PCDATA", name); + filterAttrs.addAttribute(null, "Filter", "Filter", "#PCDATA", filter); + content.startElement(null, "Filter", "Filter", filterAttrs); + + + AttributesImpl fileAttrs = new AttributesImpl(); + fileAttrs.addAttribute(null, "RelativePath", "RelativePath", + "#PCDATA", ""); + + + for (int i = 0; i < sortedSources.length; i++) { + if (isGroupMember(filter, sortedSources[i])) { + String relativePath = CUtil.getRelativePath(basePath, + sortedSources[i]); + fileAttrs.setValue(0, relativePath); + content.startElement(null, "File", "File", fileAttrs); + content.endElement(null, "File", "File"); + } + } + content.endElement(null, "Filter", "Filter"); + + } + + /** + * Returns true if the file has an extension that + * appears in the group filter. + * + * @param filter String group filter + * @param candidate File file + * @return boolean true if member of group + */ + private boolean isGroupMember(final String filter, final File candidate) { + String fileName = candidate.getName(); + int lastDot = fileName.lastIndexOf('.'); + if (lastDot >= 0 && lastDot < fileName.length() - 1) { + String extension = + ";" + fileName.substring(lastDot + 1).toLowerCase() + ";"; + String semiFilter = ";" + filter + ";"; + return semiFilter.indexOf(extension) >= 0; + } + return false; + } + + + /** + * Adds an non-namespace-qualified attribute to attribute list. + * @param attributes list of attributes. + * @param attrName attribute name, may not be null. + * @param attrValue attribute value, if null attribute is not added. + */ + private static void addAttribute(final AttributesImpl attributes, + final String attrName, + final String attrValue) { + if (attrName == null) { + throw new IllegalArgumentException("attrName"); + } + if (attrValue != null) { + attributes.addAttribute(null, attrName, attrName, + "#PCDATA", attrValue); + } + } + + /** + * Gets the first recognized compiler from the + * compilation targets. + * @param targets compilation targets + * @return representative (hopefully) compiler configuration + */ + private CommandLineCompilerConfiguration + getBaseCompilerConfiguration(final Hashtable targets) { + // + // 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) { + CommandLineCompilerConfiguration compilerConfig = + (CommandLineCompilerConfiguration) config; + if (compilerConfig.getCompiler() + instanceof DevStudioCCompiler) { + return compilerConfig; + } + } + } + return null; + } +} + diff --git a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/package.html b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/package.html new file mode 100644 index 0000000..46a31b4 --- /dev/null +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/package.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<html> +<head> +<!-- + +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. + +--> +</head> +<body bgcolor="white"> + +Adapters for Microsoft tools. +</body> +</html> + |