summaryrefslogtreecommitdiff
path: root/src/main/java/net/sf/antcontrib/cpptasks/devstudio
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/net/sf/antcontrib/cpptasks/devstudio')
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudio2005CCompiler.java62
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCCompiler.java50
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleCCompiler.java136
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLibrarian.java80
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLinker.java148
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioLibrarian.java36
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioLinker.java44
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioMIDLCompiler.java112
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioProcessor.java90
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioProjectWriter.java710
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioResourceCompiler.java119
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/devstudio/VisualStudioNETProjectWriter.java866
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/devstudio/package.html27
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>
+