diff options
Diffstat (limited to 'Source/cmLocalVisualStudio7Generator.cxx')
-rw-r--r-- | Source/cmLocalVisualStudio7Generator.cxx | 2392 |
1 files changed, 2392 insertions, 0 deletions
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx new file mode 100644 index 0000000..a4bce8a --- /dev/null +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -0,0 +1,2392 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmGlobalVisualStudio7Generator.h" +#include "cmLocalVisualStudio7Generator.h" +#include "cmXMLParser.h" +#include <cm_expat.h> +#include "cmMakefile.h" +#include "cmSystemTools.h" +#include "cmSourceFile.h" +#include "cmGeneratorTarget.h" +#include "cmCustomCommandGenerator.h" +#include "cmake.h" + +#include "cmComputeLinkInformation.h" +#include "cmGeneratedFileStream.h" + +#include <ctype.h> // for isspace + +static bool cmLVS6G_IsFAT(const char* dir); + +class cmLocalVisualStudio7GeneratorInternals +{ +public: + cmLocalVisualStudio7GeneratorInternals(cmLocalVisualStudio7Generator* e): + LocalGenerator(e) {} + typedef cmComputeLinkInformation::ItemVector ItemVector; + void OutputLibraries(std::ostream& fout, ItemVector const& libs); + void OutputObjects(std::ostream& fout, cmTarget* t, const char* isep = 0); +private: + cmLocalVisualStudio7Generator* LocalGenerator; +}; + +extern cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[]; + +static void cmConvertToWindowsSlash(std::string& s) +{ + std::string::size_type pos = 0; + while((pos = s.find('/', pos)) != std::string::npos) + { + s[pos] = '\\'; + pos++; + } +} + +//---------------------------------------------------------------------------- +cmLocalVisualStudio7Generator +::cmLocalVisualStudio7Generator(cmGlobalGenerator* gg, cmMakefile* mf): + cmLocalVisualStudioGenerator(gg, mf) +{ + this->Internal = new cmLocalVisualStudio7GeneratorInternals(this); +} + +cmLocalVisualStudio7Generator::~cmLocalVisualStudio7Generator() +{ + delete this->Internal; +} + +void cmLocalVisualStudio7Generator::AddHelperCommands() +{ + // Now create GUIDs for targets + cmTargets &tgts = this->Makefile->GetTargets(); + + for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++) + { + if(l->second.GetType() == cmTarget::INTERFACE_LIBRARY) + { + continue; + } + const char* path = l->second.GetProperty("EXTERNAL_MSPROJECT"); + if(path) + { + this->ReadAndStoreExternalGUID( + l->second.GetName().c_str(), path); + } + } + + + this->FixGlobalTargets(); +} + +void cmLocalVisualStudio7Generator::Generate() +{ + this->WriteProjectFiles(); + this->WriteStampFiles(); +} + +void cmLocalVisualStudio7Generator::AddCMakeListsRules() +{ + cmTargets &tgts = this->Makefile->GetTargets(); + // Create the regeneration custom rule. + if(!this->Makefile->IsOn("CMAKE_SUPPRESS_REGENERATION")) + { + // Create a rule to regenerate the build system when the target + // specification source changes. + if(cmSourceFile* sf = this->CreateVCProjBuildRule()) + { + // Add the rule to targets that need it. + for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l) + { + if (l->second.GetType() == cmTarget::GLOBAL_TARGET) + { + continue; + } + if(l->first != CMAKE_CHECK_BUILD_SYSTEM_TARGET) + { + l->second.AddSource(sf->GetFullPath()); + } + } + } + } +} + +void cmLocalVisualStudio7Generator::FixGlobalTargets() +{ + // Visual Studio .NET 2003 Service Pack 1 will not run post-build + // commands for targets in which no sources are built. Add dummy + // rules to force these targets to build. + cmTargets &tgts = this->Makefile->GetTargets(); + for(cmTargets::iterator l = tgts.begin(); + l != tgts.end(); l++) + { + cmTarget& tgt = l->second; + if(tgt.GetType() == cmTarget::GLOBAL_TARGET) + { + std::vector<std::string> no_depends; + cmCustomCommandLine force_command; + force_command.push_back("cd"); + force_command.push_back("."); + cmCustomCommandLines force_commands; + force_commands.push_back(force_command); + std::string no_main_dependency = ""; + std::string force = this->Makefile->GetCurrentBinaryDirectory(); + force += cmake::GetCMakeFilesDirectory(); + force += "/"; + force += tgt.GetName(); + force += "_force"; + if(cmSourceFile* file = + this->Makefile->AddCustomCommandToOutput( + force.c_str(), no_depends, no_main_dependency, + force_commands, " ", 0, true)) + { + tgt.AddSource(file->GetFullPath()); + } + } + } +} + +// TODO +// for CommandLine= need to repleace quotes with " +// write out configurations +void cmLocalVisualStudio7Generator::WriteProjectFiles() +{ + // If not an in source build, then create the output directory + if(strcmp(this->Makefile->GetCurrentBinaryDirectory(), + this->Makefile->GetHomeDirectory()) != 0) + { + if(!cmSystemTools::MakeDirectory + (this->Makefile->GetCurrentBinaryDirectory())) + { + cmSystemTools::Error("Error creating directory ", + this->Makefile->GetCurrentBinaryDirectory()); + } + } + + // Get the set of targets in this directory. + cmTargets &tgts = this->Makefile->GetTargets(); + + // Create the project file for each target. + for(cmTargets::iterator l = tgts.begin(); + l != tgts.end(); l++) + { + if(l->second.GetType() == cmTarget::INTERFACE_LIBRARY) + { + continue; + } + // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace + // so don't build a projectfile for it + if(!l->second.GetProperty("EXTERNAL_MSPROJECT")) + { + this->CreateSingleVCProj(l->first.c_str(),l->second); + } + } +} + +//---------------------------------------------------------------------------- +void cmLocalVisualStudio7Generator::WriteStampFiles() +{ + // Touch a timestamp file used to determine when the project file is + // out of date. + std::string stampName = this->Makefile->GetCurrentBinaryDirectory(); + stampName += cmake::GetCMakeFilesDirectory(); + cmSystemTools::MakeDirectory(stampName.c_str()); + stampName += "/"; + stampName += "generate.stamp"; + cmsys::ofstream stamp(stampName.c_str()); + stamp << "# CMake generation timestamp file for this directory.\n"; + + // Create a helper file so CMake can determine when it is run + // through the rule created by CreateVCProjBuildRule whether it + // really needs to regenerate the project. This file lists its own + // dependencies. If any file listed in it is newer than itself then + // CMake must rerun. Otherwise the project files are up to date and + // the stamp file can just be touched. + std::string depName = stampName; + depName += ".depend"; + cmsys::ofstream depFile(depName.c_str()); + depFile << "# CMake generation dependency list for this directory.\n"; + std::vector<std::string> const& listFiles = this->Makefile->GetListFiles(); + for(std::vector<std::string>::const_iterator lf = listFiles.begin(); + lf != listFiles.end(); ++lf) + { + depFile << *lf << std::endl; + } +} + +//---------------------------------------------------------------------------- +void cmLocalVisualStudio7Generator +::CreateSingleVCProj(const std::string& lname, cmTarget &target) +{ + cmGlobalVisualStudioGenerator* gg + = static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator); + this->FortranProject = gg->TargetIsFortranOnly(target); + this->WindowsCEProject = gg->TargetsWindowsCE(); + + // Intel Fortran for VS10 uses VS9 format ".vfproj" files. + cmGlobalVisualStudioGenerator::VSVersion realVersion = gg->GetVersion(); + if(this->FortranProject + && gg->GetVersion() >= cmGlobalVisualStudioGenerator::VS10) + { + gg->SetVersion(cmGlobalVisualStudioGenerator::VS9); + } + + // add to the list of projects + target.SetProperty("GENERATOR_FILE_NAME",lname.c_str()); + // create the dsp.cmake file + std::string fname; + fname = this->Makefile->GetCurrentBinaryDirectory(); + fname += "/"; + fname += lname; + if(this->FortranProject) + { + fname += ".vfproj"; + } + else + { + fname += ".vcproj"; + } + + // Generate the project file and replace it atomically with + // copy-if-different. We use a separate timestamp so that the IDE + // does not reload project files unnecessarily. + cmGeneratedFileStream fout(fname.c_str()); + fout.SetCopyIfDifferent(true); + this->WriteVCProjFile(fout,lname,target); + if (fout.Close()) + { + this->GlobalGenerator->FileReplacedDuringGenerate(fname); + } + + gg->SetVersion(realVersion); +} + +//---------------------------------------------------------------------------- +cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() +{ + std::string stampName = this->Makefile->GetCurrentBinaryDirectory(); + stampName += "/"; + stampName += cmake::GetCMakeFilesDirectoryPostSlash(); + stampName += "generate.stamp"; + cmCustomCommandLine commandLine; + commandLine.push_back(cmSystemTools::GetCMakeCommand()); + std::string makefileIn = this->Makefile->GetCurrentSourceDirectory(); + makefileIn += "/"; + makefileIn += "CMakeLists.txt"; + makefileIn = cmSystemTools::CollapseFullPath(makefileIn.c_str()); + if(!cmSystemTools::FileExists(makefileIn.c_str())) + { + return 0; + } + std::string comment = "Building Custom Rule "; + comment += makefileIn; + std::string args; + args = "-H"; + args += this->Makefile->GetHomeDirectory(); + commandLine.push_back(args); + args = "-B"; + args += this->Makefile->GetHomeOutputDirectory(); + commandLine.push_back(args); + commandLine.push_back("--check-stamp-file"); + std::string stampFilename = this->Convert(stampName.c_str(), FULL, + SHELL); + commandLine.push_back(stampFilename.c_str()); + + std::vector<std::string> const& listFiles = this->Makefile->GetListFiles(); + + cmCustomCommandLines commandLines; + commandLines.push_back(commandLine); + const char* no_working_directory = 0; + std::string fullpathStampName = this->Convert(stampName.c_str(), FULL, + UNCHANGED); + this->Makefile->AddCustomCommandToOutput(fullpathStampName.c_str(), + listFiles, makefileIn.c_str(), + commandLines, comment.c_str(), + no_working_directory, true); + if(cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str())) + { + return file; + } + else + { + cmSystemTools::Error("Error adding rule for ", makefileIn.c_str()); + return 0; + } +} + +void cmLocalVisualStudio7Generator::WriteConfigurations( + std::ostream& fout, std::vector<std::string> const& configs, + const std::string& libName, cmTarget &target + ) +{ + fout << "\t<Configurations>\n"; + for (std::vector<std::string>::const_iterator i = configs.begin(); + i != configs.end(); ++i) + { + this->WriteConfiguration(fout, i->c_str(), libName, target); + } + fout << "\t</Configurations>\n"; +} +cmVS7FlagTable cmLocalVisualStudio7GeneratorFortranFlagTable[] = +{ + {"Preprocess", "fpp", "Run Preprocessor on files", "preprocessYes", 0}, + {"SuppressStartupBanner", "nologo", "SuppressStartupBanner", "true", 0}, + {"SourceFileFormat", "fixed", "Use Fixed Format", "fileFormatFixed", 0}, + {"SourceFileFormat", "free", "Use Free Format", "fileFormatFree", 0}, + {"DebugInformationFormat", "Zi", "full debug", "debugEnabled", 0}, + {"DebugInformationFormat", "debug:full", "full debug", "debugEnabled", 0}, + {"DebugInformationFormat", "Z7", "c7 compat", "debugOldStyleInfo", 0}, + {"DebugInformationFormat", "Zd", "line numbers", "debugLineInfoOnly", 0}, + {"Optimization", "Od", "disable optimization", "optimizeDisabled", 0}, + {"Optimization", "O1", "min space", "optimizeMinSpace", 0}, + {"Optimization", "O3", "full optimize", "optimizeFull", 0}, + {"GlobalOptimizations", "Og", "global optimize", "true", 0}, + {"InlineFunctionExpansion", "Ob0", "", "expandDisable", 0}, + {"InlineFunctionExpansion", "Ob1", "", "expandOnlyInline", 0}, + {"FavorSizeOrSpeed", "Os", "", "favorSize", 0}, + {"OmitFramePointers", "Oy-", "", "false", 0}, + {"OptimizeForProcessor", "GB", "", "procOptimizeBlended", 0}, + {"OptimizeForProcessor", "G5", "", "procOptimizePentium", 0}, + {"OptimizeForProcessor", "G6", "", "procOptimizePentiumProThruIII", 0}, + {"UseProcessorExtensions", "QzxK", "", "codeForStreamingSIMD", 0}, + {"OptimizeForProcessor", "QaxN", "", "codeForPentium4", 0}, + {"OptimizeForProcessor", "QaxB", "", "codeForPentiumM", 0}, + {"OptimizeForProcessor", "QaxP", "", "codeForCodeNamedPrescott", 0}, + {"OptimizeForProcessor", "QaxT", "", "codeForCore2Duo", 0}, + {"OptimizeForProcessor", "QxK", "", "codeExclusivelyStreamingSIMD", 0}, + {"OptimizeForProcessor", "QxN", "", "codeExclusivelyPentium4", 0}, + {"OptimizeForProcessor", "QxB", "", "codeExclusivelyPentiumM", 0}, + {"OptimizeForProcessor", "QxP", "", "codeExclusivelyCodeNamedPrescott", 0}, + {"OptimizeForProcessor", "QxT", "", "codeExclusivelyCore2Duo", 0}, + {"OptimizeForProcessor", "QxO", "", "codeExclusivelyCore2StreamingSIMD", 0}, + {"OptimizeForProcessor", "QxS", "", "codeExclusivelyCore2StreamingSIMD4", 0}, + {"OpenMP", "Qopenmp", "", "OpenMPParallelCode", 0}, + {"OpenMP", "Qopenmp-stubs", "", "OpenMPSequentialCode", 0}, + {"Traceback", "traceback", "", "true", 0}, + {"Traceback", "notraceback", "", "false", 0}, + {"FloatingPointExceptionHandling", "fpe:0", "", "fpe0", 0}, + {"FloatingPointExceptionHandling", "fpe:1", "", "fpe1", 0}, + {"FloatingPointExceptionHandling", "fpe:3", "", "fpe3", 0}, + + {"ModulePath", "module:", "", "", + cmVS7FlagTable::UserValueRequired}, + {"LoopUnrolling", "Qunroll:", "", "", + cmVS7FlagTable::UserValueRequired}, + {"AutoParallelThreshold", "Qpar-threshold:", "", "", + cmVS7FlagTable::UserValueRequired}, + {"HeapArrays", "heap-arrays:", "", "", + cmVS7FlagTable::UserValueRequired}, + {"ObjectText", "bintext:", "", "", + cmVS7FlagTable::UserValueRequired}, + {"Parallelization", "Qparallel", "", "true", 0}, + {"PrefetchInsertion", "Qprefetch-", "", "false", 0}, + {"BufferedIO", "assume:buffered_io", "", "true", 0}, + {"CallingConvention", "iface:stdcall", "", "callConventionStdCall", 0}, + {"CallingConvention", "iface:cref", "", "callConventionCRef", 0}, + {"CallingConvention", "iface:stdref", "", "callConventionStdRef", 0}, + {"CallingConvention", "iface:stdcall", "", "callConventionStdCall", 0}, + {"CallingConvention", "iface:cvf", "", "callConventionCVF", 0}, + {"EnableRecursion", "recursive", "", "true", 0}, + {"ReentrantCode", "reentrancy", "", "true", 0}, + // done up to Language + {0,0,0,0,0} +}; +// fill the table here currently the comment field is not used for +// anything other than documentation NOTE: Make sure the longer +// commandFlag comes FIRST! +cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[] = +{ + // option flags (some flags map to the same option) + {"BasicRuntimeChecks", "GZ", "Stack frame checks", "1", 0}, + {"BasicRuntimeChecks", "RTCsu", + "Both stack and uninitialized checks", "3", 0}, + {"BasicRuntimeChecks", "RTCs", "Stack frame checks", "1", 0}, + {"BasicRuntimeChecks", "RTCu", "Uninitialized Variables ", "2", 0}, + {"BasicRuntimeChecks", "RTC1", + "Both stack and uninitialized checks", "3", 0}, + {"DebugInformationFormat", "Z7", "debug format", "1", 0}, + {"DebugInformationFormat", "Zd", "debug format", "2", 0}, + {"DebugInformationFormat", "Zi", "debug format", "3", 0}, + {"DebugInformationFormat", "ZI", "debug format", "4", 0}, + {"EnableEnhancedInstructionSet", "arch:SSE2", + "Use sse2 instructions", "2", 0}, + {"EnableEnhancedInstructionSet", "arch:SSE", + "Use sse instructions", "1", 0}, + {"FloatingPointModel", "fp:precise", + "Use precise floating point model", "0", 0}, + {"FloatingPointModel", "fp:strict", + "Use strict floating point model", "1", 0}, + {"FloatingPointModel", "fp:fast", "Use fast floating point model", "2", 0}, + {"FavorSizeOrSpeed", "Ot", "Favor fast code", "1", 0}, + {"FavorSizeOrSpeed", "Os", "Favor small code", "2", 0}, + {"CompileAs", "TC", "Compile as c code", "1", 0}, + {"CompileAs", "TP", "Compile as c++ code", "2", 0}, + {"Optimization", "Od", "Non Debug", "0", 0}, + {"Optimization", "O1", "Min Size", "1", 0}, + {"Optimization", "O2", "Max Speed", "2", 0}, + {"Optimization", "Ox", "Max Optimization", "3", 0}, + {"OptimizeForProcessor", "GB", "Blended processor mode", "0", 0}, + {"OptimizeForProcessor", "G5", "Pentium", "1", 0}, + {"OptimizeForProcessor", "G6", "PPro PII PIII", "2", 0}, + {"OptimizeForProcessor", "G7", "Pentium 4 or Athlon", "3", 0}, + {"InlineFunctionExpansion", "Ob0", "no inlines", "0", 0}, + {"InlineFunctionExpansion", "Ob1", "when inline keyword", "1", 0}, + {"InlineFunctionExpansion", "Ob2", "any time you can inline", "2", 0}, + {"RuntimeLibrary", "MTd", "Multithreaded debug", "1", 0}, + {"RuntimeLibrary", "MT", "Multithreaded", "0", 0}, + {"RuntimeLibrary", "MDd", "Multithreaded dll debug", "3", 0}, + {"RuntimeLibrary", "MD", "Multithreaded dll", "2", 0}, + {"RuntimeLibrary", "MLd", "Single Thread debug", "5", 0}, + {"RuntimeLibrary", "ML", "Single Thread", "4", 0}, + {"StructMemberAlignment", "Zp16", "struct align 16 byte ", "5", 0}, + {"StructMemberAlignment", "Zp1", "struct align 1 byte ", "1", 0}, + {"StructMemberAlignment", "Zp2", "struct align 2 byte ", "2", 0}, + {"StructMemberAlignment", "Zp4", "struct align 4 byte ", "3", 0}, + {"StructMemberAlignment", "Zp8", "struct align 8 byte ", "4", 0}, + {"WarningLevel", "W0", "Warning level", "0", 0}, + {"WarningLevel", "W1", "Warning level", "1", 0}, + {"WarningLevel", "W2", "Warning level", "2", 0}, + {"WarningLevel", "W3", "Warning level", "3", 0}, + {"WarningLevel", "W4", "Warning level", "4", 0}, + {"DisableSpecificWarnings", "wd", "Disable specific warnings", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + + // Precompiled header and related options. Note that the + // UsePrecompiledHeader entries are marked as "Continue" so that the + // corresponding PrecompiledHeaderThrough entry can be found. + {"UsePrecompiledHeader", "Yc", "Create Precompiled Header", "1", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, + {"PrecompiledHeaderThrough", "Yc", "Precompiled Header Name", "", + cmVS7FlagTable::UserValueRequired}, + {"PrecompiledHeaderFile", "Fp", "Generated Precompiled Header", "", + cmVS7FlagTable::UserValue}, + // The YX and Yu options are in a per-global-generator table because + // their values differ based on the VS IDE version. + {"ForcedIncludeFiles", "FI", "Forced include files", "", + cmVS7FlagTable::UserValueRequired | cmVS7FlagTable::SemicolonAppendable}, + + {"AssemblerListingLocation", "Fa", "ASM List Location", "", + cmVS7FlagTable::UserValue}, + {"ProgramDataBaseFileName", "Fd", "Program Database File Name", "", + cmVS7FlagTable::UserValue}, + + // boolean flags + {"BufferSecurityCheck", "GS", "Buffer security check", "true", 0}, + {"BufferSecurityCheck", "GS-", "Turn off Buffer security check", "false", 0}, + {"Detect64BitPortabilityProblems", "Wp64", + "Detect 64-bit Portability Problems", "true", 0}, + {"EnableFiberSafeOptimizations", "GT", "Enable Fiber-safe Optimizations", + "true", 0}, + {"EnableFunctionLevelLinking", "Gy", + "EnableFunctionLevelLinking", "true", 0}, + {"EnableIntrinsicFunctions", "Oi", "EnableIntrinsicFunctions", "true", 0}, + {"GlobalOptimizations", "Og", "Global Optimize", "true", 0}, + {"ImproveFloatingPointConsistency", "Op", + "ImproveFloatingPointConsistency", "true", 0}, + {"MinimalRebuild", "Gm", "minimal rebuild", "true", 0}, + {"OmitFramePointers", "Oy", "OmitFramePointers", "true", 0}, + {"OptimizeForWindowsApplication", "GA", "Optimize for windows", "true", 0}, + {"RuntimeTypeInfo", "GR", + "Turn on Run time type information for c++", "true", 0}, + {"RuntimeTypeInfo", "GR-", + "Turn off Run time type information for c++", "false", 0}, + {"SmallerTypeCheck", "RTCc", "smaller type check", "true", 0}, + {"SuppressStartupBanner", "nologo", "SuppressStartupBanner", "true", 0}, + {"WholeProgramOptimization", "GL", + "Enables whole program optimization", "true", 0}, + {"WholeProgramOptimization", "GL-", + "Disables whole program optimization", "false", 0}, + {"WarnAsError", "WX", "Treat warnings as errors", "true", 0}, + {"BrowseInformation", "FR", "Generate browse information", "1", 0}, + {"StringPooling", "GF", "Enable StringPooling", "true", 0}, + {0,0,0,0,0} +}; + + + +cmVS7FlagTable cmLocalVisualStudio7GeneratorLinkFlagTable[] = +{ + // option flags (some flags map to the same option) + {"GenerateManifest", "MANIFEST:NO", + "disable manifest generation", "false", 0}, + {"GenerateManifest", "MANIFEST", "enable manifest generation", "true", 0}, + {"LinkIncremental", "INCREMENTAL:NO", "link incremental", "1", 0}, + {"LinkIncremental", "INCREMENTAL:YES", "link incremental", "2", 0}, + {"CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0}, + {"CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0}, + {"DataExecutionPrevention", "NXCOMPAT:NO", + "Not known to work with Windows Data Execution Prevention", "1", 0}, + {"DataExecutionPrevention", "NXCOMPAT", + "Known to work with Windows Data Execution Prevention", "2", 0}, + {"DelaySign", "DELAYSIGN:NO", "", "false", 0}, + {"DelaySign", "DELAYSIGN", "", "true", 0}, + {"EntryPointSymbol", "ENTRY:", "sets the starting address", "", + cmVS7FlagTable::UserValue}, + {"IgnoreDefaultLibraryNames", "NODEFAULTLIB:", "default libs to ignore", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable}, + {"IgnoreAllDefaultLibraries", "NODEFAULTLIB", "ignore all default libs", + "true", 0}, + {"FixedBaseAddress", "FIXED:NO", "Generate a relocation section", "1", 0}, + {"FixedBaseAddress", "FIXED", "Image must be loaded at a fixed address", + "2", 0}, + {"EnableCOMDATFolding", "OPT:NOICF", "Do not remove redundant COMDATs", + "1", 0}, + {"EnableCOMDATFolding", "OPT:ICF", "Remove redundant COMDATs", "2", 0}, + {"ResourceOnlyDLL", "NOENTRY", "Create DLL with no entry point", "true", 0}, + {"OptimizeReferences", "OPT:NOREF", "Keep unreferenced data", "1", 0}, + {"OptimizeReferences", "OPT:REF", "Eliminate unreferenced data", "2", 0}, + {"Profile", "PROFILE", "", "true", 0}, + {"RandomizedBaseAddress", "DYNAMICBASE:NO", + "Image may not be rebased at load-time", "1", 0}, + {"RandomizedBaseAddress", "DYNAMICBASE", + "Image may be rebased at load-time", "2", 0}, + {"SetChecksum", "RELEASE", "Enable setting checksum in header", "true", 0}, + {"SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0}, + {"TargetMachine", "MACHINE:I386", "Machine x86", "1", 0}, + {"TargetMachine", "MACHINE:X86", "Machine x86", "1", 0}, + {"TargetMachine", "MACHINE:AM33", "Machine AM33", "2", 0}, + {"TargetMachine", "MACHINE:ARM", "Machine ARM", "3", 0}, + {"TargetMachine", "MACHINE:EBC", "Machine EBC", "4", 0}, + {"TargetMachine", "MACHINE:IA64", "Machine IA64", "5", 0}, + {"TargetMachine", "MACHINE:M32R", "Machine M32R", "6", 0}, + {"TargetMachine", "MACHINE:MIPS", "Machine MIPS", "7", 0}, + {"TargetMachine", "MACHINE:MIPS16", "Machine MIPS16", "8", 0}, + {"TargetMachine", "MACHINE:MIPSFPU)", "Machine MIPSFPU", "9", 0}, + {"TargetMachine", "MACHINE:MIPSFPU16", "Machine MIPSFPU16", "10", 0}, + {"TargetMachine", "MACHINE:MIPSR41XX", "Machine MIPSR41XX", "11", 0}, + {"TargetMachine", "MACHINE:SH3", "Machine SH3", "12", 0}, + {"TargetMachine", "MACHINE:SH3DSP", "Machine SH3DSP", "13", 0}, + {"TargetMachine", "MACHINE:SH4", "Machine SH4", "14", 0}, + {"TargetMachine", "MACHINE:SH5", "Machine SH5", "15", 0}, + {"TargetMachine", "MACHINE:THUMB", "Machine THUMB", "16", 0}, + {"TargetMachine", "MACHINE:X64", "Machine x64", "17", 0}, + {"TurnOffAssemblyGeneration", "NOASSEMBLY", + "No assembly even if CLR information is present in objects.", "true", 0}, + {"ModuleDefinitionFile", "DEF:", "add an export def file", "", + cmVS7FlagTable::UserValue}, + {"GenerateMapFile", "MAP", "enable generation of map file", "true", 0}, + {0,0,0,0,0} +}; + +cmVS7FlagTable cmLocalVisualStudio7GeneratorFortranLinkFlagTable[] = +{ + {"LinkIncremental", "INCREMENTAL:NO", "link incremental", + "linkIncrementalNo", 0}, + {"LinkIncremental", "INCREMENTAL:YES", "link incremental", + "linkIncrementalYes", 0}, + {0,0,0,0,0} +}; + +//---------------------------------------------------------------------------- +// Helper class to write build event <Tool .../> elements. +class cmLocalVisualStudio7Generator::EventWriter +{ +public: + EventWriter(cmLocalVisualStudio7Generator* lg, + const std::string& config, std::ostream& os): + LG(lg), Config(config), Stream(os), First(true) {} + void Start(const char* tool) + { + this->First = true; + this->Stream << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\""; + } + void Finish() + { + this->Stream << (this->First? "" : "\"") << "/>\n"; + } + void Write(std::vector<cmCustomCommand> const& ccs) + { + for(std::vector<cmCustomCommand>::const_iterator ci = ccs.begin(); + ci != ccs.end(); ++ci) + { + this->Write(*ci); + } + } + void Write(cmCustomCommand const& cc) + { + cmCustomCommandGenerator ccg(cc, this->Config, this->LG); + if(this->First) + { + const char* comment = ccg.GetComment(); + if(comment && *comment) + { + this->Stream << "\nDescription=\"" + << this->LG->EscapeForXML(comment) << "\""; + } + this->Stream << "\nCommandLine=\""; + this->First = false; + } + else + { + this->Stream << this->LG->EscapeForXML("\n"); + } + std::string script = this->LG->ConstructScript(ccg); + this->Stream << this->LG->EscapeForXML(script.c_str()); + } +private: + cmLocalVisualStudio7Generator* LG; + std::string Config; + std::ostream& Stream; + bool First; +}; + +//---------------------------------------------------------------------------- +void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, + const std::string& configName, + const std::string& libName, + cmTarget &target) +{ + const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG"); + if(!mfcFlag) + { + mfcFlag = "0"; + } + cmGlobalVisualStudio7Generator* gg = + static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator); + fout << "\t\t<Configuration\n" + << "\t\t\tName=\"" << configName + << "|" << gg->GetPlatformName() << "\"\n"; + // This is an internal type to Visual Studio, it seems that: + // 4 == static library + // 2 == dll + // 1 == executable + // 10 == utility + const char* configType = "10"; + const char* projectType = 0; + bool targetBuilds = true; + + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + + switch(target.GetType()) + { + case cmTarget::OBJECT_LIBRARY: + targetBuilds = false; // no manifest tool for object library + case cmTarget::STATIC_LIBRARY: + projectType = "typeStaticLibrary"; + configType = "4"; + break; + case cmTarget::SHARED_LIBRARY: + case cmTarget::MODULE_LIBRARY: + projectType = "typeDynamicLibrary"; + configType = "2"; + break; + case cmTarget::EXECUTABLE: + configType = "1"; + break; + case cmTarget::UTILITY: + case cmTarget::GLOBAL_TARGET: + configType = "10"; + default: + targetBuilds = false; + break; + } + if(this->FortranProject && projectType) + { + configType = projectType; + } + std::string flags; + if(strcmp(configType, "10") != 0) + { + const std::string& linkLanguage = (this->FortranProject? + std::string("Fortran"): + gt->GetLinkerLanguage(configName)); + if(linkLanguage.empty()) + { + cmSystemTools::Error + ("CMake can not determine linker language for target: ", + target.GetName().c_str()); + return; + } + if(linkLanguage == "C" || linkLanguage == "CXX" + || linkLanguage == "Fortran") + { + std::string baseFlagVar = "CMAKE_"; + baseFlagVar += linkLanguage; + baseFlagVar += "_FLAGS"; + flags = this->Makefile->GetRequiredDefinition(baseFlagVar.c_str()); + std::string flagVar = baseFlagVar + std::string("_") + + cmSystemTools::UpperCase(configName); + flags += " "; + flags += this->Makefile->GetRequiredDefinition(flagVar.c_str()); + } + // set the correct language + if(linkLanguage == "C") + { + flags += " /TC "; + } + if(linkLanguage == "CXX") + { + flags += " /TP "; + } + + // Add the target-specific flags. + this->AddCompileOptions(flags, &target, linkLanguage, configName); + } + + if(this->FortranProject) + { + switch(this->GetFortranFormat(target.GetProperty("Fortran_FORMAT"))) + { + case FortranFormatFixed: flags += " -fixed"; break; + case FortranFormatFree: flags += " -free"; break; + default: break; + } + } + + // Get preprocessor definitions for this directory. + std::string defineFlags = this->Makefile->GetDefineFlags(); + Options::Tool t = Options::Compiler; + cmVS7FlagTable const* table = cmLocalVisualStudio7GeneratorFlagTable; + if(this->FortranProject) + { + t = Options::FortranCompiler; + table = cmLocalVisualStudio7GeneratorFortranFlagTable; + } + Options targetOptions(this, t, + table, + gg->ExtraFlagTable); + targetOptions.FixExceptionHandlingDefault(); + std::string asmLocation = configName + "/"; + targetOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str()); + targetOptions.Parse(flags.c_str()); + targetOptions.Parse(defineFlags.c_str()); + targetOptions.ParseFinish(); + std::vector<std::string> targetDefines; + gt->GetCompileDefinitions(targetDefines, configName, "CXX"); + targetOptions.AddDefines(targetDefines); + targetOptions.SetVerboseMakefile( + this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE")); + + // Add a definition for the configuration name. + std::string configDefine = "CMAKE_INTDIR=\""; + configDefine += configName; + configDefine += "\""; + targetOptions.AddDefine(configDefine); + + // Add the export symbol definition for shared library objects. + if(const char* exportMacro = target.GetExportMacro()) + { + targetOptions.AddDefine(exportMacro); + } + + // The intermediate directory name consists of a directory for the + // target and a subdirectory for the configuration name. + std::string intermediateDir = this->GetTargetDirectory(target); + intermediateDir += "/"; + intermediateDir += configName; + + if (target.GetType() < cmTarget::UTILITY) + { + std::string const& outDir = + target.GetType() == cmTarget::OBJECT_LIBRARY? + intermediateDir : target.GetDirectory(configName); + fout << "\t\t\tOutputDirectory=\"" + << this->ConvertToXMLOutputPathSingle(outDir.c_str()) << "\"\n"; + } + + fout << "\t\t\tIntermediateDirectory=\"" + << this->ConvertToXMLOutputPath(intermediateDir.c_str()) + << "\"\n" + << "\t\t\tConfigurationType=\"" << configType << "\"\n" + << "\t\t\tUseOfMFC=\"" << mfcFlag << "\"\n" + << "\t\t\tATLMinimizesCRunTimeLibraryUsage=\"false\"\n"; + + if (this->FortranProject) + { + // Intel Fortran >= 15.0 uses TargetName property. + std::string targetNameFull = gt->GetFullName(configName); + std::string targetName = + cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull); + std::string targetExt = + cmSystemTools::GetFilenameLastExtension(targetNameFull); + fout << + "\t\t\tTargetName=\"" << this->EscapeForXML(targetName) << "\"\n" + "\t\t\tTargetExt=\"" << this->EscapeForXML(targetExt) << "\"\n" + ; + } + + // If unicode is enabled change the character set to unicode, if not + // then default to MBCS. + if(targetOptions.UsingUnicode()) + { + fout << "\t\t\tCharacterSet=\"1\">\n"; + } + else if(targetOptions.UsingSBCS()) + { + fout << "\t\t\tCharacterSet=\"0\">\n"; + } + else + { + fout << "\t\t\tCharacterSet=\"2\">\n"; + } + const char* tool = "VCCLCompilerTool"; + if(this->FortranProject) + { + tool = "VFFortranCompilerTool"; + } + fout << "\t\t\t<Tool\n" + << "\t\t\t\tName=\"" << tool << "\"\n"; + if(this->FortranProject) + { + const char* target_mod_dir = + target.GetProperty("Fortran_MODULE_DIRECTORY"); + std::string modDir; + if(target_mod_dir) + { + modDir = this->Convert(target_mod_dir, + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::UNCHANGED); + } + else + { + modDir = "."; + } + fout << "\t\t\t\tModulePath=\"" + << this->ConvertToXMLOutputPath(modDir.c_str()) + << "\\$(ConfigurationName)\"\n"; + } + targetOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n"); + fout << "\t\t\t\tAdditionalIncludeDirectories=\""; + std::vector<std::string> includes; + this->GetIncludeDirectories(includes, gt, "C", configName); + std::vector<std::string>::iterator i = includes.begin(); + for(;i != includes.end(); ++i) + { + // output the include path + std::string ipath = this->ConvertToXMLOutputPath(i->c_str()); + fout << ipath << ";"; + // if this is fortran then output the include with + // a ConfigurationName on the end of it. + if(this->FortranProject) + { + ipath = i->c_str(); + ipath += "/$(ConfigurationName)"; + ipath = this->ConvertToXMLOutputPath(ipath.c_str()); + fout << ipath << ";"; + } + } + fout << "\"\n"; + targetOptions.OutputFlagMap(fout, "\t\t\t\t"); + targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n", "CXX"); + fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n"; + if(target.GetType() <= cmTarget::OBJECT_LIBRARY) + { + // Specify the compiler program database file if configured. + std::string pdb = gt->GetCompilePDBPath(configName); + if(!pdb.empty()) + { + fout << "\t\t\t\tProgramDataBaseFileName=\"" + << this->ConvertToXMLOutputPathSingle(pdb.c_str()) + << "\"\n"; + } + } + fout << "/>\n"; // end of <Tool Name=VCCLCompilerTool + if(gg->IsMasmEnabled() && !this->FortranProject) + { + Options masmOptions(this, Options::MasmCompiler, 0, 0); + fout << + "\t\t\t<Tool\n" + "\t\t\t\tName=\"MASM\"\n" + "\t\t\t\tIncludePaths=\"" + ; + const char* sep = ""; + for(i = includes.begin(); i != includes.end(); ++i) + { + std::string inc = *i; + cmConvertToWindowsSlash(inc); + fout << sep << this->EscapeForXML(inc); + sep = ";"; + } + fout << "\"\n"; + // Use same preprocessor definitions as VCCLCompilerTool. + targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n", + "ASM_MASM"); + masmOptions.OutputFlagMap(fout, "\t\t\t\t"); + fout << + "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n" + "\t\t\t/>\n"; + } + tool = "VCCustomBuildTool"; + if(this->FortranProject) + { + tool = "VFCustomBuildTool"; + } + fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"/>\n"; + tool = "VCResourceCompilerTool"; + if(this->FortranProject) + { + tool = "VFResourceCompilerTool"; + } + fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n" + << "\t\t\t\tAdditionalIncludeDirectories=\""; + for(i = includes.begin();i != includes.end(); ++i) + { + std::string ipath = this->ConvertToXMLOutputPath(i->c_str()); + fout << ipath << ";"; + } + // add the -D flags to the RC tool + fout << "\""; + targetOptions.OutputPreprocessorDefinitions(fout, "\n\t\t\t\t", "", "RC"); + fout << "/>\n"; + tool = "VCMIDLTool"; + if(this->FortranProject) + { + tool = "VFMIDLTool"; + } + fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n"; + fout << "\t\t\t\tAdditionalIncludeDirectories=\""; + for(i = includes.begin(); i != includes.end(); ++i) + { + std::string ipath = this->ConvertToXMLOutputPath(i->c_str()); + fout << ipath << ";"; + } + fout << "\"\n"; + fout << "\t\t\t\tMkTypLibCompatible=\"false\"\n"; + if( gg->GetPlatformName() == "x64" ) + { + fout << "\t\t\t\tTargetEnvironment=\"3\"\n"; + } + else if( gg->GetPlatformName() == "ia64" ) + { + fout << "\t\t\t\tTargetEnvironment=\"2\"\n"; + } + else + { + fout << "\t\t\t\tTargetEnvironment=\"1\"\n"; + } + fout << "\t\t\t\tGenerateStublessProxies=\"true\"\n"; + fout << "\t\t\t\tTypeLibraryName=\"$(InputName).tlb\"\n"; + fout << "\t\t\t\tOutputDirectory=\"$(IntDir)\"\n"; + fout << "\t\t\t\tHeaderFileName=\"$(InputName).h\"\n"; + fout << "\t\t\t\tDLLDataFileName=\"\"\n"; + fout << "\t\t\t\tInterfaceIdentifierFileName=\"$(InputName)_i.c\"\n"; + fout << "\t\t\t\tProxyFileName=\"$(InputName)_p.c\"/>\n"; + // end of <Tool Name=VCMIDLTool + + // Add manifest tool settings. + if(targetBuilds && this->GetVersion() >= cmGlobalVisualStudioGenerator::VS8) + { + const char* manifestTool = "VCManifestTool"; + if (this->FortranProject) + { + manifestTool = "VFManifestTool"; + } + fout << + "\t\t\t<Tool\n" + "\t\t\t\tName=\"" << manifestTool << "\""; + + std::vector<cmSourceFile const*> manifest_srcs; + gt->GetManifests(manifest_srcs, configName); + if (!manifest_srcs.empty()) + { + fout << "\n\t\t\t\tAdditionalManifestFiles=\""; + for (std::vector<cmSourceFile const*>::const_iterator + mi = manifest_srcs.begin(); mi != manifest_srcs.end(); ++mi) + { + std::string m = (*mi)->GetFullPath(); + fout << this->ConvertToXMLOutputPath(m.c_str()) << ";"; + } + fout << "\""; + } + + // Check if we need the FAT32 workaround. + // Check the filesystem type where the target will be written. + if (cmLVS6G_IsFAT(target.GetDirectory(configName).c_str())) + { + // Add a flag telling the manifest tool to use a workaround + // for FAT32 file systems, which can cause an empty manifest + // to be embedded into the resulting executable. See CMake + // bug #2617. + fout << "\n\t\t\t\tUseFAT32Workaround=\"true\""; + } + fout << "/>\n"; + } + + this->OutputTargetRules(fout, configName, target, libName); + this->OutputBuildTool(fout, configName, target, targetOptions); + fout << "\t\t</Configuration>\n"; +} + +//---------------------------------------------------------------------------- +std::string +cmLocalVisualStudio7Generator +::GetBuildTypeLinkerFlags(std::string rootLinkerFlags, + const std::string& configName) +{ + std::string configTypeUpper = cmSystemTools::UpperCase(configName); + std::string extraLinkOptionsBuildTypeDef = + rootLinkerFlags + "_" + configTypeUpper; + + std::string extraLinkOptionsBuildType = + this->Makefile->GetRequiredDefinition + (extraLinkOptionsBuildTypeDef.c_str()); + + return extraLinkOptionsBuildType; +} + +void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, + const std::string& configName, cmTarget &target, + const Options& targetOptions) +{ + cmGlobalVisualStudio7Generator* gg = + static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator); + std::string temp; + std::string extraLinkOptions; + if(target.GetType() == cmTarget::EXECUTABLE) + { + extraLinkOptions = + this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS") + + std::string(" ") + + GetBuildTypeLinkerFlags("CMAKE_EXE_LINKER_FLAGS", configName); + } + if(target.GetType() == cmTarget::SHARED_LIBRARY) + { + extraLinkOptions = + this->Makefile->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS") + + std::string(" ") + + GetBuildTypeLinkerFlags("CMAKE_SHARED_LINKER_FLAGS", configName); + } + if(target.GetType() == cmTarget::MODULE_LIBRARY) + { + extraLinkOptions = + this->Makefile->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS") + + std::string(" ") + + GetBuildTypeLinkerFlags("CMAKE_MODULE_LINKER_FLAGS", configName); + } + + const char* targetLinkFlags = target.GetProperty("LINK_FLAGS"); + if(targetLinkFlags) + { + extraLinkOptions += " "; + extraLinkOptions += targetLinkFlags; + } + std::string configTypeUpper = cmSystemTools::UpperCase(configName); + std::string linkFlagsConfig = "LINK_FLAGS_"; + linkFlagsConfig += configTypeUpper; + targetLinkFlags = target.GetProperty(linkFlagsConfig.c_str()); + if(targetLinkFlags) + { + extraLinkOptions += " "; + extraLinkOptions += targetLinkFlags; + } + Options linkOptions(this, Options::Linker); + if(this->FortranProject) + { + linkOptions.AddTable(cmLocalVisualStudio7GeneratorFortranLinkFlagTable); + } + linkOptions.AddTable(cmLocalVisualStudio7GeneratorLinkFlagTable); + + linkOptions.Parse(extraLinkOptions.c_str()); + if(!this->ModuleDefinitionFile.empty()) + { + std::string defFile = + this->ConvertToOutputFormat(this->ModuleDefinitionFile, SHELL); + linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str()); + } + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + + if (target.GetType() == cmTarget::SHARED_LIBRARY && + this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) + { + if (target.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) + { + linkOptions.AddFlag("ModuleDefinitionFile", "$(IntDir)/exportall.def"); + } + } + switch(target.GetType()) + { + case cmTarget::UNKNOWN_LIBRARY: + break; + case cmTarget::OBJECT_LIBRARY: + { + std::string libpath = this->GetTargetDirectory(target); + libpath += "/"; + libpath += configName; + libpath += "/"; + libpath += target.GetName(); + libpath += ".lib"; + const char* tool = + this->FortranProject? "VFLibrarianTool":"VCLibrarianTool"; + fout << "\t\t\t<Tool\n" + << "\t\t\t\tName=\"" << tool << "\"\n"; + fout << "\t\t\t\tOutputFile=\"" + << this->ConvertToXMLOutputPathSingle(libpath.c_str()) << "\"/>\n"; + break; + } + case cmTarget::STATIC_LIBRARY: + { + std::string targetNameFull = gt->GetFullName(configName); + std::string libpath = target.GetDirectory(configName); + libpath += "/"; + libpath += targetNameFull; + const char* tool = "VCLibrarianTool"; + if(this->FortranProject) + { + tool = "VFLibrarianTool"; + } + fout << "\t\t\t<Tool\n" + << "\t\t\t\tName=\"" << tool << "\"\n"; + + if(this->GetVersion() < cmGlobalVisualStudioGenerator::VS8 + || this->FortranProject) + { + std::ostringstream libdeps; + this->Internal->OutputObjects(libdeps, &target); + if(!libdeps.str().empty()) + { + fout << "\t\t\t\tAdditionalDependencies=\"" << libdeps.str() << "\"\n"; + } + } + std::string libflags; + this->GetStaticLibraryFlags(libflags, configTypeUpper, &target); + if(!libflags.empty()) + { + fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\n"; + } + fout << "\t\t\t\tOutputFile=\"" + << this->ConvertToXMLOutputPathSingle(libpath.c_str()) << "\"/>\n"; + break; + } + case cmTarget::SHARED_LIBRARY: + case cmTarget::MODULE_LIBRARY: + { + std::string targetName; + std::string targetNameSO; + std::string targetNameFull; + std::string targetNameImport; + std::string targetNamePDB; + gt->GetLibraryNames(targetName, targetNameSO, targetNameFull, + targetNameImport, targetNamePDB, configName); + + // Compute the link library and directory information. + cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName); + if(!pcli) + { + return; + } + cmComputeLinkInformation& cli = *pcli; + std::string linkLanguage = cli.GetLinkLanguage(); + + // Compute the variable name to lookup standard libraries for this + // language. + std::string standardLibsVar = "CMAKE_"; + standardLibsVar += linkLanguage; + standardLibsVar += "_STANDARD_LIBRARIES"; + const char* tool = "VCLinkerTool"; + if(this->FortranProject) + { + tool = "VFLinkerTool"; + } + fout << "\t\t\t<Tool\n" + << "\t\t\t\tName=\"" << tool << "\"\n"; + if(!gg->NeedLinkLibraryDependencies(target)) + { + fout << "\t\t\t\tLinkLibraryDependencies=\"false\"\n"; + } + linkOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n"); + // Use the NOINHERIT macro to avoid getting VS project default + // libraries which may be set by the user to something bad. + fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " + << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); + if(this->GetVersion() < cmGlobalVisualStudioGenerator::VS8 + || this->FortranProject) + { + this->Internal->OutputObjects(fout, &target, " "); + } + fout << " "; + this->Internal->OutputLibraries(fout, cli.GetItems()); + fout << "\"\n"; + temp = target.GetDirectory(configName); + temp += "/"; + temp += targetNameFull; + fout << "\t\t\t\tOutputFile=\"" + << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n"; + this->WriteTargetVersionAttribute(fout, target); + linkOptions.OutputFlagMap(fout, "\t\t\t\t"); + fout << "\t\t\t\tAdditionalLibraryDirectories=\""; + this->OutputLibraryDirectories(fout, cli.GetDirectories()); + fout << "\"\n"; + temp = target.GetPDBDirectory(configName); + temp += "/"; + temp += targetNamePDB; + fout << "\t\t\t\tProgramDatabaseFile=\"" << + this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n"; + if(targetOptions.IsDebug()) + { + fout << "\t\t\t\tGenerateDebugInformation=\"true\"\n"; + } + if(this->WindowsCEProject) + { + if(this->GetVersion() < cmGlobalVisualStudioGenerator::VS9) + { + fout << "\t\t\t\tSubSystem=\"9\"\n"; + } + else + { + fout << "\t\t\t\tSubSystem=\"8\"\n"; + } + } + std::string stackVar = "CMAKE_"; + stackVar += linkLanguage; + stackVar += "_STACK_SIZE"; + const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str()); + if(stackVal) + { + fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\"\n"; + } + temp = target.GetDirectory(configName, true); + temp += "/"; + temp += targetNameImport; + fout << "\t\t\t\tImportLibrary=\"" + << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\""; + if(this->FortranProject) + { + fout << "\n\t\t\t\tLinkDLL=\"true\""; + } + fout << "/>\n"; + } + break; + case cmTarget::EXECUTABLE: + { + std::string targetName; + std::string targetNameFull; + std::string targetNameImport; + std::string targetNamePDB; + gt->GetExecutableNames(targetName, targetNameFull, + targetNameImport, targetNamePDB, configName); + + // Compute the link library and directory information. + cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName); + if(!pcli) + { + return; + } + cmComputeLinkInformation& cli = *pcli; + std::string linkLanguage = cli.GetLinkLanguage(); + + bool isWin32Executable = target.GetPropertyAsBool("WIN32_EXECUTABLE"); + + // Compute the variable name to lookup standard libraries for this + // language. + std::string standardLibsVar = "CMAKE_"; + standardLibsVar += linkLanguage; + standardLibsVar += "_STANDARD_LIBRARIES"; + const char* tool = "VCLinkerTool"; + if(this->FortranProject) + { + tool = "VFLinkerTool"; + } + fout << "\t\t\t<Tool\n" + << "\t\t\t\tName=\"" << tool << "\"\n"; + if(!gg->NeedLinkLibraryDependencies(target)) + { + fout << "\t\t\t\tLinkLibraryDependencies=\"false\"\n"; + } + linkOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n"); + // Use the NOINHERIT macro to avoid getting VS project default + // libraries which may be set by the user to something bad. + fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " + << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); + if(this->GetVersion() < cmGlobalVisualStudioGenerator::VS8 + || this->FortranProject) + { + this->Internal->OutputObjects(fout, &target, " "); + } + fout << " "; + this->Internal->OutputLibraries(fout, cli.GetItems()); + fout << "\"\n"; + temp = target.GetDirectory(configName); + temp += "/"; + temp += targetNameFull; + fout << "\t\t\t\tOutputFile=\"" + << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n"; + this->WriteTargetVersionAttribute(fout, target); + linkOptions.OutputFlagMap(fout, "\t\t\t\t"); + fout << "\t\t\t\tAdditionalLibraryDirectories=\""; + this->OutputLibraryDirectories(fout, cli.GetDirectories()); + fout << "\"\n"; + std::string path = this->ConvertToXMLOutputPathSingle( + target.GetPDBDirectory(configName).c_str()); + fout << "\t\t\t\tProgramDatabaseFile=\"" + << path << "/" << targetNamePDB + << "\"\n"; + if(targetOptions.IsDebug()) + { + fout << "\t\t\t\tGenerateDebugInformation=\"true\"\n"; + } + if ( this->WindowsCEProject ) + { + if(this->GetVersion() < cmGlobalVisualStudioGenerator::VS9) + { + fout << "\t\t\t\tSubSystem=\"9\"\n"; + } + else + { + fout << "\t\t\t\tSubSystem=\"8\"\n"; + } + + if(!linkOptions.GetFlag("EntryPointSymbol")) + { + const char* entryPointSymbol = targetOptions.UsingUnicode() ? + (isWin32Executable ? "wWinMainCRTStartup" : "mainWCRTStartup") : + (isWin32Executable ? "WinMainCRTStartup" : "mainACRTStartup"); + fout << "\t\t\t\tEntryPointSymbol=\"" << entryPointSymbol << "\"\n"; + } + } + else if ( this->FortranProject ) + { + fout << "\t\t\t\tSubSystem=\"" + << (isWin32Executable ? "subSystemWindows" : "subSystemConsole") + << "\"\n"; + } + else + { + fout << "\t\t\t\tSubSystem=\"" + << (isWin32Executable ? "2" : "1") + << "\"\n"; + } + std::string stackVar = "CMAKE_"; + stackVar += linkLanguage; + stackVar += "_STACK_SIZE"; + const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str()); + if(stackVal) + { + fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\""; + } + temp = target.GetDirectory(configName, true); + temp += "/"; + temp += targetNameImport; + fout << "\t\t\t\tImportLibrary=\"" + << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"/>\n"; + break; + } + case cmTarget::UTILITY: + case cmTarget::GLOBAL_TARGET: + case cmTarget::INTERFACE_LIBRARY: + break; + } +} + +//---------------------------------------------------------------------------- +void +cmLocalVisualStudio7Generator +::WriteTargetVersionAttribute(std::ostream& fout, cmTarget& target) +{ + int major; + int minor; + target.GetTargetVersion(major, minor); + fout << "\t\t\t\tVersion=\"" << major << "." << minor << "\"\n"; +} + +//---------------------------------------------------------------------------- +void +cmLocalVisualStudio7GeneratorInternals +::OutputLibraries(std::ostream& fout, ItemVector const& libs) +{ + cmLocalVisualStudio7Generator* lg = this->LocalGenerator; + for(ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l) + { + if(l->IsPath) + { + std::string rel = lg->Convert(l->Value.c_str(), + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::UNCHANGED); + fout << lg->ConvertToXMLOutputPath(rel.c_str()) << " "; + } + else if (!l->Target + || l->Target->GetType() != cmTarget::INTERFACE_LIBRARY) + { + fout << l->Value << " "; + } + } +} + +//---------------------------------------------------------------------------- +void +cmLocalVisualStudio7GeneratorInternals +::OutputObjects(std::ostream& fout, cmTarget* t, const char* isep) +{ + // VS < 8 does not support per-config source locations so we + // list object library content on the link line instead. + cmLocalVisualStudio7Generator* lg = this->LocalGenerator; + cmGeneratorTarget* gt = + lg->GetGlobalGenerator()->GetGeneratorTarget(t); + std::vector<std::string> objs; + gt->UseObjectLibraries(objs, ""); + const char* sep = isep? isep : ""; + for(std::vector<std::string>::const_iterator + oi = objs.begin(); oi != objs.end(); ++oi) + { + std::string rel = lg->Convert(oi->c_str(), + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::UNCHANGED); + fout << sep << lg->ConvertToXMLOutputPath(rel.c_str()); + sep = " "; + } +} + +//---------------------------------------------------------------------------- +void +cmLocalVisualStudio7Generator +::OutputLibraryDirectories(std::ostream& fout, + std::vector<std::string> const& dirs) +{ + const char* comma = ""; + for(std::vector<std::string>::const_iterator d = dirs.begin(); + d != dirs.end(); ++d) + { + // Remove any trailing slash and skip empty paths. + std::string dir = *d; + if(dir[dir.size()-1] == '/') + { + dir = dir.substr(0, dir.size()-1); + } + if(dir.empty()) + { + continue; + } + + // Switch to a relative path specification if it is shorter. + if(cmSystemTools::FileIsFullPath(dir.c_str())) + { + std::string rel = this->Convert(dir.c_str(), START_OUTPUT, UNCHANGED); + if(rel.size() < dir.size()) + { + dir = rel; + } + } + + // First search a configuration-specific subdirectory and then the + // original directory. + fout << comma + << this->ConvertToXMLOutputPath((dir+"/$(ConfigurationName)").c_str()) + << "," << this->ConvertToXMLOutputPath(dir.c_str()); + comma = ","; + } +} + +void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, + const std::string& libName, + cmTarget &target) +{ + std::vector<std::string> configs; + this->Makefile->GetConfigurations(configs); + + // We may be modifying the source groups temporarily, so make a copy. + std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups(); + + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + + // get the classes from the source lists then add them to the groups + this->ModuleDefinitionFile = ""; + std::vector<cmSourceFile*> classes; + if (!gt->GetConfigCommonSourceFiles(classes)) + { + return; + } + for(std::vector<cmSourceFile*>::const_iterator i = classes.begin(); + i != classes.end(); i++) + { + if (!(*i)->GetObjectLibrary().empty()) + { + continue; + } + // Add the file to the list of sources. + std::string source = (*i)->GetFullPath(); + if(cmSystemTools::UpperCase((*i)->GetExtension()) == "DEF") + { + this->ModuleDefinitionFile = (*i)->GetFullPath(); + } + cmSourceGroup* sourceGroup = + this->Makefile->FindSourceGroup(source.c_str(), sourceGroups); + sourceGroup->AssignSource(*i); + } + + // open the project + this->WriteProjectStart(fout, libName, target, sourceGroups); + // write the configuration information + this->WriteConfigurations(fout, configs, libName, target); + + fout << "\t<Files>\n"; + + + // Loop through every source group. + for(unsigned int i = 0; i < sourceGroups.size(); ++i) + { + cmSourceGroup sg = sourceGroups[i]; + this->WriteGroup(&sg, target, fout, libName, configs); + } + + if(this->GetVersion() >= cmGlobalVisualStudioGenerator::VS8 + && !this->FortranProject) + { + // VS >= 8 support per-config source locations so we + // list object library content as external objects. + std::vector<std::string> objs; + gt->UseObjectLibraries(objs, ""); + if(!objs.empty()) + { + // TODO: Separate sub-filter for each object library used? + fout << "\t\t<Filter Name=\"Object Libraries\">\n"; + for(std::vector<std::string>::const_iterator + oi = objs.begin(); oi != objs.end(); ++oi) + { + std::string o = this->ConvertToXMLOutputPathSingle(oi->c_str()); + fout << "\t\t\t<File RelativePath=\"" << o << "\" />\n"; + } + fout << "\t\t</Filter>\n"; + } + } + + fout << "\t</Files>\n"; + + // Write the VCProj file's footer. + this->WriteVCProjFooter(fout, target); +} + +struct cmLVS7GFileConfig +{ + std::string ObjectName; + std::string CompileFlags; + std::string CompileDefs; + std::string CompileDefsConfig; + std::string AdditionalDeps; + bool ExcludedFromBuild; +}; + +class cmLocalVisualStudio7GeneratorFCInfo +{ +public: + cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg, + cmTarget& target, + cmSourceFile const& sf, + std::vector<std::string> const& configs); + std::map<std::string, cmLVS7GFileConfig> FileConfigMap; +}; + +cmLocalVisualStudio7GeneratorFCInfo +::cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg, + cmTarget& target, + cmSourceFile const& sf, + std::vector<std::string> const& configs) +{ + cmGeneratorTarget* gt = + lg->GetGlobalGenerator()->GetGeneratorTarget(&target); + std::string objectName; + if(gt->HasExplicitObjectName(&sf)) + { + objectName = gt->GetObjectName(&sf); + } + + // Compute per-source, per-config information. + for(std::vector<std::string>::const_iterator i = configs.begin(); + i != configs.end(); ++i) + { + std::string configUpper = cmSystemTools::UpperCase(*i); + cmLVS7GFileConfig fc; + bool needfc = false; + if(!objectName.empty()) + { + fc.ObjectName = objectName; + needfc = true; + } + if(const char* cflags = sf.GetProperty("COMPILE_FLAGS")) + { + fc.CompileFlags = cflags; + needfc = true; + } + if(lg->FortranProject) + { + switch(lg->GetFortranFormat(sf.GetProperty("Fortran_FORMAT"))) + { + case cmLocalGenerator::FortranFormatFixed: + fc.CompileFlags = "-fixed " + fc.CompileFlags; + needfc = true; + break; + case cmLocalGenerator::FortranFormatFree: + fc.CompileFlags = "-free " + fc.CompileFlags; + needfc = true; + break; + default: break; + } + } + if(const char* cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) + { + fc.CompileDefs = cdefs; + needfc = true; + } + std::string defPropName = "COMPILE_DEFINITIONS_"; + defPropName += configUpper; + if(const char* ccdefs = sf.GetProperty(defPropName.c_str())) + { + fc.CompileDefsConfig = ccdefs; + needfc = true; + } + + // Check for extra object-file dependencies. + if(const char* deps = sf.GetProperty("OBJECT_DEPENDS")) + { + std::vector<std::string> depends; + cmSystemTools::ExpandListArgument(deps, depends); + const char* sep = ""; + for(std::vector<std::string>::iterator j = depends.begin(); + j != depends.end(); ++j) + { + fc.AdditionalDeps += sep; + fc.AdditionalDeps += lg->ConvertToXMLOutputPath(j->c_str()); + sep = ";"; + needfc = true; + } + } + + std::string lang = + lg->GlobalGenerator->GetLanguageFromExtension + (sf.GetExtension().c_str()); + const std::string& sourceLang = lg->GetSourceFileLanguage(sf); + const std::string& linkLanguage = gt->GetLinkerLanguage(i->c_str()); + bool needForceLang = false; + // source file does not match its extension language + if(lang != sourceLang) + { + needForceLang = true; + lang = sourceLang; + } + // If HEADER_FILE_ONLY is set, we must suppress this generation in + // the project file + fc.ExcludedFromBuild = + (sf.GetPropertyAsBool("HEADER_FILE_ONLY")); + if(fc.ExcludedFromBuild) + { + needfc = true; + } + + // if the source file does not match the linker language + // then force c or c++ + if(needForceLang || (linkLanguage != lang)) + { + if(lang == "CXX") + { + // force a C++ file type + fc.CompileFlags += " /TP "; + needfc = true; + } + else if(lang == "C") + { + // force to c + fc.CompileFlags += " /TC "; + needfc = true; + } + } + + if(needfc) + { + this->FileConfigMap[*i] = fc; + } + } +} + +//---------------------------------------------------------------------------- +std::string +cmLocalVisualStudio7Generator +::ComputeLongestObjectDirectory(cmTarget& target) const +{ + std::vector<std::string> configs; + target.GetMakefile()->GetConfigurations(configs); + + // Compute the maximum length configuration name. + std::string config_max; + for(std::vector<std::string>::iterator i = configs.begin(); + i != configs.end(); ++i) + { + if(i->size() > config_max.size()) + { + config_max = *i; + } + } + + // Compute the maximum length full path to the intermediate + // files directory for any configuration. This is used to construct + // object file names that do not produce paths that are too long. + std::string dir_max; + dir_max += this->Makefile->GetCurrentBinaryDirectory(); + dir_max += "/"; + dir_max += this->GetTargetDirectory(target); + dir_max += "/"; + dir_max += config_max; + dir_max += "/"; + return dir_max; +} + +bool cmLocalVisualStudio7Generator +::WriteGroup(const cmSourceGroup *sg, cmTarget& target, + std::ostream &fout, const std::string& libName, + std::vector<std::string> const& configs) +{ + cmGlobalVisualStudio7Generator* gg = + static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator); + const std::vector<const cmSourceFile *> &sourceFiles = + sg->GetSourceFiles(); + std::vector<cmSourceGroup> const& children = sg->GetGroupChildren(); + + // Write the children to temporary output. + bool hasChildrenWithSources = false; + std::ostringstream tmpOut; + for(unsigned int i=0;i<children.size();++i) + { + if(this->WriteGroup(&children[i], target, tmpOut, libName, configs)) + { + hasChildrenWithSources = true; + } + } + + // If the group is empty, don't write it at all. + if(sourceFiles.empty() && !hasChildrenWithSources) + { + return false; + } + + // If the group has a name, write the header. + std::string name = sg->GetName(); + if(name != "") + { + this->WriteVCProjBeginGroup(fout, name.c_str(), ""); + } + + // Loop through each source in the source group. + std::string objectName; + for(std::vector<const cmSourceFile *>::const_iterator sf = + sourceFiles.begin(); sf != sourceFiles.end(); ++sf) + { + std::string source = (*sf)->GetFullPath(); + FCInfo fcinfo(this, target, *(*sf), configs); + + if (source != libName || target.GetType() == cmTarget::UTILITY || + target.GetType() == cmTarget::GLOBAL_TARGET ) + { + fout << "\t\t\t<File\n"; + std::string d = this->ConvertToXMLOutputPathSingle(source.c_str()); + // Tell MS-Dev what the source is. If the compiler knows how to + // build it, then it will. + fout << "\t\t\t\tRelativePath=\"" << d << "\">\n"; + if(cmCustomCommand const* command = (*sf)->GetCustomCommand()) + { + this->WriteCustomRule(fout, configs, source.c_str(), + *command, fcinfo); + } + else if(!fcinfo.FileConfigMap.empty()) + { + const char* aCompilerTool = "VCCLCompilerTool"; + const char* ppLang = "CXX"; + if(this->FortranProject) + { + aCompilerTool = "VFFortranCompilerTool"; + } + std::string const& lang = (*sf)->GetLanguage(); + std::string ext = (*sf)->GetExtension(); + ext = cmSystemTools::LowerCase(ext); + if(ext == "idl") + { + aCompilerTool = "VCMIDLTool"; + if(this->FortranProject) + { + aCompilerTool = "VFMIDLTool"; + } + } + if(ext == "rc") + { + aCompilerTool = "VCResourceCompilerTool"; + ppLang = "RC"; + if(this->FortranProject) + { + aCompilerTool = "VFResourceCompilerTool"; + } + } + if(ext == "def") + { + aCompilerTool = "VCCustomBuildTool"; + if(this->FortranProject) + { + aCompilerTool = "VFCustomBuildTool"; + } + } + if (gg->IsMasmEnabled() && !this->FortranProject && + lang == "ASM_MASM") + { + aCompilerTool = "MASM"; + } + for(std::map<std::string, cmLVS7GFileConfig>::const_iterator + fci = fcinfo.FileConfigMap.begin(); + fci != fcinfo.FileConfigMap.end(); ++fci) + { + cmLVS7GFileConfig const& fc = fci->second; + fout << "\t\t\t\t<FileConfiguration\n" + << "\t\t\t\t\tName=\"" << fci->first + << "|" << gg->GetPlatformName() << "\""; + if(fc.ExcludedFromBuild) + { + fout << " ExcludedFromBuild=\"true\""; + } + fout << ">\n"; + fout << "\t\t\t\t\t<Tool\n" + << "\t\t\t\t\tName=\"" << aCompilerTool << "\"\n"; + if(!fc.CompileFlags.empty() || + !fc.CompileDefs.empty() || + !fc.CompileDefsConfig.empty()) + { + Options::Tool tool = Options::Compiler; + cmVS7FlagTable const* table = + cmLocalVisualStudio7GeneratorFlagTable; + if(this->FortranProject) + { + tool = Options::FortranCompiler; + table = cmLocalVisualStudio7GeneratorFortranFlagTable; + } + Options fileOptions(this, tool, table, + gg->ExtraFlagTable); + fileOptions.Parse(fc.CompileFlags.c_str()); + fileOptions.AddDefines(fc.CompileDefs.c_str()); + fileOptions.AddDefines(fc.CompileDefsConfig.c_str()); + fileOptions.OutputAdditionalOptions(fout, "\t\t\t\t\t", "\n"); + fileOptions.OutputFlagMap(fout, "\t\t\t\t\t"); + fileOptions.OutputPreprocessorDefinitions(fout, + "\t\t\t\t\t", "\n", + ppLang); + } + if(!fc.AdditionalDeps.empty()) + { + fout << "\t\t\t\t\tAdditionalDependencies=\"" + << fc.AdditionalDeps.c_str() << "\"\n"; + } + if(!fc.ObjectName.empty()) + { + fout << "\t\t\t\t\tObjectFile=\"$(IntDir)/" + << fc.ObjectName.c_str() << "\"\n"; + } + fout << "\t\t\t\t\t/>\n" + << "\t\t\t\t</FileConfiguration>\n"; + } + } + fout << "\t\t\t</File>\n"; + } + } + + // If the group has children with source files, write the children. + if(hasChildrenWithSources) + { + fout << tmpOut.str(); + } + + // If the group has a name, write the footer. + if(name != "") + { + this->WriteVCProjEndGroup(fout); + } + + return true; +} + +void cmLocalVisualStudio7Generator:: +WriteCustomRule(std::ostream& fout, + std::vector<std::string> const& configs, + const char* source, + const cmCustomCommand& command, + FCInfo& fcinfo) +{ + cmGlobalVisualStudio7Generator* gg = + static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator); + + // Write the rule for each configuration. + const char* compileTool = "VCCLCompilerTool"; + if(this->FortranProject) + { + compileTool = "VFCLCompilerTool"; + } + const char* customTool = "VCCustomBuildTool"; + if(this->FortranProject) + { + customTool = "VFCustomBuildTool"; + } + for (std::vector<std::string>::const_iterator i = configs.begin(); + i != configs.end(); ++i) + { + cmCustomCommandGenerator ccg(command, *i, this); + cmLVS7GFileConfig const& fc = fcinfo.FileConfigMap[*i]; + fout << "\t\t\t\t<FileConfiguration\n"; + fout << "\t\t\t\t\tName=\"" << *i << "|" + << gg->GetPlatformName() << "\">\n"; + if(!fc.CompileFlags.empty()) + { + fout << "\t\t\t\t\t<Tool\n" + << "\t\t\t\t\tName=\"" << compileTool << "\"\n" + << "\t\t\t\t\tAdditionalOptions=\"" + << this->EscapeForXML(fc.CompileFlags.c_str()) << "\"/>\n"; + } + + std::string comment = this->ConstructComment(ccg); + std::string script = this->ConstructScript(ccg); + if(this->FortranProject) + { + cmSystemTools::ReplaceString(script, "$(Configuration)", i->c_str()); + } + fout << "\t\t\t\t\t<Tool\n" + << "\t\t\t\t\tName=\"" << customTool << "\"\n" + << "\t\t\t\t\tDescription=\"" + << this->EscapeForXML(comment.c_str()) << "\"\n" + << "\t\t\t\t\tCommandLine=\"" + << this->EscapeForXML(script.c_str()) << "\"\n" + << "\t\t\t\t\tAdditionalDependencies=\""; + if(ccg.GetDepends().empty()) + { + // There are no real dependencies. Produce an artificial one to + // make sure the rule runs reliably. + if(!cmSystemTools::FileExists(source)) + { + cmsys::ofstream depout(source); + depout << "Artificial dependency for a custom command.\n"; + } + fout << this->ConvertToXMLOutputPath(source); + } + else + { + // Write out the dependencies for the rule. + for(std::vector<std::string>::const_iterator d = + ccg.GetDepends().begin(); + d != ccg.GetDepends().end(); + ++d) + { + // Get the real name of the dependency in case it is a CMake target. + std::string dep; + if(this->GetRealDependency(d->c_str(), i->c_str(), dep)) + { + fout << this->ConvertToXMLOutputPath(dep.c_str()) + << ";"; + } + } + } + fout << "\"\n"; + fout << "\t\t\t\t\tOutputs=\""; + if(ccg.GetOutputs().empty()) + { + fout << source << "_force"; + } + else + { + // Write a rule for the output generated by this command. + const char* sep = ""; + for(std::vector<std::string>::const_iterator o = + ccg.GetOutputs().begin(); + o != ccg.GetOutputs().end(); + ++o) + { + fout << sep << this->ConvertToXMLOutputPathSingle(o->c_str()); + sep = ";"; + } + } + fout << "\"/>\n"; + fout << "\t\t\t\t</FileConfiguration>\n"; + } +} + + +void cmLocalVisualStudio7Generator::WriteVCProjBeginGroup(std::ostream& fout, + const char* group, + const char* ) +{ + fout << "\t\t<Filter\n" + << "\t\t\tName=\"" << group << "\"\n" + << "\t\t\tFilter=\"\">\n"; +} + + +void cmLocalVisualStudio7Generator::WriteVCProjEndGroup(std::ostream& fout) +{ + fout << "\t\t</Filter>\n"; +} + + +// look for custom rules on a target and collect them together +void cmLocalVisualStudio7Generator +::OutputTargetRules(std::ostream& fout, + const std::string& configName, + cmTarget &target, + const std::string& /*libName*/) +{ + if (target.GetType() > cmTarget::GLOBAL_TARGET) + { + return; + } + EventWriter event(this, configName, fout); + + // Add pre-build event. + const char* tool = + this->FortranProject? "VFPreBuildEventTool":"VCPreBuildEventTool"; + event.Start(tool); + event.Write(target.GetPreBuildCommands()); + event.Finish(); + + // Add pre-link event. + tool = this->FortranProject? "VFPreLinkEventTool":"VCPreLinkEventTool"; + event.Start(tool); + bool addedPrelink = false; + if (target.GetType() == cmTarget::SHARED_LIBRARY && + this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) + { + if (target.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS")) + { + addedPrelink = true; + std::vector<cmCustomCommand> commands = + target.GetPreLinkCommands(); + cmGlobalVisualStudioGenerator* gg + = static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator); + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + gg->AddSymbolExportCommand( + gt, commands, configName); + event.Write(commands); + } + } + if (!addedPrelink) + { + event.Write(target.GetPreLinkCommands()); + } + cmsys::auto_ptr<cmCustomCommand> pcc( + this->MaybeCreateImplibDir(target, configName, this->FortranProject)); + if(pcc.get()) + { + event.Write(*pcc); + } + event.Finish(); + + // Add post-build event. + tool = this->FortranProject? "VFPostBuildEventTool":"VCPostBuildEventTool"; + event.Start(tool); + event.Write(target.GetPostBuildCommands()); + event.Finish(); +} + +void cmLocalVisualStudio7Generator::WriteProjectSCC(std::ostream& fout, + cmTarget& target) +{ + // if we have all the required Source code control tags + // then add that to the project + const char* vsProjectname = target.GetProperty("VS_SCC_PROJECTNAME"); + const char* vsLocalpath = target.GetProperty("VS_SCC_LOCALPATH"); + const char* vsProvider = target.GetProperty("VS_SCC_PROVIDER"); + + if(vsProvider && vsLocalpath && vsProjectname) + { + fout << "\tSccProjectName=\"" << vsProjectname << "\"\n" + << "\tSccLocalPath=\"" << vsLocalpath << "\"\n" + << "\tSccProvider=\"" << vsProvider << "\"\n"; + + const char* vsAuxPath = target.GetProperty("VS_SCC_AUXPATH"); + if(vsAuxPath) + { + fout << "\tSccAuxPath=\"" << vsAuxPath << "\"\n"; + } + } +} + +void +cmLocalVisualStudio7Generator +::WriteProjectStartFortran(std::ostream& fout, + const std::string& libName, + cmTarget & target) +{ + + cmGlobalVisualStudio7Generator* gg = + static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator); + fout << "<?xml version=\"1.0\" encoding = \"" + << gg->Encoding() << "\"?>\n" + << "<VisualStudioProject\n" + << "\tProjectCreator=\"Intel Fortran\"\n" + << "\tVersion=\"" << gg->GetIntelProjectVersion() << "\"\n"; + const char* keyword = target.GetProperty("VS_KEYWORD"); + if(!keyword) + { + keyword = "Console Application"; + } + const char* projectType = 0; + switch(target.GetType()) + { + case cmTarget::STATIC_LIBRARY: + projectType = "typeStaticLibrary"; + if(keyword) + { + keyword = "Static Library"; + } + break; + case cmTarget::SHARED_LIBRARY: + case cmTarget::MODULE_LIBRARY: + projectType = "typeDynamicLibrary"; + if(!keyword) + { + keyword = "Dll"; + } + break; + case cmTarget::EXECUTABLE: + if(!keyword) + { + keyword = "Console Application"; + } + projectType = 0; + break; + case cmTarget::UTILITY: + case cmTarget::GLOBAL_TARGET: + default: + break; + } + if(projectType) + { + fout << "\tProjectType=\"" << projectType << "\"\n"; + } + this->WriteProjectSCC(fout, target); + fout<< "\tKeyword=\"" << keyword << "\">\n" + << "\tProjectGUID=\"{" << gg->GetGUID(libName.c_str()) << "}\">\n" + << "\t<Platforms>\n" + << "\t\t<Platform\n\t\t\tName=\"" << gg->GetPlatformName() << "\"/>\n" + << "\t</Platforms>\n"; +} + + +void +cmLocalVisualStudio7Generator::WriteProjectStart(std::ostream& fout, + const std::string& libName, + cmTarget & target, + std::vector<cmSourceGroup> &) +{ + if(this->FortranProject) + { + this->WriteProjectStartFortran(fout, libName, target); + return; + } + + cmGlobalVisualStudio7Generator* gg = + static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator); + + fout << "<?xml version=\"1.0\" encoding = \"" + << gg->Encoding() << "\"?>\n" + << "<VisualStudioProject\n" + << "\tProjectType=\"Visual C++\"\n"; + if(gg->GetVersion() == cmGlobalVisualStudioGenerator::VS71) + { + fout << "\tVersion=\"7.10\"\n"; + } + else + { + fout << "\tVersion=\"" << (gg->GetVersion()/10) << ".00\"\n"; + } + const char* projLabel = target.GetProperty("PROJECT_LABEL"); + if(!projLabel) + { + projLabel = libName.c_str(); + } + const char* keyword = target.GetProperty("VS_KEYWORD"); + if(!keyword) + { + keyword = "Win32Proj"; + } + fout << "\tName=\"" << projLabel << "\"\n"; + if(gg->GetVersion() >= cmGlobalVisualStudioGenerator::VS8) + { + fout << "\tProjectGUID=\"{" << gg->GetGUID(libName.c_str()) << "}\"\n"; + } + this->WriteProjectSCC(fout, target); + if(const char* targetFrameworkVersion = + target.GetProperty("VS_DOTNET_TARGET_FRAMEWORK_VERSION")) + { + fout << "\tTargetFrameworkVersion=\"" << targetFrameworkVersion << "\"\n"; + } + fout << "\tKeyword=\"" << keyword << "\">\n" + << "\t<Platforms>\n" + << "\t\t<Platform\n\t\t\tName=\"" << gg->GetPlatformName() << "\"/>\n" + << "\t</Platforms>\n"; + if(gg->IsMasmEnabled()) + { + fout << + "\t<ToolFiles>\n" + "\t\t<DefaultToolFile\n" + "\t\t\tFileName=\"masm.rules\"\n" + "\t\t/>\n" + "\t</ToolFiles>\n" + ; + } +} + + +void cmLocalVisualStudio7Generator::WriteVCProjFooter(std::ostream& fout, + cmTarget &target) +{ + fout << "\t<Globals>\n"; + + cmPropertyMap const& props = target.GetProperties(); + for(cmPropertyMap::const_iterator i = props.begin(); i != props.end(); ++i) + { + if(i->first.find("VS_GLOBAL_") == 0) + { + std::string name = i->first.substr(10); + if(name != "") + { + fout << "\t\t<Global\n" + << "\t\t\tName=\"" << name << "\"\n" + << "\t\t\tValue=\"" << i->second.GetValue() << "\"\n" + << "\t\t/>\n"; + } + } + } + + fout << "\t</Globals>\n" + << "</VisualStudioProject>\n"; +} + +std::string cmLocalVisualStudio7GeneratorEscapeForXML(const std::string& s) +{ + std::string ret = s; + cmSystemTools::ReplaceString(ret, "&", "&"); + cmSystemTools::ReplaceString(ret, "\"", """); + cmSystemTools::ReplaceString(ret, "<", "<"); + cmSystemTools::ReplaceString(ret, ">", ">"); + cmSystemTools::ReplaceString(ret, "\n", "
"); + return ret; +} + +std::string cmLocalVisualStudio7Generator::EscapeForXML(const std::string& s) +{ + return cmLocalVisualStudio7GeneratorEscapeForXML(s); +} + +std::string cmLocalVisualStudio7Generator +::ConvertToXMLOutputPath(const char* path) +{ + std::string ret = this->ConvertToOutputFormat(path, SHELL); + cmSystemTools::ReplaceString(ret, "&", "&"); + cmSystemTools::ReplaceString(ret, "\"", """); + cmSystemTools::ReplaceString(ret, "<", "<"); + cmSystemTools::ReplaceString(ret, ">", ">"); + return ret; +} + +std::string cmLocalVisualStudio7Generator +::ConvertToXMLOutputPathSingle(const char* path) +{ + std::string ret = this->ConvertToOutputFormat(path, SHELL); + cmSystemTools::ReplaceString(ret, "\"", ""); + cmSystemTools::ReplaceString(ret, "&", "&"); + cmSystemTools::ReplaceString(ret, "<", "<"); + cmSystemTools::ReplaceString(ret, ">", ">"); + return ret; +} + + +// This class is used to parse an existing vs 7 project +// and extract the GUID +class cmVS7XMLParser : public cmXMLParser +{ +public: + virtual void EndElement(const std::string& /* name */) + { + } + virtual void StartElement(const std::string& name, const char** atts) + { + // once the GUID is found do nothing + if(!this->GUID.empty()) + { + return; + } + int i =0; + if("VisualStudioProject" == name) + { + while(atts[i]) + { + if(strcmp(atts[i], "ProjectGUID") == 0) + { + if(atts[i+1]) + { + this->GUID = atts[i+1]; + this->GUID = this->GUID.substr(1, this->GUID.size()-2); + } + else + { + this->GUID = ""; + } + return; + } + ++i; + } + } + } + int InitializeParser() + { + int ret = cmXMLParser::InitializeParser(); + if(ret == 0) + { + return ret; + } + // visual studio projects have a strange encoding, but it is + // really utf-8 + XML_SetEncoding(static_cast<XML_Parser>(this->Parser), "utf-8"); + return 1; + } + std::string GUID; +}; + +void cmLocalVisualStudio7Generator::ReadAndStoreExternalGUID( + const std::string& name, + const char* path) +{ + cmVS7XMLParser parser; + parser.ParseFile(path); + // if we can not find a GUID then we will generate one later + if(parser.GUID.empty()) + { + return; + } + std::string guidStoreName = name; + guidStoreName += "_GUID_CMAKE"; + // save the GUID in the cache + this->GlobalGenerator->GetCMakeInstance()-> + AddCacheEntry(guidStoreName.c_str(), + parser.GUID.c_str(), + "Stored GUID", + cmState::INTERNAL); +} + + +//---------------------------------------------------------------------------- +std::string cmLocalVisualStudio7Generator +::GetTargetDirectory(cmTarget const& target) const +{ + std::string dir; + dir += target.GetName(); + dir += ".dir"; + return dir; +} + +//---------------------------------------------------------------------------- +#include <windows.h> +static bool cmLVS6G_IsFAT(const char* dir) +{ + if(dir[0] && dir[1] == ':') + { + char volRoot[4] = "_:/"; + volRoot[0] = dir[0]; + char fsName[16]; + if(GetVolumeInformationA(volRoot, 0, 0, 0, 0, 0, fsName, 16) && + strstr(fsName, "FAT") != 0) + { + return true; + } + } + return false; +} |