From fba51b096e2d8ec281653aa05720c11dc9b9bfe6 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 24 Feb 2014 14:15:21 -0500 Subject: [PATCH] MSVC: Add properties to configure compiler PDB files (#14762) Since commit v2.8.12~437^2~2 (VS: Separate compiler and linker PDB files 2013-04-05) we no longer set /Fd with the PDB_NAME or PDB_OUTPUT_DIRECTORY properties. Those properties now exclusively handle linker PDB files. Since STATIC libraries do not link their compiler PDB file becomes more important. Add new target properties "COMPILE_PDB_NAME[_]" and "COMPILE_PDB_OUTPUT_DIRECTORY[_]" to specify the compiler PDB file location and pass the value to the MSVC /Fd option. --- Help/manual/cmake-properties.7.rst | 4 ++ Help/manual/cmake-variables.7.rst | 2 + Help/prop_tgt/COMPILE_PDB_NAME.rst | 11 ++++ Help/prop_tgt/COMPILE_PDB_NAME_CONFIG.rst | 10 ++++ Help/prop_tgt/COMPILE_PDB_NOTE.txt | 8 +++ .../prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY.rst | 13 +++++ .../COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst | 16 ++++++ Help/prop_tgt/PDB_NAME.rst | 1 + Help/prop_tgt/PDB_NAME_CONFIG.rst | 1 + Help/prop_tgt/PDB_NOTE.txt | 2 +- Help/prop_tgt/PDB_OUTPUT_DIRECTORY.rst | 1 + Help/prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG.rst | 1 + Help/release/dev/msvc-compiler-pdb-files.rst | 10 ++++ .../CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY.rst | 8 +++ ...KE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst | 11 ++++ Modules/Platform/Windows-MSVC.cmake | 2 +- Source/cmLocalGenerator.cxx | 7 +++ Source/cmLocalGenerator.h | 1 + Source/cmLocalVisualStudio7Generator.cxx | 13 ++++- .../cmMakefileExecutableTargetGenerator.cxx | 4 ++ Source/cmMakefileLibraryTargetGenerator.cxx | 4 ++ Source/cmMakefileTargetGenerator.cxx | 17 ++++++ Source/cmNinjaTargetGenerator.cxx | 16 ++++++ Source/cmTarget.cxx | 57 +++++++++++++++++++ Source/cmTarget.h | 12 ++++ Source/cmVisualStudio10TargetGenerator.cxx | 11 ++++ Tests/PDBDirectoryAndName/CMakeLists.txt | 30 +++++++--- 27 files changed, 262 insertions(+), 11 deletions(-) create mode 100644 Help/prop_tgt/COMPILE_PDB_NAME.rst create mode 100644 Help/prop_tgt/COMPILE_PDB_NAME_CONFIG.rst create mode 100644 Help/prop_tgt/COMPILE_PDB_NOTE.txt create mode 100644 Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY.rst create mode 100644 Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst create mode 100644 Help/release/dev/msvc-compiler-pdb-files.rst create mode 100644 Help/variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY.rst create mode 100644 Help/variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index d315fcbb6..6ea5839c8 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -100,6 +100,10 @@ Properties on Targets /prop_tgt/COMPILE_DEFINITIONS /prop_tgt/COMPILE_FLAGS /prop_tgt/COMPILE_OPTIONS + /prop_tgt/COMPILE_PDB_NAME + /prop_tgt/COMPILE_PDB_NAME_CONFIG + /prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY + /prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG /prop_tgt/CONFIG_OUTPUT_NAME /prop_tgt/CONFIG_POSTFIX /prop_tgt/DEBUG_POSTFIX diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index c4ae193d0..5f2ba28f7 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -198,6 +198,8 @@ Variables that Control the Build /variable/CMAKE_AUTOUIC /variable/CMAKE_AUTOUIC_OPTIONS /variable/CMAKE_BUILD_WITH_INSTALL_RPATH + /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY + /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG /variable/CMAKE_CONFIG_POSTFIX /variable/CMAKE_DEBUG_POSTFIX /variable/CMAKE_EXE_LINKER_FLAGS_CONFIG diff --git a/Help/prop_tgt/COMPILE_PDB_NAME.rst b/Help/prop_tgt/COMPILE_PDB_NAME.rst new file mode 100644 index 000000000..24a9f62d6 --- /dev/null +++ b/Help/prop_tgt/COMPILE_PDB_NAME.rst @@ -0,0 +1,11 @@ +COMPILE_PDB_NAME +---------------- + +Output name for the MS debug symbol ``.pdb`` file generated by the +compiler while building source files. + +This property specifies the base name for the debug symbols file. +If not set, the default is unspecified. + +.. |PDB_XXX| replace:: :prop_tgt:`PDB_NAME` +.. include:: COMPILE_PDB_NOTE.txt diff --git a/Help/prop_tgt/COMPILE_PDB_NAME_CONFIG.rst b/Help/prop_tgt/COMPILE_PDB_NAME_CONFIG.rst new file mode 100644 index 000000000..e4077f559 --- /dev/null +++ b/Help/prop_tgt/COMPILE_PDB_NAME_CONFIG.rst @@ -0,0 +1,10 @@ +COMPILE_PDB_NAME_ +------------------------- + +Per-configuration output name for the MS debug symbol ``.pdb`` file +generated by the compiler while building source files. + +This is the configuration-specific version of :prop_tgt:`COMPILE_PDB_NAME`. + +.. |PDB_XXX| replace:: :prop_tgt:`PDB_NAME_` +.. include:: COMPILE_PDB_NOTE.txt diff --git a/Help/prop_tgt/COMPILE_PDB_NOTE.txt b/Help/prop_tgt/COMPILE_PDB_NOTE.txt new file mode 100644 index 000000000..5941d72ef --- /dev/null +++ b/Help/prop_tgt/COMPILE_PDB_NOTE.txt @@ -0,0 +1,8 @@ +.. note:: + The compiler-generated program database files are specified by the + ``/Fd`` compiler flag and are not the same as linker-generated + program database files specified by the ``/pdb`` linker flag. + Use the |PDB_XXX| property to specify the latter. + + This property is not implemented by the :generator:`Visual Studio 6` + generator. diff --git a/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY.rst b/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY.rst new file mode 100644 index 000000000..34f49bebe --- /dev/null +++ b/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY.rst @@ -0,0 +1,13 @@ +COMPILE_PDB_OUTPUT_DIRECTORY +---------------------------- + +Output directory for the MS debug symbol ``.pdb`` file +generated by the compiler while building source files. + +This property specifies the directory into which the MS debug symbols +will be placed by the compiler. This property is initialized by the +value of the :variable:`CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY` variable +if it is set when a target is created. + +.. |PDB_XXX| replace:: :prop_tgt:`PDB_OUTPUT_DIRECTORY` +.. include:: COMPILE_PDB_NOTE.txt diff --git a/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst b/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst new file mode 100644 index 000000000..52ef013da --- /dev/null +++ b/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst @@ -0,0 +1,16 @@ +COMPILE_PDB_OUTPUT_DIRECTORY_ +------------------------------------- + +Per-configuration output directory for the MS debug symbol ``.pdb`` file +generated by the compiler while building source files. + +This is a per-configuration version of +:prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY`, +but multi-configuration generators (VS, Xcode) do NOT append a +per-configuration subdirectory to the specified directory. This +property is initialized by the value of the +:variable:`CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_` variable +if it is set when a target is created. + +.. |PDB_XXX| replace:: :prop_tgt:`PDB_OUTPUT_DIRECTORY_` +.. include:: COMPILE_PDB_NOTE.txt diff --git a/Help/prop_tgt/PDB_NAME.rst b/Help/prop_tgt/PDB_NAME.rst index 333c8656b..479dec3f9 100644 --- a/Help/prop_tgt/PDB_NAME.rst +++ b/Help/prop_tgt/PDB_NAME.rst @@ -7,4 +7,5 @@ linker for an executable or shared library target. This property specifies the base name for the debug symbols file. If not set, the logical target name is used by default. +.. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_NAME` .. include:: PDB_NOTE.txt diff --git a/Help/prop_tgt/PDB_NAME_CONFIG.rst b/Help/prop_tgt/PDB_NAME_CONFIG.rst index 7bf9e43dc..cb3121c2f 100644 --- a/Help/prop_tgt/PDB_NAME_CONFIG.rst +++ b/Help/prop_tgt/PDB_NAME_CONFIG.rst @@ -6,4 +6,5 @@ generated by the linker for an executable or shared library target. This is the configuration-specific version of :prop_tgt:`PDB_NAME`. +.. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_NAME_` .. include:: PDB_NOTE.txt diff --git a/Help/prop_tgt/PDB_NOTE.txt b/Help/prop_tgt/PDB_NOTE.txt index c03bd3a56..f90ea8117 100644 --- a/Help/prop_tgt/PDB_NOTE.txt +++ b/Help/prop_tgt/PDB_NOTE.txt @@ -6,7 +6,7 @@ The linker-generated program database files are specified by the ``/pdb`` linker flag and are not the same as compiler-generated program database files specified by the ``/Fd`` compiler flag. - This property does not influence the latter. + Use the |COMPILE_PDB_XXX| property to specify the latter. This property is not implemented by the :generator:`Visual Studio 6` generator. diff --git a/Help/prop_tgt/PDB_OUTPUT_DIRECTORY.rst b/Help/prop_tgt/PDB_OUTPUT_DIRECTORY.rst index 48773685f..730cf5776 100644 --- a/Help/prop_tgt/PDB_OUTPUT_DIRECTORY.rst +++ b/Help/prop_tgt/PDB_OUTPUT_DIRECTORY.rst @@ -9,4 +9,5 @@ will be placed by the linker. This property is initialized by the value of the :variable:`CMAKE_PDB_OUTPUT_DIRECTORY` variable if it is set when a target is created. +.. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY` .. include:: PDB_NOTE.txt diff --git a/Help/prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG.rst b/Help/prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG.rst index 7bbc23706..6037fa0c7 100644 --- a/Help/prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG.rst +++ b/Help/prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG.rst @@ -11,4 +11,5 @@ property is initialized by the value of the :variable:`CMAKE_PDB_OUTPUT_DIRECTORY_` variable if it is set when a target is created. +.. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY_` .. include:: PDB_NOTE.txt diff --git a/Help/release/dev/msvc-compiler-pdb-files.rst b/Help/release/dev/msvc-compiler-pdb-files.rst new file mode 100644 index 000000000..d06d20275 --- /dev/null +++ b/Help/release/dev/msvc-compiler-pdb-files.rst @@ -0,0 +1,10 @@ +msvc-compiler-pdb-files +----------------------- + +* New :prop_tgt:`COMPILE_PDB_NAME` and + :prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY` target properties + were introduced to specify the MSVC compiler program database + file location (``cl /Fd``). This complements the existing + :prop_tgt:`PDB_NAME` and :prop_tgt:`PDB_OUTPUT_DIRECTORY` + target properties that specify the linker program database + file location (``link /pdb``). diff --git a/Help/variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY.rst b/Help/variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY.rst new file mode 100644 index 000000000..ea33c7d64 --- /dev/null +++ b/Help/variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY.rst @@ -0,0 +1,8 @@ +CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY +---------------------------------- + +Output directory for MS debug symbol ``.pdb`` files +generated by the compiler while building source files. + +This variable is used to initialize the +:prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY` property on all the targets. diff --git a/Help/variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst b/Help/variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst new file mode 100644 index 000000000..fdeb9abdd --- /dev/null +++ b/Help/variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst @@ -0,0 +1,11 @@ +CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_ +------------------------------------------- + +Per-configuration output directory for MS debug symbol ``.pdb`` files +generated by the compiler while building source files. + +This is a per-configuration version of +:variable:`CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY`. +This variable is used to initialize the +:prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY_` +property on all the targets. diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index e29aaf41f..5732170fc 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -241,7 +241,7 @@ macro(__windows_compiler_msvc lang) set(CMAKE_${lang}_CREATE_STATIC_LIBRARY " /lib ${CMAKE_CL_NOLOGO} /out: ") set(CMAKE_${lang}_COMPILE_OBJECT - " ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} /Fo /Fd/${_FS_${lang}} -c ${CMAKE_END_TEMP_FILE}") + " ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} /Fo /Fd${_FS_${lang}} -c ${CMAKE_END_TEMP_FILE}") set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE " > ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} -E ${CMAKE_END_TEMP_FILE}") set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index aca195c57..4266dd061 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -901,6 +901,13 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable, return replaceValues.TargetPDB; } } + if(replaceValues.TargetCompilePDB) + { + if(variable == "TARGET_COMPILE_PDB") + { + return replaceValues.TargetCompilePDB; + } + } if(replaceValues.DependencyFile ) { if(variable == "DEP_FILE") diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 97648138a..0f7fd253b 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -245,6 +245,7 @@ public: } cmTarget* CMTarget; const char* TargetPDB; + const char* TargetCompilePDB; const char* TargetVersionMajor; const char* TargetVersionMinor; const char* Language; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 212b06b3a..ce24d8d0c 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -660,7 +660,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, switch(target.GetType()) { case cmTarget::OBJECT_LIBRARY: - targetBuilds = false; // TODO: PDB for object library? + targetBuilds = false; // no manifest tool for object library case cmTarget::STATIC_LIBRARY: projectType = "typeStaticLibrary"; configType = "4"; @@ -846,6 +846,17 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, targetOptions.OutputFlagMap(fout, "\t\t\t\t"); targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n", "CXX"); fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n"; + if(target.GetType() <= cmTarget::OBJECT_LIBRARY) + { + // Specify the compiler program database file if configured. + std::string pdb = target.GetCompilePDBPath(configName); + if(!pdb.empty()) + { + fout << "\t\t\t\tProgramDataBaseFileName=\"" + << this->ConvertToXMLOutputPathSingle(pdb.c_str()) + << "\"\n"; + } + } fout << "/>\n"; // end of FortranProject) diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 664d73e87..03fdda246 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -129,6 +129,10 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) } } + std::string compilePdbOutputPath = + this->Target->GetCompilePDBDirectory(this->ConfigName); + cmSystemTools::MakeDirectory(compilePdbOutputPath.c_str()); + std::string pdbOutputPath = this->Target->GetPDBDirectory(this->ConfigName); cmSystemTools::MakeDirectory(pdbOutputPath.c_str()); pdbOutputPath += "/"; diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index b9af63815..807aca8f6 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -321,6 +321,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules } } + std::string compilePdbOutputPath = + this->Target->GetCompilePDBDirectory(this->ConfigName); + cmSystemTools::MakeDirectory(compilePdbOutputPath.c_str()); + std::string pdbOutputPath = this->Target->GetPDBDirectory(this->ConfigName); cmSystemTools::MakeDirectory(pdbOutputPath.c_str()); pdbOutputPath += "/"; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index c3ca85d5a..c6ade7f1d 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -624,9 +624,11 @@ cmMakefileTargetGenerator std::string targetOutPathReal; std::string targetOutPathPDB; + std::string targetOutPathCompilePDB; { std::string targetFullPathReal; std::string targetFullPathPDB; + std::string targetFullPathCompilePDB; if(this->Target->GetType() == cmTarget::EXECUTABLE || this->Target->GetType() == cmTarget::STATIC_LIBRARY || this->Target->GetType() == cmTarget::SHARED_LIBRARY || @@ -638,12 +640,26 @@ cmMakefileTargetGenerator targetFullPathPDB += "/"; targetFullPathPDB += this->Target->GetPDBName(this->ConfigName); } + if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY) + { + targetFullPathCompilePDB = + this->Target->GetCompilePDBPath(this->ConfigName); + if(targetFullPathCompilePDB.empty()) + { + targetFullPathCompilePDB = this->Target->GetSupportDirectory() + "/"; + } + } + targetOutPathReal = this->Convert(targetFullPathReal.c_str(), cmLocalGenerator::START_OUTPUT, cmLocalGenerator::SHELL); targetOutPathPDB = this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::NONE, cmLocalGenerator::SHELL); + targetOutPathCompilePDB = + this->Convert(targetFullPathCompilePDB.c_str(), + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::SHELL); } cmLocalGenerator::RuleVariables vars; vars.RuleLauncher = "RULE_LAUNCH_COMPILE"; @@ -651,6 +667,7 @@ cmMakefileTargetGenerator vars.Language = lang; vars.Target = targetOutPathReal.c_str(); vars.TargetPDB = targetOutPathPDB.c_str(); + vars.TargetCompilePDB = targetOutPathCompilePDB.c_str(); vars.Source = sourceFile.c_str(); std::string shellObj = this->Convert(obj.c_str(), diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 900af8d6e..eaeddefed 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -320,6 +320,7 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID")) { std::string pdbPath; + std::string compilePdbPath; if(this->Target->GetType() == cmTarget::EXECUTABLE || this->Target->GetType() == cmTarget::STATIC_LIBRARY || this->Target->GetType() == cmTarget::SHARED_LIBRARY || @@ -329,11 +330,25 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const pdbPath += "/"; pdbPath += this->Target->GetPDBName(this->GetConfigName()); } + if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY) + { + compilePdbPath = this->Target->GetCompilePDBPath(this->GetConfigName()); + if(compilePdbPath.empty()) + { + compilePdbPath = this->Target->GetSupportDirectory() + "/"; + } + } vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat( ConvertToNinjaPath(pdbPath.c_str()).c_str(), cmLocalGenerator::SHELL); + vars["TARGET_COMPILE_PDB"] = + this->GetLocalGenerator()->ConvertToOutputFormat( + ConvertToNinjaPath(compilePdbPath.c_str()).c_str(), + cmLocalGenerator::SHELL); + EnsureParentDirectoryExists(pdbPath); + EnsureParentDirectoryExists(compilePdbPath); return true; } return false; @@ -362,6 +377,7 @@ cmNinjaTargetGenerator vars.Object = "$out"; vars.Defines = "$DEFINES"; vars.TargetPDB = "$TARGET_PDB"; + vars.TargetCompilePDB = "$TARGET_COMPILE_PDB"; vars.ObjectDir = "$OBJECT_DIR"; cmMakefile* mf = this->GetMakefile(); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index a50d6adfc..7a0df745c 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -74,6 +74,7 @@ struct cmTarget::ImportInfo //---------------------------------------------------------------------------- struct cmTarget::CompileInfo { + std::string CompilePdbDir; }; struct TargetConfigPair : public std::pair { @@ -275,6 +276,7 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->SetPropertyDefault("LIBRARY_OUTPUT_DIRECTORY", 0); this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", 0); this->SetPropertyDefault("PDB_OUTPUT_DIRECTORY", 0); + this->SetPropertyDefault("COMPILE_PDB_OUTPUT_DIRECTORY", 0); this->SetPropertyDefault("Fortran_FORMAT", 0); this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0); this->SetPropertyDefault("GNUtoMS", 0); @@ -303,6 +305,7 @@ void cmTarget::SetMakefile(cmMakefile* mf) "LIBRARY_OUTPUT_DIRECTORY_", "RUNTIME_OUTPUT_DIRECTORY_", "PDB_OUTPUT_DIRECTORY_", + "COMPILE_PDB_OUTPUT_DIRECTORY_", "MAP_IMPORTED_CONFIG_", 0}; for(std::vector::iterator ci = configNames.begin(); @@ -2517,6 +2520,7 @@ cmTarget::CompileInfo const* cmTarget::GetCompileInfo(const char* config) const if(i == this->Internal->CompileInfoMap.end()) { CompileInfo info; + this->ComputePDBOutputDir("COMPILE_PDB", config, info.CompilePdbDir); CompileInfoMapType::value_type entry(config_upper, info); i = this->Internal->CompileInfoMap.insert(entry).first; } @@ -2552,6 +2556,16 @@ std::string cmTarget::GetPDBDirectory(const char* config) const return ""; } +//---------------------------------------------------------------------------- +std::string cmTarget::GetCompilePDBDirectory(const char* config) const +{ + if(CompileInfo const* info = this->GetCompileInfo(config)) + { + return info->CompilePdbDir; + } + return ""; +} + //---------------------------------------------------------------------------- const char* cmTarget::GetLocation(const char* config) const { @@ -3212,6 +3226,49 @@ std::string cmTarget::GetPDBName(const char* config) const return prefix+base+".pdb"; } +//---------------------------------------------------------------------------- +std::string cmTarget::GetCompilePDBName(const char* config) const +{ + std::string prefix; + std::string base; + std::string suffix; + this->GetFullNameInternal(config, false, prefix, base, suffix); + + // Check for a per-configuration output directory target property. + std::string configUpper = cmSystemTools::UpperCase(config? config : ""); + std::string configProp = "COMPILE_PDB_NAME_"; + configProp += configUpper; + const char* config_name = this->GetProperty(configProp.c_str()); + if(config_name && *config_name) + { + return prefix + config_name + ".pdb"; + } + + const char* name = this->GetProperty("COMPILE_PDB_NAME"); + if(name && *name) + { + return prefix + name + ".pdb"; + } + + return ""; +} + +//---------------------------------------------------------------------------- +std::string cmTarget::GetCompilePDBPath(const char* config) const +{ + std::string dir = this->GetCompilePDBDirectory(config); + std::string name = this->GetCompilePDBName(config); + if(dir.empty() && !name.empty()) + { + dir = this->GetPDBDirectory(config); + } + if(!dir.empty()) + { + dir += "/"; + } + return dir + name; +} + //---------------------------------------------------------------------------- bool cmTarget::HasSOName(const char* config) const { diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 678770606..a3f544c69 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -342,6 +342,12 @@ public: pdb output directory is given. */ std::string GetPDBDirectory(const char* config) const; + /** Get the directory in which to place the target compiler .pdb file. + If the configuration name is given then the generator will add its + subdirectory for that configuration. Otherwise just the canonical + compiler pdb output directory is given. */ + std::string GetCompilePDBDirectory(const char* config = 0) const; + /** Get the location of the target in the build tree for the given configuration. This location is suitable for use as the LOCATION target property. */ @@ -377,6 +383,12 @@ public: /** Get the name of the pdb file for the target. */ std::string GetPDBName(const char* config) const; + /** Get the name of the compiler pdb file for the target. */ + std::string GetCompilePDBName(const char* config=0) const; + + /** Get the path for the MSVC /Fd option for this target. */ + std::string GetCompilePDBPath(const char* config=0) const; + /** Whether this library has soname enabled and platform supports it. */ bool HasSOName(const char* config) const; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index ed7e243e8..b1f09741d 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1427,6 +1427,17 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", "\n", "CXX"); this->WriteString("$(IntDir)\n", 3); + + // Specify the compiler program database file if configured. + std::string pdb = this->Target->GetCompilePDBPath(configName.c_str()); + if(!pdb.empty()) + { + this->ConvertToWindowsSlash(pdb); + this->WriteString("", 3); + *this->BuildFileStream << cmVS10EscapeXML(pdb) + << "\n"; + } + this->WriteString("\n", 2); } diff --git a/Tests/PDBDirectoryAndName/CMakeLists.txt b/Tests/PDBDirectoryAndName/CMakeLists.txt index 28e46b1f5..90af600fc 100644 --- a/Tests/PDBDirectoryAndName/CMakeLists.txt +++ b/Tests/PDBDirectoryAndName/CMakeLists.txt @@ -6,6 +6,13 @@ if(NOT MSVC AND NOT "${CMAKE_C_COMPILER_ID}" MATCHES "^(Intel)$") message(FATAL_ERROR "The PDBDirectoryAndName test works only with MSVC or Intel") endif() +# Intel 11.1 does not support /Fd but Intel 14.0 does. +# TODO: Did a version in between these add it? +if(CMAKE_C_COMPILER_ID STREQUAL Intel AND + CMAKE_C_COMPILER_VERSION VERSION_LESS 14.0) + set(NO_COMPILE_PDB 1) +endif() + set(my_targets "") add_library(mylibA SHARED mylibA.c) @@ -17,12 +24,12 @@ list(APPEND my_targets mylibA) add_library(mylibB STATIC mylibB.c) set_target_properties(mylibB PROPERTIES - PDB_NAME "mylibB_Special" - PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibB_PDB" + COMPILE_PDB_NAME "mylibB_Special" + COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibB_PDB" ) -# TODO: The only .pdb available for a static library is that generated -# by the compiler /Fd option which is not the same as the linker /pdb. -# list(APPEND my_targets mylibB) +if(NOT NO_COMPILE_PDB) + list(APPEND my_targets mylibB) +endif() add_library(mylibC SHARED mylibC.c) set_target_properties(mylibC PROPERTIES @@ -32,10 +39,11 @@ list(APPEND my_targets mylibC) add_library(mylibD STATIC mylibD.c) set_target_properties(mylibD PROPERTIES - PDB_NAME "mylibD_Special" + COMPILE_PDB_NAME "mylibD_Special" ) -# TODO: See comment for mylibB. -# list(APPEND my_targets mylibD) +if(NOT NO_COMPILE_PDB) + list(APPEND my_targets mylibD) +endif() add_executable(myexe myexe.c) set_target_properties(myexe PROPERTIES @@ -66,6 +74,12 @@ set(pdbs "") foreach(t ${my_targets}) get_property(pdb_name TARGET ${t} PROPERTY PDB_NAME) get_property(pdb_dir TARGET ${t} PROPERTY PDB_OUTPUT_DIRECTORY) + if(NOT pdb_name) + get_property(pdb_name TARGET ${t} PROPERTY COMPILE_PDB_NAME) + endif() + if(NOT pdb_dir) + get_property(pdb_dir TARGET ${t} PROPERTY COMPILE_PDB_OUTPUT_DIRECTORY) + endif() if(NOT pdb_dir) set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR}) endif()