diff options
Diffstat (limited to 'src/main/java/net/sf/antcontrib/cpptasks/devstudio')
5 files changed, 502 insertions, 259 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/DevStudioCompatibleCCompiler.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleCCompiler.java index dc1afb3..cc4493d 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleCCompiler.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleCCompiler.java @@ -72,11 +72,7 @@ public abstract class DevStudioCompatibleCCompiler } if (debug) { mindex += 1; -// FREEHEP changed /Zi into /Z7 - args.addElement("/Zi"); - args.addElement("/Od"); - args.addElement("/GZ"); - args.addElement("/D_DEBUG"); + addDebugSwitch(args); } else { if (optimization != null) { if (optimization.isSize()) { @@ -98,6 +94,12 @@ public abstract class DevStudioCompatibleCCompiler args.addElement("/GR"); } } + protected void addDebugSwitch(Vector args) { + args.addElement("/Zi"); + args.addElement("/Od"); + args.addElement("/GZ"); + args.addElement("/D_DEBUG"); + } protected void addWarningSwitch(Vector args, int level) { DevStudioProcessor.addWarningSwitch(args, level); } diff --git a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLinker.java index 88ecd78..987948b 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLinker.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLinker.java @@ -134,7 +134,7 @@ public abstract class DevStudioCompatibleLinker extends CommandLineLinker { * @param versionInfo version information * @param linkType link type * @param isDebug true if debug build - * @param executableName name of generated executable + * @param outputFile name of generated executable * @param objDir directory for generated files * @param matcher bidded fileset */ diff --git a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioProjectWriter.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioProjectWriter.java index 94030fb..51ab1dd 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioProjectWriter.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/DevStudioProjectWriter.java @@ -1,6 +1,6 @@ /* * - * Copyright 2004 The Ant-Contrib project + * Copyright 2004-2008 The Ant-Contrib project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,27 +16,26 @@ */ package net.sf.antcontrib.cpptasks.devstudio; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.Writer; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.List; - import net.sf.antcontrib.cpptasks.CCTask; import net.sf.antcontrib.cpptasks.CUtil; import net.sf.antcontrib.cpptasks.TargetInfo; import net.sf.antcontrib.cpptasks.compiler.CommandLineCompilerConfiguration; import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; import net.sf.antcontrib.cpptasks.compiler.ProcessorConfiguration; +import net.sf.antcontrib.cpptasks.ide.DependencyDef; import net.sf.antcontrib.cpptasks.ide.ProjectDef; import net.sf.antcontrib.cpptasks.ide.ProjectWriter; +import net.sf.antcontrib.cpptasks.ide.CommentDef; import org.apache.tools.ant.BuildException; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.*; +import java.text.MessageFormat; + /** * Writes a Microsoft Visual Studio 97 or Visual Studio 6 project file. * @@ -60,6 +59,24 @@ public final class DevStudioProjectWriter this.version = versionArg; } + private static String toProjectName(final String name) { + // + // some characters are apparently not allowed in VS project names + // but have not been able to find them documented + // limiting characters to alphas, numerics and hyphens + StringBuffer projectNameBuf = new StringBuffer(name); + for (int i = 0; i < projectNameBuf.length(); i++) { + final char ch = projectNameBuf.charAt(i); + if (!((ch >= 'a' && ch <= 'z') + || (ch >= 'A' && ch <= 'Z') + || (ch >= '0' && ch <= '9'))) { + projectNameBuf.setCharAt(i, '_'); + } + } + return projectNameBuf.toString(); + + } + /** * Writes a project definition file. * @param fileName File name base, writer may append appropriate extension @@ -81,22 +98,12 @@ public final class DevStudioProjectWriter // some characters are apparently not allowed in VS project names // but have not been able to find them documented // limiting characters to alphas, numerics and hyphens - StringBuffer projectNameBuf; String projectName = projectDef.getName(); if (projectName != null) { - projectNameBuf = new StringBuffer(projectName); + projectName = toProjectName(projectName); } else { - projectNameBuf = new StringBuffer(fileName.getName()); - } - for (int i = 0; i < projectNameBuf.length(); i++) { - final char ch = projectNameBuf.charAt(i); - if (!((ch >= 'a' && ch <= 'z') - || (ch >= 'A' && ch <= 'Z') - || (ch >= '0' && ch <= '9'))) { - projectNameBuf.setCharAt(i, '_'); - } + projectName = toProjectName(fileName.getName()); } - projectName = projectNameBuf.toString(); final String basePath = fileName.getAbsoluteFile().getParent(); @@ -128,15 +135,11 @@ public final class DevStudioProjectWriter writer.write(this.version); writer.write("\r\n"); writer.write("# ** DO NOT EDIT **\r\n\r\n"); + + writeComments(writer, projectDef.getComments()); + String outputType = task.getOuttype(); String subsystem = task.getSubsystem(); - String configName = projectName; - final boolean isDebug = task.getDebug(); - if (isDebug) { - configName += " - Win32 Debug"; - } else { - configName += " - Win32 Release"; - } String targtype = "Win32 (x86) Dynamic-Link Library"; String targid = "0x0102"; if ("executable".equals(outputType)) { @@ -156,10 +159,11 @@ public final class DevStudioProjectWriter writer.write("\" "); writer.write(targid); writer.write("\r\n\r\nCFG="); - writer.write(configName); + + writer.write(projectName + " - Win32 Debug"); writer.write("\r\n"); - writeMessage(writer, projectName, configName, targtype); + writeMessage(writer, projectName, targtype); writer.write("# Begin Project\r\n"); if (version.equals("6.00")) { @@ -170,59 +174,22 @@ public final class DevStudioProjectWriter writer.write("CPP=cl.exe\r\n"); writer.write("MTL=midl.exe\r\n"); writer.write("RSC=rc.exe\r\n"); - writer.write("# PROP BASE Use_MFC 0\r\n"); - writer.write("# PROP BASE Use_Debug_Libraries "); - if (isDebug) { - writer.write("1\r\n"); - } else { - writer.write("0\r\n"); - } + writer.write("\r\n!IF \"$(CFG)\" == \"" + projectName + " - Win32 Release\"\r\n"); + + writeConfig(writer, false, projectDef.getDependencies(), basePath, compilerConfig, linkTarget, targets); + + writer.write("\r\n!ELSEIF \"$(CFG)\" == \"" + projectName + " - Win32 Debug\"\r\n"); + + writeConfig(writer, true, projectDef.getDependencies(), basePath, compilerConfig, linkTarget, targets); + + writer.write("\r\n!ENDIF\r\n"); - File objDir = task.getObjdir(); - String objDirPath = CUtil.getRelativePath(basePath, objDir); - - File outFile = task.getOutfile(); - File buildDir = outFile.getParentFile(); - String buildDirPath = CUtil.getRelativePath(basePath, buildDir); - - writer.write("# PROP BASE Output_Dir \""); - writer.write(buildDirPath); - writer.write("\"\r\n"); - writer.write("# PROP BASE Intermediate_Dir \""); - writer.write(objDirPath); - writer.write("\"\r\n"); - writer.write("# PROP BASE Target_Dir \"\"\r\n"); - writer.write("# PROP Use_MFC 0\r\n"); - writer.write("# PROP Use_Debug_Libraries "); - if (isDebug) { - writer.write("1\r\n"); - } else { - writer.write("0\r\n"); - } - writer.write("# PROP Output_Dir \""); - writer.write(buildDirPath); - writer.write("\"\r\n"); - writer.write("# PROP Intermediate_Dir \""); - writer.write(objDirPath); - writer.write("\"\r\n"); - writer.write("# PROP Target_Dir \"\"\r\n"); - writeCompileOptions(writer, basePath, compilerConfig); - writer.write( - "# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /o NUL /win32\r\n"); - writer.write( - "# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /o NUL /win32\r\n"); - writer.write("# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\r\n"); - writer.write("# ADD RSC /l 0x409 /d \"_DEBUG\"\r\n"); - writer.write("BSC32=bscmake.exe\r\n"); - writer.write("# ADD BASE BSC32 /nologo\r\n"); - writer.write("# ADD BSC32 /nologo\r\n"); - writer.write("LINK32=link.exe\r\n"); - writeLinkOptions(writer, basePath, linkTarget, targets); writer.write("# Begin Target\r\n\r\n"); - writer.write("# Name \""); - writer.write(configName); - writer.write("\"\r\n"); + writer.write("# Name \"" + projectName + " - Win32 Release\"\r\n"); + writer.write("# Name \"" + projectName + " - Win32 Debug\"\r\n"); + + File[] sortedSources = getSources(files); @@ -277,30 +244,128 @@ public final class DevStudioProjectWriter // write workspace file // writer = new BufferedWriter(new FileWriter(dswFile)); + writeWorkspace(writer, projectDef, projectName, dspFile); + writer.close(); - writer.write("Microsoft Developer Studio Workspace File, Format Version "); - writer.write(version); - writer.write("\r\n"); - writer.write("# WARNING: DO NOT EDIT OR DELETE"); - writer.write(" THIS WORKSPACE FILE!\r\n\r\n"); + } - writer.write("############################################"); - writer.write("###################################\r\n\r\n"); - writer.write("Project: \"" + projectName + "\"=.\\" - + dspFile.getName() - + " - Package Owner=<4>\r\n\r\n"); + private void writeConfig(final Writer writer, + boolean isDebug, + final List dependencies, + final String basePath, + CommandLineCompilerConfiguration compilerConfig, + TargetInfo linkTarget, + Hashtable targets) throws IOException { + writer.write("# PROP BASE Use_MFC 0\r\n"); + + String configType = "Release"; + String configInt = "0"; + String configMacro = "NDEBUG"; + if (isDebug) { + configType = "Debug"; + configInt = "1"; + configMacro = "_DEBUG"; + } - writer.write("Package=<5>\r\n{{{\r\n}}}\r\n\r\n"); - writer.write("Package=<4>\r\n{{{\r\n}}}\r\n\r\n"); - writer.write("######################################"); - writer.write("#########################################\r\n\r\n"); + writer.write("# PROP BASE Use_Debug_Libraries "); + writer.write(configInt); + writer.write("\r\n# PROP BASE Output_Dir \""); + writer.write(configType); + writer.write("\"\r\n"); + writer.write("# PROP BASE Intermediate_Dir \""); + writer.write(configType); + writer.write("\"\r\n"); + writer.write("# PROP BASE Target_Dir \"\"\r\n"); + writer.write("# PROP Use_MFC 0\r\n"); + writer.write("# PROP Use_Debug_Libraries "); + writer.write(configInt); + writer.write("\r\n# PROP Output_Dir \""); + writer.write(configType); + writer.write("\"\r\n"); + writer.write("# PROP Intermediate_Dir \""); + writer.write(configType); + writer.write("\"\r\n"); + writer.write("# PROP Target_Dir \"\"\r\n"); + writeCompileOptions(writer, isDebug, basePath, compilerConfig); + writer.write( + "# ADD BASE MTL /nologo /D \"" + configMacro + "\" /mktyplib203 /o NUL /win32\r\n"); + writer.write( + "# ADD MTL /nologo /D \"" + configMacro + "\" /mktyplib203 /o NUL /win32\r\n"); + writer.write("# ADD BASE RSC /l 0x409 /d \"" + configMacro + "\"\r\n"); + writer.write("# ADD RSC /l 0x409 /d \"" + configMacro + "\"\r\n"); + writer.write("BSC32=bscmake.exe\r\n"); + writer.write("# ADD BASE BSC32 /nologo\r\n"); + writer.write("# ADD BSC32 /nologo\r\n"); + writer.write("LINK32=link.exe\r\n"); + writeLinkOptions(writer, isDebug, dependencies, basePath, linkTarget, targets); + } + private static void writeWorkspaceProject(final Writer writer, + final String projectName, + final String projectFile, + final List dependsOn) throws IOException { + writer.write("############################################"); + writer.write("###################################\r\n\r\n"); + String file = projectFile; + if(!file.startsWith(".") && !file.startsWith("\\") && !file.startsWith("/")) { + file = ".\\" + file; + } + writer.write("Project: \"" + projectName + "\"=\"" + + file + + "\" - Package Owner=<4>\r\n\r\n"); + + writer.write("Package=<5>\r\n{{{\r\n}}}\r\n\r\n"); + writer.write("Package=<4>\r\n{{{\r\n"); + if (dependsOn != null) { + for(Iterator iter = dependsOn.iterator(); iter.hasNext();) { + writer.write(" Begin Project Dependency\r\n"); + writer.write(" Project_Dep_Name " + toProjectName(String.valueOf(iter.next())) + "\r\n"); + writer.write(" End Project Dependency\r\n"); + } + } + writer.write("}}}\r\n\r\n"); - writer.write("Global:\r\n\r\nPackage=<5>\r\n{{{\r\n}}}"); - writer.write("\r\n\r\nPackage=<3>\r\n{{{\r\n}}}\r\n\r\n"); + } + + private void writeWorkspace(final Writer writer, + final ProjectDef project, + final String projectName, + final File dspFile) throws IOException { + + writer.write("Microsoft Developer Studio Workspace File, Format Version "); + writer.write(version); + writer.write("\r\n"); + writer.write("# WARNING: DO NOT EDIT OR DELETE"); + writer.write(" THIS WORKSPACE FILE!\r\n\r\n"); + + writeComments(writer, project.getComments()); + + + List dependencies = project.getDependencies(); + List projectDeps = new ArrayList(); + String basePath = dspFile.getParent(); + for(Iterator iter = dependencies.iterator(); iter.hasNext();) { + DependencyDef dep = (DependencyDef) iter.next(); + if (dep.getFile() != null) { + String projName = toProjectName(dep.getName()); + projectDeps.add(projName); + String depProject = CUtil.toWindowsPath( + CUtil.getRelativePath(basePath, + new File(dep.getFile() + ".dsp"))); + writeWorkspaceProject(writer, projName, depProject, dep.getDependsList()); + } + } + + writeWorkspaceProject(writer, projectName, dspFile.getName(), projectDeps); + + writer.write("############################################"); + writer.write("###################################\r\n\r\n"); - writer.write("########################################"); - writer.write("#######################################\r\n\r\n"); - writer.close(); + + writer.write("Global:\r\n\r\nPackage=<5>\r\n{{{\r\n}}}"); + writer.write("\r\n\r\nPackage=<3>\r\n{{{\r\n}}}\r\n\r\n"); + + writer.write("########################################"); + writer.write("#######################################\r\n\r\n"); } @@ -344,7 +409,7 @@ public final class DevStudioProjectWriter && !relativePath.startsWith("\\")) { relativePath = ".\\" + relativePath; } - writer.write(relativePath); + writer.write(CUtil.toWindowsPath(relativePath)); writer.write("\r\n# End Source File\r\n"); } @@ -368,14 +433,12 @@ public final class DevStudioProjectWriter * Writes "This is not a makefile" warning. * @param writer Writer writer * @param projectName String project name - * @param configName String configuration name * @param targtype String target type * @throws IOException if error writing project */ private void writeMessage(final Writer writer, final String projectName, - final String configName, final String targtype) throws IOException { writer.write( "!MESSAGE This is not a valid makefile. "); @@ -395,16 +458,14 @@ public final class DevStudioProjectWriter writer.write("!MESSAGE NMAKE /f \""); writer.write(projectName); writer.write(".mak\" CFG=\""); - writer.write(configName); - writer.write("\"\r\n"); + writer.write(projectName); + writer.write(" - Win32 Debug\"\r\n"); writer.write("!MESSAGE \r\n"); writer.write("!MESSAGE Possible choices for configuration are:\r\n"); writer.write("!MESSAGE \r\n"); - writer.write("!MESSAGE \""); - writer.write(configName); - writer.write("\" (based on \""); - writer.write(targtype); - writer.write("\")\r\n"); + String pattern = "!MESSAGE \"{0} - Win32 {1}\" (based on \"{2}\")\r\n"; + writer.write(MessageFormat.format(pattern, new Object[] { projectName, "Release", targtype })); + writer.write(MessageFormat.format(pattern, new Object[] { projectName, "Debug", targtype })); writer.write("!MESSAGE \r\n"); writer.write("\r\n"); @@ -421,7 +482,7 @@ public final class DevStudioProjectWriter // // find first target with an DevStudio C compilation // - CommandLineCompilerConfiguration compilerConfig = null; + CommandLineCompilerConfiguration compilerConfig; // // get the first target and assume that it is representative // @@ -429,7 +490,6 @@ public final class DevStudioProjectWriter while (targetIter.hasNext()) { TargetInfo targetInfo = (TargetInfo) targetIter.next(); ProcessorConfiguration config = targetInfo.getConfiguration(); - String identifier = config.getIdentifier(); // // for the first cl compiler // @@ -446,11 +506,13 @@ public final class DevStudioProjectWriter /** * Writes compiler options. * @param writer Writer writer + * @param isDebug true if debug. * @param baseDir String base directory * @param compilerConfig compiler configuration * @throws IOException if error on writing project */ private void writeCompileOptions(final Writer writer, + final boolean isDebug, final String baseDir, final CommandLineCompilerConfiguration compilerConfig) throws IOException { @@ -462,9 +524,34 @@ public final class DevStudioProjectWriter for (int i = 0; i < includePath.length; i++) { options.append(" /I \""); String relPath = CUtil.getRelativePath(baseDir, includePath[i]); - options.append(relPath); + options.append(CUtil.toWindowsPath(relPath)); options.append('"'); } + Hashtable optionMap = new Hashtable(); + + if (isDebug) { + // + // release options that should be mapped to debug counterparts + // + optionMap.put("/MT", "/MTd"); + optionMap.put("/ML", "/MLd"); + optionMap.put("/MD", "/MDd"); + optionMap.put("/O2", "/Od"); + optionMap.put("/O3", "/Od"); + } else { + // + // debug options that should be mapped to release counterparts + // + optionMap.put("/MTD", "/MT"); + optionMap.put("/MLD", "/ML"); + optionMap.put("/MDD", "/MD"); + optionMap.put("/GM", ""); + optionMap.put("/ZI", ""); + optionMap.put("/OD", "/O2"); + optionMap.put("/GZ", ""); + } + + String[] preArgs = compilerConfig.getPreArguments(); for (int i = 0; i < preArgs.length; i++) { @@ -476,15 +563,30 @@ public final class DevStudioProjectWriter options.append(body); baseOptions.append(body); } else { - options.append('"'); - options.append(body); - options.append('"'); + StringBuffer buf = new StringBuffer("\""); + if ("NDEBUG".equals(body) || "_DEBUG".equals(body)) { + if (isDebug) { + buf.append("_DEBUG"); + } else { + buf.append("NDEBUG"); + } + } else { + buf.append(body); + } + buf.append("\""); + options.append(buf); + baseOptions.append(buf); } } else if (!preArgs[i].startsWith("/I")) { + String option = preArgs[i]; + String key = option.toUpperCase(Locale.US); + if (optionMap.containsKey(key)) { + option = optionMap.get(key).toString(); + } options.append(" "); - options.append(preArgs[i]); + options.append(option); baseOptions.append(" "); - baseOptions.append(preArgs[i]); + baseOptions.append(option); } } baseOptions.append("\r\n"); @@ -494,15 +596,22 @@ public final class DevStudioProjectWriter } + + + + /** * Writes link options. * @param writer Writer writer * @param basePath String base path + * @param dependencies project dependencies, used to suppress explicit linking. * @param linkTarget TargetInfo link target * @param targets Hashtable all targets * @throws IOException if unable to write to project file */ private void writeLinkOptions(final Writer writer, + final boolean isDebug, + final List dependencies, final String basePath, final TargetInfo linkTarget, final Hashtable targets) throws IOException { @@ -523,26 +632,51 @@ public final class DevStudioProjectWriter // if file was not compiled or otherwise generated // if (targets.get(linkSources[i].getName()) == null) { - String relPath = CUtil.getRelativePath(basePath, linkSources[i]); // - // if path has an embedded space then - // must quote - if (relPath.indexOf(' ') > 0) { - options.append(" \""); - options.append(relPath); - options.append("\""); - } else { - options.append(' '); - options.append(relPath); + // if source appears to be a system library or object file + // just output the name of the file (advapi.lib for example) + // otherwise construct a relative path. + // + String relPath = linkSources[i].getName(); + // + // check if file comes from a project dependency + // if it does it should not be explicitly linked + boolean fromDependency = false; + if (relPath.indexOf(".") > 0) { + String baseName = relPath.substring(0, relPath.indexOf(".")); + for(Iterator iter = dependencies.iterator(); iter.hasNext(); ) { + DependencyDef depend = (DependencyDef) iter.next(); + if (baseName.compareToIgnoreCase(depend.getName()) == 0) { + fromDependency = true; + } + } } + if (!fromDependency) { + if (!CUtil.isSystemPath(linkSources[i])) { + relPath = CUtil.getRelativePath(basePath, linkSources[i]); + } + // + // if path has an embedded space then + // must quote + if (relPath.indexOf(' ') > 0) { + options.append(" \""); + options.append(CUtil.toWindowsPath(relPath)); + options.append("\""); + } else { + options.append(' '); + options.append(CUtil.toWindowsPath(relPath)); + } + } } } String[] preArgs = linkConfig.getPreArguments(); for (int i = 0; i < preArgs.length; i++) { - options.append(' '); - options.append(preArgs[i]); - baseOptions.append(' '); - baseOptions.append(preArgs[i]); + if (isDebug || !preArgs[i].equals("/DEBUG")) { + options.append(' '); + options.append(preArgs[i]); + baseOptions.append(' '); + baseOptions.append(preArgs[i]); + } } String[] endArgs = linkConfig.getEndArguments(); for (int i = 0; i < endArgs.length; i++) { @@ -557,4 +691,20 @@ public final class DevStudioProjectWriter writer.write(baseOptions.toString()); writer.write(options.toString()); } + + private static void writeComments(final Writer writer, + final List comments) throws IOException { + for(Iterator iter = comments.iterator();iter.hasNext();) { + String comment = ((CommentDef) iter.next()).getText(); + if (comment != null) { + int start = 0; + for(int end = comment.indexOf('\n'); + end != -1; + end = comment.indexOf('\n', start)) { + writer.write("#" + comment.substring(start, end) + "\r\n"); + start = end + 1; + } + } + } + } } diff --git a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/VisualStudioNETProjectWriter.java b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/VisualStudioNETProjectWriter.java index 898503e..f554e09 100644 --- a/src/main/java/net/sf/antcontrib/cpptasks/devstudio/VisualStudioNETProjectWriter.java +++ b/src/main/java/net/sf/antcontrib/cpptasks/devstudio/VisualStudioNETProjectWriter.java @@ -1,6 +1,6 @@ /* * - * Copyright 2004-2006 The Ant-Contrib project + * Copyright 2004-2008 The Ant-Contrib project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,10 +23,11 @@ import net.sf.antcontrib.cpptasks.compiler.CommandLineCompilerConfiguration; import net.sf.antcontrib.cpptasks.compiler.ProcessorConfiguration; import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; import net.sf.antcontrib.cpptasks.ide.ProjectDef; +import net.sf.antcontrib.cpptasks.ide.CommentDef; import net.sf.antcontrib.cpptasks.ide.ProjectWriter; +import net.sf.antcontrib.cpptasks.ide.DependencyDef; import org.apache.tools.ant.BuildException; import org.apache.xml.serialize.OutputFormat; -import org.apache.xml.serialize.Serializer; import org.apache.xml.serialize.XMLSerializer; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; @@ -88,18 +89,8 @@ public final class VisualStudioNETProjectWriter this.trueLiteral = trueArg; this.falseLiteral = falseArg; } + - /** - * Get configuration name. - * @param task cc task, may not be null. - * @return configuration name. - */ - private String getConfigurationName(final CCTask task) { - if (task.getDebug()) { - return "Debug|Win32"; - } - return "Release|Win32"; - } /** * Gets the configuration type. @@ -118,30 +109,6 @@ public final class VisualStudioNETProjectWriter return targtype; } - /** - * Get output directory. - * @param basePath path to parent of project file. - * @param task cc task, may not be null. - * @return output directory relative path. - */ - private String getOutputDirectory(final String basePath, - final CCTask task) { - File outFile = task.getOutfile(); - File buildDir = outFile.getParentFile(); - return CUtil.getRelativePath(basePath, buildDir); - } - - /** - * Get object file directory. - * @param basePath path to parent of project file. - * @param task cc task, may not be null. - * @return object file directory relative path. - */ - private String getIntermediateDirectory(final String basePath, - final CCTask task) { - File objDir = task.getObjdir(); - return CUtil.getRelativePath(basePath, objDir); - } /** @@ -167,23 +134,27 @@ public final class VisualStudioNETProjectWriter /** * Write the start tag of the Configuration element. * @param content serialization content handler. - * @param basePath path of directory containing project file. + * @param isDebug if true, write a debug configuration. * @param task cc task. * @param compilerConfig compiler configuration. * @throws SAXException thrown if serialization error. */ private void writeConfigurationStartTag(final ContentHandler content, - final String basePath, + final boolean isDebug, final CCTask task, final CommandLineCompilerConfiguration compilerConfig) throws SAXException { AttributesImpl attributes = new AttributesImpl(); - addAttribute(attributes, "Name", - getConfigurationName(task)); - addAttribute(attributes, "OutputDirectory", - getOutputDirectory(basePath, task)); - addAttribute(attributes, "IntermediateDirectory", - getIntermediateDirectory(basePath, task)); + if (isDebug) { + addAttribute(attributes, "Name", "Debug|Win32"); + addAttribute(attributes, "OutputDirectory", "Debug"); + addAttribute(attributes, "IntermediateDirectory", "Debug"); + } else { + addAttribute(attributes, "Name", "Release|Win32"); + addAttribute(attributes, "OutputDirectory", "Release"); + addAttribute(attributes, "IntermediateDirectory", "Release"); + + } addAttribute(attributes, "ConfigurationType", getConfigurationType(task)); addAttribute(attributes, "CharacterSet", @@ -221,19 +192,21 @@ public final class VisualStudioNETProjectWriter /** * Get value of AdditionalIncludeDirectories property. * @param compilerConfig compiler configuration. + * @param baseDir base for relative paths. * @return value of AdditionalIncludeDirectories property. */ private String getAdditionalIncludeDirectories( + final String baseDir, final CommandLineCompilerConfiguration compilerConfig) { + File[] includePath = compilerConfig.getIncludePath(); StringBuffer includeDirs = new StringBuffer(); - String[] args = compilerConfig.getPreArguments(); - for (int i = 0; i < args.length; i++) { - if (args[i].startsWith("/I")) { - includeDirs.append(args[i].substring(2)); - includeDirs.append(';'); - } + for (int i = 0; i < includePath.length; i++) { + String relPath = CUtil.getRelativePath(baseDir, includePath[i]); + includeDirs.append(CUtil.toWindowsPath(relPath)); + includeDirs.append(';'); } + if (includeDirs.length() > 0) { includeDirs.setLength(includeDirs.length() - 1); } @@ -243,15 +216,27 @@ public final class VisualStudioNETProjectWriter /** * Get value of PreprocessorDefinitions property. * @param compilerConfig compiler configuration. + * @param isDebug true if generating debug configuration. * @return value of PreprocessorDefinitions property. */ private String getPreprocessorDefinitions( - final CommandLineCompilerConfiguration compilerConfig) { + final CommandLineCompilerConfiguration compilerConfig, + final boolean isDebug) { StringBuffer defines = new StringBuffer(); String[] args = compilerConfig.getPreArguments(); for (int i = 0; i < args.length; i++) { if (args[i].startsWith("/D")) { - defines.append(args[i].substring(2)); + String macro = args[i].substring(2); + if (isDebug) { + if (macro.equals("NDEBUG")) { + macro = "_DEBUG"; + } + } else { + if (macro.equals("_DEBUG")) { + macro = "NDEBUG"; + } + } + defines.append(macro); defines.append(";"); } } @@ -265,24 +250,27 @@ public final class VisualStudioNETProjectWriter /** * Get value of RuntimeLibrary property. * @param compilerConfig compiler configuration. + * @param isDebug true if generating debug configuration. * @return value of RuntimeLibrary property. */ private String getRuntimeLibrary( - final CommandLineCompilerConfiguration compilerConfig) { + final CommandLineCompilerConfiguration compilerConfig, + final boolean isDebug) { String rtl = null; String[] args = compilerConfig.getPreArguments(); for (int i = 0; i < args.length; i++) { - if ("/MT".equals(args[i])) { - rtl = "0"; - } - if ("/MTd".equals(args[i])) { - rtl = "1"; - } - if ("/MD".equals(args[i])) { - rtl = "2"; - } - if ("/MDd".equals(args[i])) { - rtl = "3"; + if (args[i].startsWith("/MT")) { + if (isDebug) { + rtl = "1"; + } else { + rtl = "0"; + } + } else if (args[i].startsWith("/MD")) { + if (isDebug) { + rtl = "3"; + } else { + rtl = "2"; + } } } return rtl; @@ -326,15 +314,6 @@ public final class VisualStudioNETProjectWriter } - /** - * Get value of MinimalRebuild property. - * @param compilerConfig compiler configuration. - * @return value of MinimalRebuild property. - */ - private String getMinimalRebuild( - final CommandLineCompilerConfiguration compilerConfig) { - return trueLiteral; - } /** * Get value of BasicRuntimeChecks property. @@ -415,6 +394,9 @@ public final class VisualStudioNETProjectWriter if ("/Z7".equals(args[i])) { format = "1"; } + if ("/Zd".equals(args[i])) { + format = "2"; + } if ("/Zi".equals(args[i])) { format = "3"; } @@ -428,26 +410,41 @@ public final class VisualStudioNETProjectWriter /** * write the Compiler element. * @param content serialization content handler. + * @param isDebug true if generating debug configuration. + * @param basePath base for relative file paths. * @param compilerConfig compiler configuration. * @throws SAXException thrown if error during serialization. */ private void writeCompilerElement(final ContentHandler content, + final boolean isDebug, + final String basePath, final CommandLineCompilerConfiguration compilerConfig) throws SAXException { AttributesImpl attributes = new AttributesImpl(); addAttribute(attributes, "Name", "VCCLCompilerTool"); - addAttribute(attributes, "Optimization", - getOptimization(compilerConfig)); + String optimization = getOptimization(compilerConfig); + String debugFormat = getDebugInformationFormat(compilerConfig); + if(isDebug) { + optimization = "0"; + if ("0".equals(debugFormat)) { + debugFormat = "4"; + } + } else { + if ("0".equals(optimization)) { + optimization = "2"; + } + debugFormat = "0"; + } + addAttribute(attributes, "Optimization", optimization); addAttribute(attributes, "AdditionalIncludeDirectories", - getAdditionalIncludeDirectories(compilerConfig)); + getAdditionalIncludeDirectories(basePath, compilerConfig)); addAttribute(attributes, "PreprocessorDefinitions", - getPreprocessorDefinitions(compilerConfig)); - addAttribute(attributes, "MinimalRebuild", - getMinimalRebuild(compilerConfig)); + getPreprocessorDefinitions(compilerConfig, isDebug)); + addAttribute(attributes, "MinimalRebuild", trueLiteral); addAttribute(attributes, "BasicRuntimeChecks", getBasicRuntimeChecks(compilerConfig)); addAttribute(attributes, "RuntimeLibrary", - getRuntimeLibrary(compilerConfig)); + getRuntimeLibrary(compilerConfig, isDebug)); addAttribute(attributes, "UsePrecompiledHeader", getUsePrecompiledHeader(compilerConfig)); addAttribute(attributes, "PrecompiledHeaderFile", @@ -457,7 +454,7 @@ public final class VisualStudioNETProjectWriter addAttribute(attributes, "Detect64BitPortabilityProblems", getDetect64BitPortabilityProblems(compilerConfig)); addAttribute(attributes, "DebugInformationFormat", - getDebugInformationFormat(compilerConfig)); + debugFormat); content.startElement(null, "Tool", "Tool", attributes); content.endElement(null, "Tool", "Tool"); @@ -484,22 +481,6 @@ public final class VisualStudioNETProjectWriter return incremental; } - /** - * Get value of GenerateDebugInformation property. - * @param linkerConfig linker configuration. - * @return value of GenerateDebugInformation property - */ - private String getGenerateDebugInformation( - final CommandLineLinkerConfiguration linkerConfig) { - String debug = falseLiteral; - String[] args = linkerConfig.getPreArguments(); - for (int i = 0; i < args.length; i++) { - if ("/DEBUG".equals(args[i])) { - debug = trueLiteral; - } - } - return debug; - } /** * Get value of Subsystem property. @@ -544,11 +525,13 @@ public final class VisualStudioNETProjectWriter /** * Get value of AdditionalDependencies property. * @param linkTarget link target. + * @param projectDependencies dependencies declared in project. * @param targets all targets. * @param basePath path to directory containing project file. * @return value of AdditionalDependencies property. */ private String getAdditionalDependencies(final TargetInfo linkTarget, + final List projectDependencies, final Map targets, final String basePath) { String dependencies = null; @@ -559,19 +542,43 @@ public final class VisualStudioNETProjectWriter // if file was not compiled or otherwise generated // if (targets.get(linkSources[i].getName()) == null) { - String relPath = CUtil.getRelativePath(basePath, linkSources[i]); // - // if path has an embedded space then - // must quote - if (relPath.indexOf(' ') > 0) { - buf.append('\"'); - buf.append(relPath); - buf.append('\"'); - } else { - buf.append(relPath); - } - buf.append(';'); - } + // if source appears to be a system library or object file + // just output the name of the file (advapi.lib for example) + // otherwise construct a relative path. + // + String relPath = linkSources[i].getName(); + // + // check if file comes from a project dependency + // if it does it should not be explicitly linked + boolean fromDependency = false; + if (relPath.indexOf(".") > 0) { + String baseName = relPath.substring(0, relPath.indexOf(".")); + for(Iterator iter = projectDependencies.iterator(); iter.hasNext(); ) { + DependencyDef depend = (DependencyDef) iter.next(); + if (baseName.compareToIgnoreCase(depend.getName()) == 0) { + fromDependency = true; + } + } + } + + if (!fromDependency) { + if (!CUtil.isSystemPath(linkSources[i])) { + relPath = CUtil.getRelativePath(basePath, linkSources[i]); + } + // + // if path has an embedded space then + // must quote + if (relPath.indexOf(' ') > 0) { + buf.append('\"'); + buf.append(CUtil.toWindowsPath(relPath)); + buf.append('\"'); + } else { + buf.append(relPath); + } + buf.append(' '); + } + } } if (buf.length() > 0) { buf.setLength(buf.length() - 1); @@ -584,12 +591,16 @@ public final class VisualStudioNETProjectWriter /** * Write Tool element for linker. * @param content serialization content handler. + * @param isDebug true if generating debug configuration. + * @param dependencies project dependencies. * @param basePath path to directory containing project file. * @param linkTarget link target. * @param targets all targets. * @throws SAXException thrown if error during serialization. */ private void writeLinkerElement(final ContentHandler content, + final boolean isDebug, + final List dependencies, final String basePath, final TargetInfo linkTarget, final Map targets) throws SAXException { @@ -603,8 +614,11 @@ public final class VisualStudioNETProjectWriter if (linkerConfig.getLinker() instanceof DevStudioCompatibleLinker) { addAttribute(attributes, "LinkIncremental", getLinkIncremental(linkerConfig)); - addAttribute(attributes, "GenerateDebugInformation", - getGenerateDebugInformation(linkerConfig)); + if (isDebug) { + addAttribute(attributes, "GenerateDebugInformation", trueLiteral); + } else { + addAttribute(attributes, "GenerateDebugInformation", falseLiteral); + } addAttribute(attributes, "SubSystem", getSubsystem(linkerConfig)); addAttribute(attributes, "TargetMachine", @@ -612,7 +626,7 @@ public final class VisualStudioNETProjectWriter } } addAttribute(attributes, "AdditionalDependencies", - getAdditionalDependencies(linkTarget, targets, basePath)); + getAdditionalDependencies(linkTarget, dependencies, targets, basePath)); content.startElement(null, "Tool", "Tool", attributes); content.endElement(null, "Tool", "Tool"); } @@ -665,10 +679,16 @@ public final class VisualStudioNETProjectWriter OutputStream outStream = new FileOutputStream(fileName + ".vcproj"); OutputFormat format = new OutputFormat("xml", "UTF-8", true); - Serializer serializer = new XMLSerializer(outStream, format); + XMLSerializer serializer = new XMLSerializer(outStream, format); ContentHandler content = serializer.asContentHandler(); String basePath = fileName.getParentFile().getAbsolutePath(); content.startDocument(); + + for(Iterator iter = projectDef.getComments().iterator(); iter.hasNext(); ) { + String comment = ((CommentDef) iter.next()).getText(); + serializer.comment(comment); + } + AttributesImpl emptyAttrs = new AttributesImpl(); AttributesImpl attributes = new AttributesImpl(); @@ -687,13 +707,22 @@ public final class VisualStudioNETProjectWriter content.startElement(null, "Configurations", "Configurations", emptyAttrs); - writeConfigurationStartTag(content, basePath, task, compilerConfig); - - writeCompilerElement(content, compilerConfig); - - writeLinkerElement(content, basePath, linkTarget, targets); + // + // write debug configuration + // + writeConfigurationStartTag(content, true, task, compilerConfig); + writeCompilerElement(content, true, basePath, compilerConfig); + writeLinkerElement(content, true, projectDef.getDependencies(), basePath, linkTarget, targets); + content.endElement(null, "Configuration", "Configuration"); + // + // write release configuration + // + writeConfigurationStartTag(content, false, task, compilerConfig); + writeCompilerElement(content, false, basePath, compilerConfig); + writeLinkerElement(content, false, projectDef.getDependencies(), basePath, linkTarget, targets); content.endElement(null, "Configuration", "Configuration"); + content.endElement(null, "Configurations", "Configurations"); content.startElement(null, "References", "References", emptyAttrs); content.endElement(null, "References", "References"); |