diff options
Diffstat (limited to 'Source/cmLocalVisualStudio7Generator.cxx')
-rw-r--r-- | Source/cmLocalVisualStudio7Generator.cxx | 2154 |
1 files changed, 2154 insertions, 0 deletions
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx new file mode 100644 index 0000000..e72abe9 --- /dev/null +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -0,0 +1,2154 @@ +/*============================================================================ + 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 "cmLocalVisualStudio7Generator.h" + +#include "cmCustomCommandGenerator.h" +#include "cmGeneratorTarget.h" +#include "cmGlobalVisualStudio7Generator.h" +#include "cmMakefile.h" +#include "cmSourceFile.h" +#include "cmSystemTools.h" +#include "cmXMLParser.h" +#include "cmake.h" +#include <cm_expat.h> + +#include "cmComputeLinkInformation.h" +#include "cmGeneratedFileStream.h" + +#include <ctype.h> // for isspace + +static bool cmLVS7G_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, cmGeneratorTarget* 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 + std::vector<cmGeneratorTarget*> tgts = this->GetGeneratorTargets(); + for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin(); + l != tgts.end(); ++l) { + if ((*l)->GetType() == cmState::INTERFACE_LIBRARY) { + continue; + } + const char* path = (*l)->GetProperty("EXTERNAL_MSPROJECT"); + if (path) { + this->ReadAndStoreExternalGUID((*l)->GetName().c_str(), path); + } + } + + this->FixGlobalTargets(); +} + +void cmLocalVisualStudio7Generator::Generate() +{ + this->WriteProjectFiles(); + this->WriteStampFiles(); +} + +void cmLocalVisualStudio7Generator::AddCMakeListsRules() +{ + // 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. + std::vector<cmGeneratorTarget*> tgts = this->GetGeneratorTargets(); + for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin(); + l != tgts.end(); ++l) { + if ((*l)->GetType() == cmState::GLOBAL_TARGET) { + continue; + } + if ((*l)->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) { + (*l)->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. + std::vector<cmGeneratorTarget*> tgts = this->GetGeneratorTargets(); + for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin(); + l != tgts.end(); l++) { + if ((*l)->GetType() == cmState::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->GetCurrentBinaryDirectory(); + force += cmake::GetCMakeFilesDirectory(); + force += "/"; + force += (*l)->GetName(); + force += "_force"; + if (cmSourceFile* file = this->Makefile->AddCustomCommandToOutput( + force.c_str(), no_depends, no_main_dependency, force_commands, " ", + 0, true)) { + (*l)->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->GetCurrentBinaryDirectory(), this->GetSourceDirectory()) != + 0) { + if (!cmSystemTools::MakeDirectory(this->GetCurrentBinaryDirectory())) { + cmSystemTools::Error("Error creating directory ", + this->GetCurrentBinaryDirectory()); + } + } + + // Get the set of targets in this directory. + std::vector<cmGeneratorTarget*> tgts = this->GetGeneratorTargets(); + + // Create the project file for each target. + for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin(); + l != tgts.end(); l++) { + if ((*l)->GetType() == cmState::INTERFACE_LIBRARY) { + continue; + } + // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace + // so don't build a projectfile for it + if (!(*l)->GetProperty("EXTERNAL_MSPROJECT")) { + this->CreateSingleVCProj((*l)->GetName().c_str(), *l); + } + } +} + +void cmLocalVisualStudio7Generator::WriteStampFiles() +{ + // Touch a timestamp file used to determine when the project file is + // out of date. + std::string stampName = this->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, cmGeneratorTarget* 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->Target->SetProperty("GENERATOR_FILE_NAME", lname.c_str()); + // create the dsp.cmake file + std::string fname; + fname = this->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->GetCurrentBinaryDirectory(); + stampName += "/"; + stampName += cmake::GetCMakeFilesDirectoryPostSlash(); + stampName += "generate.stamp"; + cmCustomCommandLine commandLine; + commandLine.push_back(cmSystemTools::GetCMakeCommand()); + std::string makefileIn = this->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->GetSourceDirectory(); + commandLine.push_back(args); + args = "-B"; + args += this->GetBinaryDirectory(); + commandLine.push_back(args); + commandLine.push_back("--check-stamp-file"); + std::string stampFilename = this->Convert( + stampName.c_str(), cmOutputConverter::FULL, cmOutputConverter::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(), cmOutputConverter::FULL, cmOutputConverter::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, cmGeneratorTarget* 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 }, + + { "MultiProcessorCompilation", "MP", "", "true", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, + { "ProcessorNumber", "MP", "Multi-processor Compilation", "", + cmVS7FlagTable::UserValueRequired }, + + { "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, cmGeneratorTarget* 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; + + switch (target->GetType()) { + case cmState::OBJECT_LIBRARY: + targetBuilds = false; // no manifest tool for object library + case cmState::STATIC_LIBRARY: + projectType = "typeStaticLibrary"; + configType = "4"; + break; + case cmState::SHARED_LIBRARY: + case cmState::MODULE_LIBRARY: + projectType = "typeDynamicLibrary"; + configType = "2"; + break; + case cmState::EXECUTABLE: + configType = "1"; + break; + case cmState::UTILITY: + case cmState::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") + : target->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 (cmOutputConverter::GetFortranFormat( + target->GetProperty("Fortran_FORMAT"))) { + case cmOutputConverter::FortranFormatFixed: + flags += " -fixed"; + break; + case cmOutputConverter::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; + target->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() < cmState::UTILITY) { + std::string const& outDir = target->GetType() == cmState::OBJECT_LIBRARY + ? intermediateDir + : target->GetDirectory(configName); + /* clang-format off */ + fout << "\t\t\tOutputDirectory=\"" + << this->ConvertToXMLOutputPathSingle(outDir.c_str()) << "\"\n"; + /* clang-format on */ + } + + /* clang-format off */ + 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"; + /* clang-format on */ + + if (this->FortranProject) { + // Intel Fortran >= 15.0 uses TargetName property. + std::string targetNameFull = target->GetFullName(configName); + std::string targetName = + cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull); + std::string targetExt = + cmSystemTools::GetFilenameLastExtension(targetNameFull); + /* clang-format off */ + fout << + "\t\t\tTargetName=\"" << this->EscapeForXML(targetName) << "\"\n" + "\t\t\tTargetExt=\"" << this->EscapeForXML(targetExt) << "\"\n" + ; + /* clang-format on */ + } + + // 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, cmOutputConverter::START_OUTPUT, + cmOutputConverter::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, target, "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() <= cmState::OBJECT_LIBRARY) { + // Specify the compiler program database file if configured. + std::string pdb = target->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); + /* clang-format off */ + fout << + "\t\t\t<Tool\n" + "\t\t\t\tName=\"MASM\"\n" + "\t\t\t\tIncludePaths=\"" + ; + /* clang-format on */ + 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"); + /* clang-format off */ + fout << + "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n" + "\t\t\t/>\n"; + /* clang-format on */ + } + 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"; + } + /* clang-format off */ + fout << + "\t\t\t<Tool\n" + "\t\t\t\tName=\"" << manifestTool << "\""; + /* clang-format on */ + + std::vector<cmSourceFile const*> manifest_srcs; + target->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 (cmLVS7G_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); + this->OutputDeploymentDebuggerTool(fout, configName, target); + 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, cmGeneratorTarget* target, + const Options& targetOptions) +{ + cmGlobalVisualStudio7Generator* gg = + static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator); + std::string temp; + std::string extraLinkOptions; + if (target->GetType() == cmState::EXECUTABLE) { + extraLinkOptions = + this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS") + + std::string(" ") + + GetBuildTypeLinkerFlags("CMAKE_EXE_LINKER_FLAGS", configName); + } + if (target->GetType() == cmState::SHARED_LIBRARY) { + extraLinkOptions = + this->Makefile->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS") + + std::string(" ") + + GetBuildTypeLinkerFlags("CMAKE_SHARED_LINKER_FLAGS", configName); + } + if (target->GetType() == cmState::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, cmOutputConverter::SHELL); + linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str()); + } + + if ((target->GetType() == cmState::SHARED_LIBRARY || + target->IsExecutableWithExports()) && + 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 cmState::UNKNOWN_LIBRARY: + break; + case cmState::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 cmState::STATIC_LIBRARY: { + std::string targetNameFull = target->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 cmState::SHARED_LIBRARY: + case cmState::MODULE_LIBRARY: { + std::string targetName; + std::string targetNameSO; + std::string targetNameFull; + std::string targetNameImport; + std::string targetNamePDB; + target->GetLibraryNames(targetName, targetNameSO, targetNameFull, + targetNameImport, targetNamePDB, configName); + + // Compute the link library and directory information. + cmComputeLinkInformation* pcli = target->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 cmState::EXECUTABLE: { + std::string targetName; + std::string targetNameFull; + std::string targetNameImport; + std::string targetNamePDB; + target->GetExecutableNames(targetName, targetNameFull, targetNameImport, + targetNamePDB, configName); + + // Compute the link library and directory information. + cmComputeLinkInformation* pcli = target->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 cmState::UTILITY: + case cmState::GLOBAL_TARGET: + case cmState::INTERFACE_LIBRARY: + break; + } +} + +void cmLocalVisualStudio7Generator::OutputDeploymentDebuggerTool( + std::ostream& fout, std::string const& config, cmGeneratorTarget* target) +{ + if (this->WindowsCEProject) { + if (const char* dir = target->GetProperty("DEPLOYMENT_REMOTE_DIRECTORY")) { + /* clang-format off */ + fout << + "\t\t\t<DeploymentTool\n" + "\t\t\t\tForceDirty=\"-1\"\n" + "\t\t\t\tRemoteDirectory=\"" << this->EscapeForXML(dir) << "\"\n" + "\t\t\t\tRegisterOutput=\"0\"\n" + "\t\t\t\tAdditionalFiles=\"\"/>\n" + ; + /* clang-format on */ + std::string const exe = + dir + std::string("\\") + target->GetFullName(config); + /* clang-format off */ + fout << + "\t\t\t<DebuggerTool\n" + "\t\t\t\tRemoteExecutable=\"" << this->EscapeForXML(exe) << "\"\n" + "\t\t\t\tArguments=\"\"\n" + "\t\t\t/>\n" + ; + /* clang-format on */ + } + } +} + +void cmLocalVisualStudio7Generator::WriteTargetVersionAttribute( + std::ostream& fout, cmGeneratorTarget* gt) +{ + int major; + int minor; + gt->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(), cmOutputConverter::START_OUTPUT, + cmOutputConverter::UNCHANGED); + fout << lg->ConvertToXMLOutputPath(rel.c_str()) << " "; + } else if (!l->Target || + l->Target->GetType() != cmState::INTERFACE_LIBRARY) { + fout << l->Value << " "; + } + } +} + +void cmLocalVisualStudio7GeneratorInternals::OutputObjects( + std::ostream& fout, cmGeneratorTarget* gt, 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; + 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(), cmOutputConverter::START_OUTPUT, + cmOutputConverter::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(), cmOutputConverter::START_OUTPUT, + cmOutputConverter::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, + cmGeneratorTarget* 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(); + + // get the classes from the source lists then add them to the groups + this->ModuleDefinitionFile = ""; + std::vector<cmSourceFile*> classes; + if (!target->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; + target->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, + cmGeneratorTarget* target, + cmSourceFile const& sf, + std::vector<std::string> const& configs); + std::map<std::string, cmLVS7GFileConfig> FileConfigMap; +}; + +cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( + cmLocalVisualStudio7Generator* lg, cmGeneratorTarget* gt, + cmSourceFile const& sf, std::vector<std::string> const& configs) +{ + 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 (cmOutputConverter::GetFortranFormat( + sf.GetProperty("Fortran_FORMAT"))) { + case cmOutputConverter::FortranFormatFixed: + fc.CompileFlags = "-fixed " + fc.CompileFlags; + needfc = true; + break; + case cmOutputConverter::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( + cmGeneratorTarget const* target) const +{ + std::vector<std::string> configs; + target->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->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, cmGeneratorTarget* 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. + 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() == cmState::UTILITY || + target->GetType() == cmState::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 + << "\"\n"; + } + if (!fc.ObjectName.empty()) { + fout << "\t\t\t\t\tObjectFile=\"$(IntDir)/" << fc.ObjectName + << "\"\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()); + } + /* clang-format off */ + 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=\""; + /* clang-format on */ + 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*) +{ + /* clang-format off */ + fout << "\t\t<Filter\n" + << "\t\t\tName=\"" << group << "\"\n" + << "\t\t\tFilter=\"\">\n"; + /* clang-format on */ +} + +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, cmGeneratorTarget* target, + const std::string& /*libName*/) +{ + if (target->GetType() > cmState::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() == cmState::SHARED_LIBRARY || + target->IsExecutableWithExports()) && + 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); + gg->AddSymbolExportCommand(target, commands, configName); + event.Write(commands); + } + } + if (!addedPrelink) { + event.Write(target->GetPreLinkCommands()); + } + CM_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, + cmGeneratorTarget* 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) { + /* clang-format off */ + fout << "\tSccProjectName=\"" << vsProjectname << "\"\n" + << "\tSccLocalPath=\"" << vsLocalpath << "\"\n" + << "\tSccProvider=\"" << vsProvider << "\"\n"; + /* clang-format on */ + + const char* vsAuxPath = target->GetProperty("VS_SCC_AUXPATH"); + if (vsAuxPath) { + fout << "\tSccAuxPath=\"" << vsAuxPath << "\"\n"; + } + } +} + +void cmLocalVisualStudio7Generator::WriteProjectStartFortran( + std::ostream& fout, const std::string& libName, cmGeneratorTarget* target) +{ + + cmGlobalVisualStudio7Generator* gg = + static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator); + /* clang-format off */ + fout << "<?xml version=\"1.0\" encoding = \"" + << gg->Encoding() << "\"?>\n" + << "<VisualStudioProject\n" + << "\tProjectCreator=\"Intel Fortran\"\n" + << "\tVersion=\"" << gg->GetIntelProjectVersion() << "\"\n"; + /* clang-format on */ + const char* keyword = target->GetProperty("VS_KEYWORD"); + if (!keyword) { + keyword = "Console Application"; + } + const char* projectType = 0; + switch (target->GetType()) { + case cmState::STATIC_LIBRARY: + projectType = "typeStaticLibrary"; + if (keyword) { + keyword = "Static Library"; + } + break; + case cmState::SHARED_LIBRARY: + case cmState::MODULE_LIBRARY: + projectType = "typeDynamicLibrary"; + if (!keyword) { + keyword = "Dll"; + } + break; + case cmState::EXECUTABLE: + if (!keyword) { + keyword = "Console Application"; + } + projectType = 0; + break; + case cmState::UTILITY: + case cmState::GLOBAL_TARGET: + default: + break; + } + if (projectType) { + fout << "\tProjectType=\"" << projectType << "\"\n"; + } + this->WriteProjectSCC(fout, target); + /* clang-format off */ + 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"; + /* clang-format on */ +} + +void cmLocalVisualStudio7Generator::WriteProjectStart( + std::ostream& fout, const std::string& libName, cmGeneratorTarget* target, + std::vector<cmSourceGroup>&) +{ + if (this->FortranProject) { + this->WriteProjectStartFortran(fout, libName, target); + return; + } + + cmGlobalVisualStudio7Generator* gg = + static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator); + + /* clang-format off */ + fout << "<?xml version=\"1.0\" encoding = \"" + << gg->Encoding() << "\"?>\n" + << "<VisualStudioProject\n" + << "\tProjectType=\"Visual C++\"\n"; + /* clang-format on */ + 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"; + } + /* clang-format off */ + fout << "\tKeyword=\"" << keyword << "\">\n" + << "\t<Platforms>\n" + << "\t\t<Platform\n\t\t\tName=\"" << gg->GetPlatformName() << "\"/>\n" + << "\t</Platforms>\n"; + /* clang-format on */ + if (gg->IsMasmEnabled()) { + /* clang-format off */ + fout << + "\t<ToolFiles>\n" + "\t\t<DefaultToolFile\n" + "\t\t\tFileName=\"masm.rules\"\n" + "\t\t/>\n" + "\t</ToolFiles>\n" + ; + /* clang-format on */ + } +} + +void cmLocalVisualStudio7Generator::WriteVCProjFooter( + std::ostream& fout, cmGeneratorTarget* target) +{ + fout << "\t<Globals>\n"; + + std::vector<std::string> const& props = target->GetPropertyKeys(); + for (std::vector<std::string>::const_iterator i = props.begin(); + i != props.end(); ++i) { + if (i->find("VS_GLOBAL_") == 0) { + std::string name = i->substr(10); + if (name != "") { + /* clang-format off */ + fout << "\t\t<Global\n" + << "\t\t\tName=\"" << name << "\"\n" + << "\t\t\tValue=\"" << target->GetProperty(*i) << "\"\n" + << "\t\t/>\n"; + /* clang-format on */ + } + } + } + + 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, cmOutputConverter::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, cmOutputConverter::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( + cmGeneratorTarget const* target) const +{ + std::string dir; + dir += target->GetName(); + dir += ".dir"; + return dir; +} + +#include <windows.h> +static bool cmLVS7G_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; +} |