Browse Source

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[_<CONFIG>]" and
"COMPILE_PDB_OUTPUT_DIRECTORY[_<CONFIG>]" to specify the compiler PDB
file location and pass the value to the MSVC /Fd option.
Brad King 11 years ago
parent
commit
fba51b096e

+ 4 - 0
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

+ 2 - 0
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

+ 11 - 0
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

+ 10 - 0
Help/prop_tgt/COMPILE_PDB_NAME_CONFIG.rst

@@ -0,0 +1,10 @@
+COMPILE_PDB_NAME_<CONFIG>
+-------------------------
+
+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_<CONFIG>`
+.. include:: COMPILE_PDB_NOTE.txt

+ 8 - 0
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.

+ 13 - 0
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

+ 16 - 0
Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst

@@ -0,0 +1,16 @@
+COMPILE_PDB_OUTPUT_DIRECTORY_<CONFIG>
+-------------------------------------
+
+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_<CONFIG>` variable
+if it is set when a target is created.
+
+.. |PDB_XXX| replace:: :prop_tgt:`PDB_OUTPUT_DIRECTORY_<CONFIG>`
+.. include:: COMPILE_PDB_NOTE.txt

+ 1 - 0
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

+ 1 - 0
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_<CONFIG>`
 .. include:: PDB_NOTE.txt

+ 1 - 1
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.

+ 1 - 0
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

+ 1 - 0
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_<CONFIG>` variable if it is
 set when a target is created.
 
+.. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY_<CONFIG>`
 .. include:: PDB_NOTE.txt

+ 10 - 0
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``).

+ 8 - 0
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.

+ 11 - 0
Help/variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst

@@ -0,0 +1,11 @@
+CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_<CONFIG>
+-------------------------------------------
+
+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_<CONFIG>`
+property on all the targets.

+ 1 - 1
Modules/Platform/Windows-MSVC.cmake

@@ -241,7 +241,7 @@ macro(__windows_compiler_msvc lang)
   set(CMAKE_${lang}_CREATE_STATIC_LIBRARY  "<CMAKE_LINKER> /lib ${CMAKE_CL_NOLOGO} <LINK_FLAGS> /out:<TARGET> <OBJECTS> ")
 
   set(CMAKE_${lang}_COMPILE_OBJECT
-    "<CMAKE_${lang}_COMPILER> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} <FLAGS> <DEFINES> /Fo<OBJECT> /Fd<OBJECT_DIR>/${_FS_${lang}} -c <SOURCE>${CMAKE_END_TEMP_FILE}")
+    "<CMAKE_${lang}_COMPILER> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} <FLAGS> <DEFINES> /Fo<OBJECT> /Fd<TARGET_COMPILE_PDB>${_FS_${lang}} -c <SOURCE>${CMAKE_END_TEMP_FILE}")
   set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE
     "<CMAKE_${lang}_COMPILER> > <PREPROCESSED_SOURCE> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} <FLAGS> <DEFINES> -E <SOURCE>${CMAKE_END_TEMP_FILE}")
   set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE

+ 7 - 0
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")

+ 1 - 0
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;

+ 12 - 1
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 <Tool Name=VCCLCompilerTool
   tool = "VCCustomBuildTool";
   if(this->FortranProject)

+ 4 - 0
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 += "/";

+ 4 - 0
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 += "/";

+ 17 - 0
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(),

+ 16 - 0
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();

+ 57 - 0
Source/cmTarget.cxx

@@ -74,6 +74,7 @@ struct cmTarget::ImportInfo
 //----------------------------------------------------------------------------
 struct cmTarget::CompileInfo
 {
+  std::string CompilePdbDir;
 };
 
 struct TargetConfigPair : public std::pair<cmTarget const* , std::string> {
@@ -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<std::string>::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
 {

+ 12 - 0
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;
 

+ 11 - 0
Source/cmVisualStudio10TargetGenerator.cxx

@@ -1427,6 +1427,17 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
   clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, "      ",
                                           "\n", "CXX");
   this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\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("<ProgramDataBaseFileName>", 3);
+    *this->BuildFileStream << cmVS10EscapeXML(pdb)
+                           << "</ProgramDataBaseFileName>\n";
+    }
+
   this->WriteString("</ClCompile>\n", 2);
 }
 

+ 22 - 8
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()