diff options
Diffstat (limited to 'Source/cmLocalVisualStudio7Generator.cxx')
-rw-r--r-- | Source/cmLocalVisualStudio7Generator.cxx | 2253 |
1 files changed, 2253 insertions, 0 deletions
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx new file mode 100644 index 0000000..e7badf0 --- /dev/null +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -0,0 +1,2253 @@ +/*============================================================================ + 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 "cmCacheManager.h" +#include "cmGeneratorTarget.h" +#include "cmake.h" + +#include "cmComputeLinkInformation.h" +#include "cmGeneratedFileStream.h" + +#include <cmsys/System.h> + +#include <ctype.h> // for isspace + +// Package GUID of Intel Visual Fortran plugin to VS IDE +#define CM_INTEL_PLUGIN_GUID "{B68A201D-CB9B-47AF-A52F-7EEC72E217E4}" + +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[]; + +//---------------------------------------------------------------------------- +cmLocalVisualStudio7Generator::cmLocalVisualStudio7Generator(VSVersion v): + cmLocalVisualStudioGenerator(v) +{ + this->PlatformName = "Win32"; + this->ExtraFlagTable = 0; + this->Internal = new cmLocalVisualStudio7GeneratorInternals(this); +} + +cmLocalVisualStudio7Generator::~cmLocalVisualStudio7Generator() +{ + delete this->Internal; +} + +void cmLocalVisualStudio7Generator::AddHelperCommands() +{ + std::set<cmStdString> lang; + lang.insert("C"); + lang.insert("CXX"); + lang.insert("RC"); + lang.insert("IDL"); + lang.insert("DEF"); + lang.insert("Fortran"); + this->CreateCustomTargetsAndCommands(lang); + + // Now create GUIDs for targets + cmTargets &tgts = this->Makefile->GetTargets(); + + cmGlobalVisualStudio7Generator* gg = + static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator); + for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++) + { + const char* path = l->second.GetProperty("EXTERNAL_MSPROJECT"); + if(path) + { + this->ReadAndStoreExternalGUID( + l->second.GetName(), path); + } + else + { + gg->CreateGUID(l->first.c_str()); + } + } + + + 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->first != CMAKE_CHECK_BUILD_SYSTEM_TARGET) + { + l->second.AddSourceFile(sf); + } + } + } + } +} + +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); + const char* no_main_dependency = 0; + std::string force = this->Makefile->GetStartOutputDirectory(); + force += cmake::GetCMakeFilesDirectory(); + force += "/"; + force += tgt.GetName(); + force += "_force"; + this->Makefile->AddCustomCommandToOutput(force.c_str(), no_depends, + no_main_dependency, + force_commands, " ", 0, true); + if(cmSourceFile* file = + this->Makefile->GetSourceFileWithOutput(force.c_str())) + { + tgt.AddSourceFile(file); + } + } + } +} + +// 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->GetStartOutputDirectory(), + this->Makefile->GetHomeDirectory()) != 0) + { + if(!cmSystemTools::MakeDirectory + (this->Makefile->GetStartOutputDirectory())) + { + cmSystemTools::Error("Error creating directory ", + this->Makefile->GetStartOutputDirectory()); + } + } + + // 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++) + { + // 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->GetStartOutputDirectory(); + stampName += cmake::GetCMakeFilesDirectory(); + cmSystemTools::MakeDirectory(stampName.c_str()); + stampName += "/"; + stampName += "generate.stamp"; + std::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"; + std::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 char *lname, cmTarget &target) +{ + this->FortranProject = + static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator) + ->TargetIsFortranOnly(target); + this->WindowsCEProject = + static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator) + ->TargetsWindowsCE(); + + // Intel Fortran for VS10 uses VS9 format ".vfproj" files. + VSVersion realVersion = this->Version; + if(this->FortranProject && this->Version >= VS10) + { + this->Version = VS9; + } + + // add to the list of projects + std::string pname = lname; + target.SetProperty("GENERATOR_FILE_NAME",lname); + // create the dsp.cmake file + std::string fname; + fname = this->Makefile->GetStartOutputDirectory(); + 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); + } + + this->Version = realVersion; +} + +//---------------------------------------------------------------------------- +cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() +{ + std::string stampName = this->Makefile->GetCurrentOutputDirectory(); + stampName += "/"; + stampName += cmake::GetCMakeFilesDirectoryPostSlash(); + stampName += "generate.stamp"; + const char* dsprule = + this->Makefile->GetRequiredDefinition("CMAKE_COMMAND"); + cmCustomCommandLine commandLine; + commandLine.push_back(dsprule); + std::string makefileIn = this->Makefile->GetStartDirectory(); + 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->Convert(this->Makefile->GetHomeDirectory(), + START_OUTPUT, UNCHANGED, true); + commandLine.push_back(args); + args = "-B"; + args += + this->Convert(this->Makefile->GetHomeOutputDirectory(), + START_OUTPUT, UNCHANGED, true); + 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, + const char *libName, + cmTarget &target) +{ + std::vector<std::string> *configs = + static_cast<cmGlobalVisualStudio7Generator *> + (this->GlobalGenerator)->GetConfigurations(); + + fout << "\t<Configurations>\n"; + for( std::vector<std::string>::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}, + + {"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}, + + // 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} +}; + +//---------------------------------------------------------------------------- +// Helper class to write build event <Tool .../> elements. +class cmLocalVisualStudio7Generator::EventWriter +{ +public: + EventWriter(cmLocalVisualStudio7Generator* lg, + const char* 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) + { + if(this->First) + { + const char* comment = cc.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(cc, this->Config); + this->Stream << this->LG->EscapeForXML(script.c_str()); + } +private: + cmLocalVisualStudio7Generator* LG; + const char* Config; + std::ostream& Stream; + bool First; +}; + +//---------------------------------------------------------------------------- +void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, + const char* configName, + const char *libName, + cmTarget &target) +{ + const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG"); + if(!mfcFlag) + { + mfcFlag = "0"; + } + fout << "\t\t<Configuration\n" + << "\t\t\tName=\"" << configName << "|" << this->PlatformName << "\"\n" + << "\t\t\tOutputDirectory=\"" << configName << "\"\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 cmTarget::OBJECT_LIBRARY: + targetBuilds = false; // TODO: PDB 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 char* linkLanguage = (this->FortranProject? "Fortran": + target.GetLinkerLanguage(configName)); + if(!linkLanguage) + { + cmSystemTools::Error + ("CMake can not determine linker language for target:", + target.GetName()); + return; + } + if(strcmp(linkLanguage, "C") == 0 || strcmp(linkLanguage, "CXX") == 0 + || strcmp(linkLanguage, "Fortran") == 0) + { + 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(strcmp(linkLanguage, "C") == 0) + { + flags += " /TC "; + } + if(strcmp(linkLanguage, "CXX") == 0) + { + flags += " /TP "; + } + } + + if(this->FortranProject) + { + switch(this->GetFortranFormat(target.GetProperty("Fortran_FORMAT"))) + { + case FortranFormatFixed: flags += " -fixed"; break; + case FortranFormatFree: flags += " -free"; break; + default: break; + } + } + + std::string targetFlags; + this->GetCompileOptions(targetFlags, &target, configName); + // Add the target-specific flags. + if(!targetFlags.empty()) + { + flags += " "; + flags += targetFlags; + } + + // 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, + this->ExtraFlagTable); + targetOptions.FixExceptionHandlingDefault(); + std::string asmLocation = std::string(configName) + "/"; + targetOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str()); + targetOptions.Parse(flags.c_str()); + targetOptions.Parse(defineFlags.c_str()); + targetOptions.ParseFinish(); + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + targetOptions.AddDefines(target.GetCompileDefinitions(configName).c_str()); + 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; + 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 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"; + fout << "/>\n"; // end of <Tool Name=VCCLCompilerTool + 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( this->PlatformName == "x64" ) + { + fout << "\t\t\t\tTargetEnvironment=\"3\"\n"; + } + else if( this->PlatformName == "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 + + // Check if we need the FAT32 workaround. + if(targetBuilds && this->Version >= VS8) + { + // 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. + const char* manifestTool = "VCManifestTool"; + if(this->FortranProject) + { + manifestTool = "VFManifestTool"; + } + fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << manifestTool << "\"\n" + << "\t\t\t\tUseFAT32Workaround=\"true\"\n" + << "\t\t\t/>\n"; + } + } + + this->OutputTargetRules(fout, configName, target, libName); + this->OutputBuildTool(fout, configName, target, targetOptions.IsDebug()); + fout << "\t\t</Configuration>\n"; +} + +//---------------------------------------------------------------------------- +std::string +cmLocalVisualStudio7Generator +::GetBuildTypeLinkerFlags(std::string rootLinkerFlags, const char* 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 char* configName, + cmTarget &target, + bool isDebug) +{ + 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, + cmLocalVisualStudio7GeneratorLinkFlagTable); + linkOptions.Parse(extraLinkOptions.c_str()); + if(!this->ModuleDefinitionFile.empty()) + { + std::string defFile = + this->ConvertToXMLOutputPath(this->ModuleDefinitionFile.c_str()); + linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str()); + } + 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 = 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() < VS8) + { + cmOStringStream libdeps; + this->Internal->OutputObjects(libdeps, &target); + if(!libdeps.str().empty()) + { + fout << "\t\t\t\tAdditionalDependencies=\"" << libdeps.str() << "\"\n"; + } + } + std::string libflags; + if(const char* flags = target.GetProperty("STATIC_LIBRARY_FLAGS")) + { + libflags += flags; + } + std::string libFlagsConfig = "STATIC_LIBRARY_FLAGS_"; + libFlagsConfig += configTypeUpper; + if(const char* flagsConfig = target.GetProperty(libFlagsConfig.c_str())) + { + libflags += " "; + libflags += flagsConfig; + } + 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; + 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; + const char* 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() < VS8) + { + 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(isDebug) + { + fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n"; + } + if(this->WindowsCEProject) + { + if(this->GetVersion() < 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; + 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; + const char* 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() < VS8) + { + 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(isDebug) + { + fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n"; + } + if ( this->WindowsCEProject ) + { + if(this->GetVersion() < VS9) + { + fout << "\t\t\t\tSubSystem=\"9\"\n"; + } + else + { + fout << "\t\t\t\tSubSystem=\"8\"\n"; + } + fout << "\t\t\t\tEntryPointSymbol=\"" + << (isWin32Executable ? "WinMainCRTStartup" : "mainACRTStartup") + << "\"\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: + 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 + { + 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+"/$(OutDir)").c_str()) + << "," << this->ConvertToXMLOutputPath(dir.c_str()); + comma = ","; + } +} + +void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, + const char *libName, + cmTarget &target) +{ + // get the configurations + std::vector<std::string> *configs = + static_cast<cmGlobalVisualStudio7Generator *> + (this->GlobalGenerator)->GetConfigurations(); + + // 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*>const & classes = target.GetSourceFiles(); + for(std::vector<cmSourceFile*>::const_iterator i = classes.begin(); + i != classes.end(); i++) + { + // 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, 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() >= VS8) + { + // VS >= 8 support per-config source locations so we + // list object library content as external objects. + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + 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>* configs); + std::map<cmStdString, cmLVS7GFileConfig> FileConfigMap; +}; + +cmLocalVisualStudio7GeneratorFCInfo +::cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg, + cmTarget& target, + cmSourceFile const& sf, + std::vector<std::string>* configs) +{ + cmGeneratorTarget* gt = + lg->GetGlobalGenerator()->GetGeneratorTarget(&target); + std::string objectName; + if(gt->ExplicitObjectName.find(&sf) != gt->ExplicitObjectName.end()) + { + objectName = gt->Objects[&sf]; + } + + // Compute per-source, per-config information. + for(std::vector<std::string>::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; + } + } + + const char* lang = + lg->GlobalGenerator->GetLanguageFromExtension + (sf.GetExtension().c_str()); + const char* sourceLang = lg->GetSourceFileLanguage(sf); + const char* linkLanguage = target.GetLinkerLanguage(i->c_str()); + bool needForceLang = false; + // source file does not match its extension language + if(lang && sourceLang && strcmp(lang, sourceLang) != 0) + { + 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 + && strcmp(lang, linkLanguage) != 0)) + { + if(strcmp(lang, "CXX") == 0) + { + // force a C++ file type + fc.CompileFlags += " /TP "; + needfc = true; + } + else if(strcmp(lang, "C") == 0) + { + // 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 = + static_cast<cmGlobalVisualStudio7Generator *> + (this->GlobalGenerator)->GetConfigurations(); + // 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->GetCurrentOutputDirectory(); + 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 char *libName, + std::vector<std::string> *configs) +{ + const std::vector<const cmSourceFile *> &sourceFiles = + sg->GetSourceFiles(); + std::vector<cmSourceGroup> const& children = sg->GetGroupChildren(); + + // Write the children to temporary output. + bool hasChildrenWithSources = false; + cmOStringStream 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, source.c_str(), *command, fcinfo); + } + else if(!fcinfo.FileConfigMap.empty()) + { + const char* aCompilerTool = "VCCLCompilerTool"; + const char* lang = "CXX"; + if(this->FortranProject) + { + aCompilerTool = "VFFortranCompilerTool"; + } + std::string ext = (*sf)->GetExtension(); + ext = cmSystemTools::LowerCase(ext); + if(ext == "idl") + { + aCompilerTool = "VCMIDLTool"; + if(this->FortranProject) + { + aCompilerTool = "VFMIDLTool"; + } + } + if(ext == "rc") + { + aCompilerTool = "VCResourceCompilerTool"; + lang = "RC"; + if(this->FortranProject) + { + aCompilerTool = "VFResourceCompilerTool"; + } + } + if(ext == "def") + { + aCompilerTool = "VCCustomBuildTool"; + if(this->FortranProject) + { + aCompilerTool = "VFCustomBuildTool"; + } + } + for(std::map<cmStdString, 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 + << "|" << this->PlatformName << "\""; + 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, + this->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", + lang); + } + 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, + const char* source, + const cmCustomCommand& command, + FCInfo& fcinfo) +{ + std::string comment = this->ConstructComment(command); + + // Write the rule for each configuration. + std::vector<std::string>::iterator i; + std::vector<std::string> *configs = + static_cast<cmGlobalVisualStudio7Generator *> + (this->GlobalGenerator)->GetConfigurations(); + const char* compileTool = "VCCLCompilerTool"; + if(this->FortranProject) + { + compileTool = "VFCLCompilerTool"; + } + const char* customTool = "VCCustomBuildTool"; + if(this->FortranProject) + { + customTool = "VFCustomBuildTool"; + } + for(i = configs->begin(); i != configs->end(); ++i) + { + cmLVS7GFileConfig const& fc = fcinfo.FileConfigMap[*i]; + fout << "\t\t\t\t<FileConfiguration\n"; + fout << "\t\t\t\t\tName=\"" << *i << "|" << this->PlatformName << "\">\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 script = this->ConstructScript(command, i->c_str()); + 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(command.GetDepends().empty()) + { + // There are no real dependencies. Produce an artificial one to + // make sure the rule runs reliably. + if(!cmSystemTools::FileExists(source)) + { + std::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 = + command.GetDepends().begin(); + d != command.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(command.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 = + command.GetOutputs().begin(); + o != command.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 char* configName, + cmTarget &target, + const char * /*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); + 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 char *libName, + cmTarget & target) +{ + + cmGlobalVisualStudio7Generator* gg = + static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator); + + // Compute the version of the Intel plugin to the VS IDE. + // If the key does not exist then use a default guess. + std::string intelVersion = "9.10"; + std::string vskey = gg->GetRegistryBase(); + vskey += "\\Packages\\" CM_INTEL_PLUGIN_GUID ";ProductVersion"; + cmSystemTools::ReadRegistryValue(vskey.c_str(), intelVersion, + cmSystemTools::KeyWOW64_32); + if (intelVersion.find("13") == 0 || + intelVersion.find("12") == 0 || + intelVersion.find("11") == 0) + { + // Version 11.x, 12.x, and 13.x actually use 11.0 in project files! + intelVersion = "11.0" ; + } + else if(intelVersion.find("10") == 0) + { + // Version 10.x actually uses 9.10 in project files! + intelVersion = "9.10"; + } + + fout << "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>\n" + << "<VisualStudioProject\n" + << "\tProjectCreator=\"Intel Fortran\"\n" + << "\tVersion=\"" << intelVersion << "\"\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) << "}\">\n" + << "\t<Platforms>\n" + << "\t\t<Platform\n\t\t\tName=\"" << this->PlatformName << "\"/>\n" + << "\t</Platforms>\n"; +} + + +void +cmLocalVisualStudio7Generator::WriteProjectStart(std::ostream& fout, + const char *libName, + cmTarget & target, + std::vector<cmSourceGroup> &) +{ + if(this->FortranProject) + { + this->WriteProjectStartFortran(fout, libName, target); + return; + } + fout << "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>\n" + << "<VisualStudioProject\n" + << "\tProjectType=\"Visual C++\"\n"; + if(this->Version == VS71) + { + fout << "\tVersion=\"7.10\"\n"; + } + else + { + fout << "\tVersion=\"" << (this->Version/10) << ".00\"\n"; + } + const char* projLabel = target.GetProperty("PROJECT_LABEL"); + if(!projLabel) + { + projLabel = libName; + } + const char* keyword = target.GetProperty("VS_KEYWORD"); + if(!keyword) + { + keyword = "Win32Proj"; + } + cmGlobalVisualStudio7Generator* gg = + static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator); + fout << "\tName=\"" << projLabel << "\"\n"; + if(this->Version >= VS8) + { + fout << "\tProjectGUID=\"{" << gg->GetGUID(libName) << "}\"\n"; + } + this->WriteProjectSCC(fout, target); + fout << "\tKeyword=\"" << keyword << "\">\n" + << "\t<Platforms>\n" + << "\t\t<Platform\n\t\t\tName=\"" << this->PlatformName << "\"/>\n" + << "\t</Platforms>\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 char* 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 char* s) +{ + return cmLocalVisualStudio7GeneratorEscapeForXML(s); +} + +std::string cmLocalVisualStudio7Generator +::ConvertToXMLOutputPath(const char* path) +{ + std::string ret = this->ConvertToOptionallyRelativeOutputPath(path); + 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->ConvertToOptionallyRelativeOutputPath(path); + 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 char* /* name */) + { + } + virtual void StartElement(const char* name, const char** atts) + { + // once the GUID is found do nothing + if(this->GUID.size()) + { + return; + } + int i =0; + if(strcmp("VisualStudioProject", name) == 0) + { + 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 char* name, + const char* path) +{ + cmVS7XMLParser parser; + parser.ParseFile(path); + // if we can not find a GUID then create one + if(parser.GUID.size() == 0) + { + cmGlobalVisualStudio7Generator* gg = + static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator); + gg->CreateGUID(name); + 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", + cmCacheManager::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(GetVolumeInformation(volRoot, 0, 0, 0, 0, 0, fsName, 16) && + strstr(fsName, "FAT") != 0) + { + return true; + } + } + return false; +} |