From 3f60dbf1484575f4c28a15c89e1af071648c8f2d Mon Sep 17 00:00:00 2001
From: Yuchen Deng <loaden@gmail.com>
Date: Tue, 25 Sep 2012 09:30:42 +0800
Subject: Add PDB_OUTPUT_DIRECTORY and PDB_NAME target properties (#10830)

This enables changing the name and output folder of the debug symbol
files produced by MS compilers.

Inspired-by: Thomas Bernard <thomas.bernard@ipetronik.com>
---
 Source/cmDocumentVariables.cxx                 |   9 ++
 Source/cmLocalVisualStudio7Generator.cxx       |   6 +-
 Source/cmMakefileExecutableTargetGenerator.cxx |   7 +-
 Source/cmMakefileLibraryTargetGenerator.cxx    |   6 +-
 Source/cmMakefileTargetGenerator.cxx           |   2 +-
 Source/cmNinjaTargetGenerator.cxx              |   4 +-
 Source/cmTarget.cxx                            | 131 ++++++++++++++++++++++++-
 Source/cmTarget.h                              |   7 ++
 Source/cmVisualStudio10TargetGenerator.cxx     |   8 +-
 Tests/CMakeLists.txt                           |   1 +
 Tests/PDBDirectoryAndName/CMakeLists.txt       |  43 ++++++++
 Tests/PDBDirectoryAndName/myexe.c              |   5 +
 Tests/PDBDirectoryAndName/myexe2.c             |   3 +
 Tests/PDBDirectoryAndName/mylibA.c             |   1 +
 Tests/PDBDirectoryAndName/mylibB.c             |   1 +
 Tests/PDBDirectoryAndName/mylibC.c             |   1 +
 Tests/PDBDirectoryAndName/mylibD.c             |   1 +
 17 files changed, 220 insertions(+), 16 deletions(-)
 create mode 100644 Tests/PDBDirectoryAndName/CMakeLists.txt
 create mode 100644 Tests/PDBDirectoryAndName/myexe.c
 create mode 100644 Tests/PDBDirectoryAndName/myexe2.c
 create mode 100644 Tests/PDBDirectoryAndName/mylibA.c
 create mode 100644 Tests/PDBDirectoryAndName/mylibB.c
 create mode 100644 Tests/PDBDirectoryAndName/mylibC.c
 create mode 100644 Tests/PDBDirectoryAndName/mylibD.c

diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx
index 5e7e081..db3d055 100644
--- a/Source/cmDocumentVariables.cxx
+++ b/Source/cmDocumentVariables.cxx
@@ -1211,6 +1211,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
      "Variables that Control the Build");
 
   cm->DefineProperty
+    ("CMAKE_PDB_OUTPUT_DIRECTORY", cmProperty::VARIABLE,
+     "Where to put all the MS debug symbol files.",
+     "This variable is used to initialize the "
+     "PDB_OUTPUT_DIRECTORY property on all the targets. "
+     "See that target property for additional information.",
+     false,
+     "Variables that Control the Build");
+
+  cm->DefineProperty
     ("CMAKE_AUTOMOC", cmProperty::VARIABLE,
      "Whether to handle moc automatically for Qt targets.",
      "This variable is used to initialize the "
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 2dfca02..ed17786 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -847,7 +847,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
     // non-debug configurations because VS still creates .idb files.
     fout <<  "\t\t\t\tProgramDataBaseFileName=\""
          << this->ConvertToXMLOutputPathSingle(
-              target.GetDirectory(configName).c_str())
+              target.GetPDBDirectory(configName).c_str())
          << "/"
          << target.GetPDBName(configName) << "\"\n";
     }
@@ -1125,7 +1125,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
     fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
     this->OutputLibraryDirectories(fout, cli.GetDirectories());
     fout << "\"\n";
-    temp = target.GetDirectory(configName);
+    temp = target.GetPDBDirectory(configName);
     temp += "/";
     temp += targetNamePDB;
     fout << "\t\t\t\tProgramDatabaseFile=\"" <<
@@ -1211,7 +1211,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
     this->OutputLibraryDirectories(fout, cli.GetDirectories());
     fout << "\"\n";
     std::string path = this->ConvertToXMLOutputPathSingle(
-      target.GetDirectory(configName).c_str());
+      target.GetPDBDirectory(configName).c_str());
     fout << "\t\t\t\tProgramDatabaseFile=\""
          << path << "/" << targetNamePDB
          << "\"\n";
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index ab5150a..d06dfc0 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -131,9 +131,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
       outpathImp += "/";
       }
     }
+
+  std::string pdbOutputPath = this->Target->GetPDBDirectory();
+  cmSystemTools::MakeDirectory(pdbOutputPath.c_str());
+  pdbOutputPath += "/";
+
   std::string targetFullPath = outpath + targetName;
   std::string targetFullPathReal = outpath + targetNameReal;
-  std::string targetFullPathPDB = outpath + targetNamePDB;
+  std::string targetFullPathPDB =  pdbOutputPath + targetNamePDB;
   std::string targetFullPathImport = outpathImp + targetNameImport;
   std::string targetOutPathPDB =
     this->Convert(targetFullPathPDB.c_str(),
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 577e5fd..95b71f2 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -328,8 +328,12 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
       }
     }
 
+  std::string pdbOutputPath = this->Target->GetPDBDirectory();
+  cmSystemTools::MakeDirectory(pdbOutputPath.c_str());
+  pdbOutputPath += "/";
+
   std::string targetFullPath = outpath + targetName;
-  std::string targetFullPathPDB = outpath + targetNamePDB;
+  std::string targetFullPathPDB = pdbOutputPath + targetNamePDB;
   std::string targetFullPathSO = outpath + targetNameSO;
   std::string targetFullPathReal = outpath + targetNameReal;
   std::string targetFullPathImport = outpathImp + targetNameImport;
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 95738c4..ab25907 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -652,7 +652,7 @@ cmMakefileTargetGenerator
      this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
      this->Target->GetType() == cmTarget::MODULE_LIBRARY)
     {
-    targetFullPathPDB = this->Target->GetDirectory(this->ConfigName);
+    targetFullPathPDB = this->Target->GetPDBDirectory(this->ConfigName);
     targetFullPathPDB += "/";
     targetFullPathPDB += this->Target->GetPDBName(this->ConfigName);
     }
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 385b4a0..2456bfc 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -335,10 +335,10 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const
        this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
        this->Target->GetType() == cmTarget::MODULE_LIBRARY)
       {
-      pdbPath = this->Target->GetDirectory(this->GetConfigName());
+      pdbPath = this->Target->GetPDBDirectory(this->GetConfigName());
       pdbPath += "/";
       pdbPath += this->Target->GetPDBName(this->GetConfigName());
-    }
+      }
 
     vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
                           ConvertToNinjaPath(pdbPath.c_str()).c_str(),
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 9a3812c..b932afc 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -57,6 +57,7 @@ struct cmTarget::OutputInfo
 {
   std::string OutDir;
   std::string ImpDir;
+  std::string PdbDir;
 };
 
 //----------------------------------------------------------------------------
@@ -741,6 +742,18 @@ void cmTarget::DefineProperties(cmake *cm)
      "Use OUTPUT_NAME_<CONFIG> instead.");
 
   cm->DefineProperty
+    ("PDB_NAME", cmProperty::TARGET,
+     "Output name for MS debug symbols .pdb file.",
+     "Set the base name for debug symbols file created for an "
+     "executable or library target.  "
+     "If not set, the logical target name is used by default.");
+
+  cm->DefineProperty
+    ("PDB_NAME_<CONFIG>", cmProperty::TARGET,
+     "Per-configuration name for MS debug symbols .pdb file.  ",
+     "This is the configuration-specific version of PDB_NAME.");
+
+  cm->DefineProperty
     ("PRE_INSTALL_SCRIPT", cmProperty::TARGET,
      "Deprecated install support.",
      "The PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT properties are the "
@@ -1190,6 +1203,23 @@ void cmTarget::DefineProperties(cmake *cm)
      CM_TARGET_OUTDIR_CONFIG_DOC(RUNTIME));
 
   cm->DefineProperty
+    ("PDB_OUTPUT_DIRECTORY", cmProperty::TARGET,
+     "Output directory for MS debug symbols .pdb files.",
+     "This property specifies the directory into which the MS debug symbols "
+     "will be placed.  "
+     "This property is initialized by the value of the variable "
+     "CMAKE_PDB_OUTPUT_DIRECTORY if it is set when a target is created.");
+  cm->DefineProperty
+    ("PDB_OUTPUT_DIRECTORY_<CONFIG>", cmProperty::TARGET,
+     "Per-configuration output directory for MS debug symbols .pdb files.",
+     "This is a per-configuration version of 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_PDB_OUTPUT_DIRECTORY_<CONFIG> "
+     "if it is set when a target is created.");
+
+  cm->DefineProperty
     ("ARCHIVE_OUTPUT_NAME", cmProperty::TARGET,
      "Output name for ARCHIVE target files.",
      "This property specifies the base name for archive target files. "
@@ -1263,6 +1293,7 @@ void cmTarget::SetMakefile(cmMakefile* mf)
   this->SetPropertyDefault("ARCHIVE_OUTPUT_DIRECTORY", 0);
   this->SetPropertyDefault("LIBRARY_OUTPUT_DIRECTORY", 0);
   this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", 0);
+  this->SetPropertyDefault("PDB_OUTPUT_DIRECTORY", 0);
   this->SetPropertyDefault("Fortran_FORMAT", 0);
   this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0);
   this->SetPropertyDefault("GNUtoMS", 0);
@@ -1282,6 +1313,7 @@ void cmTarget::SetMakefile(cmMakefile* mf)
     "ARCHIVE_OUTPUT_DIRECTORY_",
     "LIBRARY_OUTPUT_DIRECTORY_",
     "RUNTIME_OUTPUT_DIRECTORY_",
+    "PDB_OUTPUT_DIRECTORY_",
     0};
   for(std::vector<std::string>::iterator ci = configNames.begin();
       ci != configNames.end(); ++ci)
@@ -2539,6 +2571,7 @@ cmTarget::OutputInfo const* cmTarget::GetOutputInfo(const char* config)
     OutputInfo info;
     this->ComputeOutputDir(config, false, info.OutDir);
     this->ComputeOutputDir(config, true, info.ImpDir);
+    this->ComputePDBOutputDir(config, info.PdbDir);
     OutputInfoMapType::value_type entry(config_upper, info);
     i = this->Internal->OutputInfoMap.insert(entry).first;
     }
@@ -2564,6 +2597,17 @@ std::string cmTarget::GetDirectory(const char* config, bool implib)
 }
 
 //----------------------------------------------------------------------------
+std::string cmTarget::GetPDBDirectory(const char* config)
+{
+  if(OutputInfo const* info = this->GetOutputInfo(config))
+    {
+    // Return the directory in which the target will be built.
+    return info->PdbDir;
+    }
+  return "";
+}
+
+//----------------------------------------------------------------------------
 const char* cmTarget::GetLocation(const char* config)
 {
   if (this->IsImported())
@@ -3028,6 +3072,28 @@ std::string cmTarget::GetPDBName(const char* config)
   std::string base;
   std::string suffix;
   this->GetFullNameInternal(config, false, prefix, base, suffix);
+
+  std::vector<std::string> props;
+  std::string configUpper =
+    cmSystemTools::UpperCase(config? config : "");
+  if(!configUpper.empty())
+    {
+    // PDB_NAME_<CONFIG>
+    props.push_back("PDB_NAME_" + configUpper);
+    }
+
+  // PDB_NAME
+  props.push_back("PDB_NAME");
+
+  for(std::vector<std::string>::const_iterator i = props.begin();
+      i != props.end(); ++i)
+    {
+    if(const char* outName = this->GetProperty(i->c_str()))
+      {
+      base = outName;
+      break;
+      }
+    }
   return prefix+base+".pdb";
 }
 
@@ -3412,7 +3478,7 @@ void cmTarget::GetLibraryNames(std::string& name,
     }
 
   // The program database file name.
-  pdbName = prefix+base+".pdb";
+  pdbName = this->GetPDBName(config);
 }
 
 //----------------------------------------------------------------------------
@@ -3491,7 +3557,7 @@ void cmTarget::GetExecutableNames(std::string& name,
   impName = this->GetFullNameInternal(config, true);
 
   // The program database file name.
-  pdbName = prefix+base+".pdb";
+  pdbName = this->GetPDBName(config);
 }
 
 //----------------------------------------------------------------------------
@@ -3570,7 +3636,7 @@ void cmTarget::GenerateTargetManifest(const char* config)
     }
   if(!pdbName.empty())
     {
-    f = dir;
+    f = this->GetPDBDirectory(config);
     f += "/";
     f += pdbName;
     gg->AddToManifest(config? config:"", f);
@@ -3880,6 +3946,65 @@ bool cmTarget::ComputeOutputDir(const char* config,
 }
 
 //----------------------------------------------------------------------------
+void cmTarget::ComputePDBOutputDir(const char* config, std::string& out)
+{
+  // Look for a target property defining the target output directory
+  // based on the target type.
+  std::string targetTypeName = "PDB";
+  const char* propertyName = 0;
+  std::string propertyNameStr = targetTypeName;
+  if(!propertyNameStr.empty())
+    {
+    propertyNameStr += "_OUTPUT_DIRECTORY";
+    propertyName = propertyNameStr.c_str();
+    }
+
+  // Check for a per-configuration output directory target property.
+  std::string configUpper = cmSystemTools::UpperCase(config? config : "");
+  const char* configProp = 0;
+  std::string configPropStr = targetTypeName;
+  if(!configPropStr.empty())
+    {
+    configPropStr += "_OUTPUT_DIRECTORY_";
+    configPropStr += configUpper;
+    configProp = configPropStr.c_str();
+    }
+
+  // Select an output directory.
+  if(const char* config_outdir = this->GetProperty(configProp))
+    {
+    // Use the user-specified per-configuration output directory.
+    out = config_outdir;
+
+    // Skip per-configuration subdirectory.
+    config = 0;
+    }
+  else if(const char* outdir = this->GetProperty(propertyName))
+    {
+    // Use the user-specified output directory.
+    out = outdir;
+    }
+  if(out.empty())
+    {
+    // Default to the current output directory.
+    out = ".";
+    }
+
+  // Convert the output path to a full path in case it is
+  // specified as a relative path.  Treat a relative path as
+  // relative to the current output directory for this makefile.
+  out = (cmSystemTools::CollapseFullPath
+         (out.c_str(), this->Makefile->GetStartOutputDirectory()));
+
+  // The generator may add the configuration's subdirectory.
+  if(config && *config)
+    {
+    this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->
+      AppendDirectoryForConfig("/", config, "", out);
+    }
+}
+
+//----------------------------------------------------------------------------
 bool cmTarget::UsesDefaultOutputDir(const char* config, bool implib)
 {
   std::string dir;
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 98eaeec..e1a9de7 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -301,6 +301,12 @@ public:
       output directory is given.  */
   std::string GetDirectory(const char* config = 0, bool implib = false);
 
+  /** Get the directory in which this targets .pdb files will be placed.
+      If the configuration name is given then the generator will add its
+      subdirectory for that configuration.  Otherwise just the canonical
+      pdb output directory is given.  */
+  std::string GetPDBDirectory(const char* config = 0);
+
   /** 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.  */
@@ -593,6 +599,7 @@ private:
   struct OutputInfo;
   OutputInfo const* GetOutputInfo(const char* config);
   bool ComputeOutputDir(const char* config, bool implib, std::string& out);
+  void ComputePDBOutputDir(const char* config, std::string& out);
 
   // Cache import information from properties for each configuration.
   struct ImportInfo;
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 3d2828d..6ce3fe2 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -1284,9 +1284,8 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
   this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3);
   if(this->Target->GetType() != cmTarget::OBJECT_LIBRARY)
     {
-    // TODO: PDB for object library?
     this->WriteString("<ProgramDataBaseFileName>", 3);
-    *this->BuildFileStream << this->Target->GetDirectory(configName.c_str())
+    *this->BuildFileStream << this->Target->GetPDBDirectory(configName.c_str())
                            << "/"
                            << this->Target->GetPDBName(configName.c_str())
                            << "</ProgramDataBaseFileName>\n";
@@ -1511,9 +1510,8 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const&
                                   config.c_str());
     }
 
-  std::string dir = this->Target->GetDirectory(config.c_str());
-  dir += "/";
-  std::string pdb = dir;
+  std::string pdb = this->Target->GetPDBDirectory(config.c_str());
+  pdb += "/";
   pdb += targetNamePDB;
   std::string imLib = this->Target->GetDirectory(config.c_str(), true);
   imLib += "/";
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index e03b926..4d071cb 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -1259,6 +1259,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
   if(CMAKE_TEST_MSVC OR
       "${CMAKE_TEST_GENERATOR}" MATCHES "(MSYS|MinGW) Makefiles")
     ADD_TEST_MACRO(ModuleDefinition example_exe)
+    ADD_TEST_MACRO(PDBDirectoryAndName myexe)
   endif()
 
   ADD_TEST_MACRO(CheckCompilerRelatedVariables CheckCompilerRelatedVariables)
diff --git a/Tests/PDBDirectoryAndName/CMakeLists.txt b/Tests/PDBDirectoryAndName/CMakeLists.txt
new file mode 100644
index 0000000..ef1cae1
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/CMakeLists.txt
@@ -0,0 +1,43 @@
+cmake_minimum_required(VERSION 2.8)
+project(PDBDirectoryAndName C)
+
+if(NOT MSVC)
+    MESSAGE(FATAL_ERROR "The PDB file test works only with MSVC")
+endif()
+
+add_library(mylibA SHARED mylibA.c)
+set_target_properties(mylibA PROPERTIES
+    PDB_NAME "mylibA_Special"
+    PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibA_PDB"
+)
+
+add_library(mylibB STATIC mylibB.c)
+set_target_properties(mylibB PROPERTIES
+    PDB_NAME "mylibB_Special"
+    PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibB_PDB"
+)
+
+add_library(mylibC SHARED mylibC.c)
+set_target_properties(mylibC PROPERTIES
+    PDB_NAME "mylibC_Special"
+)
+
+add_library(mylibD STATIC mylibD.c)
+set_target_properties(mylibD PROPERTIES
+    PDB_NAME "mylibD_Special"
+)
+
+add_executable(myexe myexe.c)
+set_target_properties(myexe PROPERTIES
+    PDB_NAME "myexe_Special"
+    PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/myexe_PDB"
+)
+
+target_link_libraries(myexe mylibA mylibB mylibC mylibD)
+
+add_executable(myexe2 myexe2.c)
+set_target_properties(myexe2 PROPERTIES
+    PDB_NAME "myexe2_Special"
+)
+
+target_link_libraries(myexe2 mylibA mylibD)
diff --git a/Tests/PDBDirectoryAndName/myexe.c b/Tests/PDBDirectoryAndName/myexe.c
new file mode 100644
index 0000000..c6d9065
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/myexe.c
@@ -0,0 +1,5 @@
+extern int mylibA();
+extern int mylibB();
+extern int mylibC();
+extern int mylibD();
+int main() { return mylibA() + mylibB() + mylibC() + mylibD(); }
diff --git a/Tests/PDBDirectoryAndName/myexe2.c b/Tests/PDBDirectoryAndName/myexe2.c
new file mode 100644
index 0000000..75b39cd
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/myexe2.c
@@ -0,0 +1,3 @@
+extern int mylibA();
+extern int mylibD();
+int main() { return mylibA() + mylibD(); }
diff --git a/Tests/PDBDirectoryAndName/mylibA.c b/Tests/PDBDirectoryAndName/mylibA.c
new file mode 100644
index 0000000..f4c553f
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/mylibA.c
@@ -0,0 +1 @@
+__declspec(dllexport) int mylibA() { return 1; }
diff --git a/Tests/PDBDirectoryAndName/mylibB.c b/Tests/PDBDirectoryAndName/mylibB.c
new file mode 100644
index 0000000..2040c67
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/mylibB.c
@@ -0,0 +1 @@
+int mylibB() { return -1; }
diff --git a/Tests/PDBDirectoryAndName/mylibC.c b/Tests/PDBDirectoryAndName/mylibC.c
new file mode 100644
index 0000000..adf7c70
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/mylibC.c
@@ -0,0 +1 @@
+__declspec(dllexport) int mylibC() { return 1; }
diff --git a/Tests/PDBDirectoryAndName/mylibD.c b/Tests/PDBDirectoryAndName/mylibD.c
new file mode 100644
index 0000000..efa8a82
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/mylibD.c
@@ -0,0 +1 @@
+int mylibD() { return -1; }
-- 
cgit v0.12


From b294457e2b96f40d01a22b867666277495977fa8 Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Tue, 25 Sep 2012 14:29:41 -0400
Subject: Verify that PDB_(NAME|OUTPUT_DIRECTORY) are honored in test

Teach the PDBDirectoryAndName test to check that the .pdb files appear
where expected.
---
 Tests/PDBDirectoryAndName/CMakeLists.txt   | 26 ++++++++++++++++++++++++++
 Tests/PDBDirectoryAndName/check_pdbs.cmake | 10 ++++++++++
 2 files changed, 36 insertions(+)
 create mode 100644 Tests/PDBDirectoryAndName/check_pdbs.cmake

diff --git a/Tests/PDBDirectoryAndName/CMakeLists.txt b/Tests/PDBDirectoryAndName/CMakeLists.txt
index ef1cae1..a9d46ca 100644
--- a/Tests/PDBDirectoryAndName/CMakeLists.txt
+++ b/Tests/PDBDirectoryAndName/CMakeLists.txt
@@ -5,33 +5,40 @@ if(NOT MSVC)
     MESSAGE(FATAL_ERROR "The PDB file test works only with MSVC")
 endif()
 
+set(my_targets "")
+
 add_library(mylibA SHARED mylibA.c)
 set_target_properties(mylibA PROPERTIES
     PDB_NAME "mylibA_Special"
     PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibA_PDB"
 )
+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"
 )
+list(APPEND my_targets mylibB)
 
 add_library(mylibC SHARED mylibC.c)
 set_target_properties(mylibC PROPERTIES
     PDB_NAME "mylibC_Special"
 )
+list(APPEND my_targets mylibC)
 
 add_library(mylibD STATIC mylibD.c)
 set_target_properties(mylibD PROPERTIES
     PDB_NAME "mylibD_Special"
 )
+list(APPEND my_targets mylibD)
 
 add_executable(myexe myexe.c)
 set_target_properties(myexe PROPERTIES
     PDB_NAME "myexe_Special"
     PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/myexe_PDB"
 )
+list(APPEND my_targets myexe)
 
 target_link_libraries(myexe mylibA mylibB mylibC mylibD)
 
@@ -39,5 +46,24 @@ add_executable(myexe2 myexe2.c)
 set_target_properties(myexe2 PROPERTIES
     PDB_NAME "myexe2_Special"
 )
+list(APPEND my_targets myexe2)
 
 target_link_libraries(myexe2 mylibA mylibD)
+
+#-----------------------------------------------------------------------------
+# Check that PDB files actually appear where expected.
+
+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_dir)
+    set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR})
+  endif()
+  list(APPEND pdbs ${pdb_dir}/${CMAKE_CFG_INTDIR}/${pdb_name}.pdb)
+endforeach()
+add_custom_target(check_pdbs ALL VERBATIM
+  COMMAND ${CMAKE_COMMAND} -Dconfig=$<CONFIGURATION> "-Dpdbs=${pdbs}"
+                           -P ${CMAKE_CURRENT_SOURCE_DIR}/check_pdbs.cmake
+  )
+add_dependencies(check_pdbs ${my_targets})
diff --git a/Tests/PDBDirectoryAndName/check_pdbs.cmake b/Tests/PDBDirectoryAndName/check_pdbs.cmake
new file mode 100644
index 0000000..89cdb3c
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/check_pdbs.cmake
@@ -0,0 +1,10 @@
+if(NOT "${config}" MATCHES "[Dd][Ee][Bb]")
+  return()
+endif()
+foreach(pdb ${pdbs})
+  if(EXISTS "${pdb}")
+    message(STATUS "PDB Exists: ${pdb}")
+  else()
+    message(SEND_ERROR "PDB MISSING: ${pdb}")
+  endif()
+endforeach()
-- 
cgit v0.12


From efc83b369b26624e7f0fb90d9125ef5ec6d1f7fa Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Tue, 25 Sep 2012 14:36:03 -0400
Subject: Document that PDB_(NAME|OUTPUT_DIRECTORY) are ignored for VS 6

---
 Source/cmTarget.cxx                      | 16 ++++++++++++----
 Tests/PDBDirectoryAndName/CMakeLists.txt |  5 +++++
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index b932afc..64950d8 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -746,12 +746,16 @@ void cmTarget::DefineProperties(cmake *cm)
      "Output name for MS debug symbols .pdb file.",
      "Set the base name for debug symbols file created for an "
      "executable or library target.  "
-     "If not set, the logical target name is used by default.");
+     "If not set, the logical target name is used by default.  "
+     "\n"
+     "This property is not implemented by the Visual Studio 6 generator.");
 
   cm->DefineProperty
     ("PDB_NAME_<CONFIG>", cmProperty::TARGET,
      "Per-configuration name for MS debug symbols .pdb file.  ",
-     "This is the configuration-specific version of PDB_NAME.");
+     "This is the configuration-specific version of PDB_NAME.  "
+     "\n"
+     "This property is not implemented by the Visual Studio 6 generator.");
 
   cm->DefineProperty
     ("PRE_INSTALL_SCRIPT", cmProperty::TARGET,
@@ -1208,7 +1212,9 @@ void cmTarget::DefineProperties(cmake *cm)
      "This property specifies the directory into which the MS debug symbols "
      "will be placed.  "
      "This property is initialized by the value of the variable "
-     "CMAKE_PDB_OUTPUT_DIRECTORY if it is set when a target is created.");
+     "CMAKE_PDB_OUTPUT_DIRECTORY if it is set when a target is created."
+     "\n"
+     "This property is not implemented by the Visual Studio 6 generator.");
   cm->DefineProperty
     ("PDB_OUTPUT_DIRECTORY_<CONFIG>", cmProperty::TARGET,
      "Per-configuration output directory for MS debug symbols .pdb files.",
@@ -1217,7 +1223,9 @@ void cmTarget::DefineProperties(cmake *cm)
      "a per-configuration subdirectory to the specified directory. "
      "This property is initialized by the value of the variable "
      "CMAKE_PDB_OUTPUT_DIRECTORY_<CONFIG> "
-     "if it is set when a target is created.");
+     "if it is set when a target is created."
+     "\n"
+     "This property is not implemented by the Visual Studio 6 generator.");
 
   cm->DefineProperty
     ("ARCHIVE_OUTPUT_NAME", cmProperty::TARGET,
diff --git a/Tests/PDBDirectoryAndName/CMakeLists.txt b/Tests/PDBDirectoryAndName/CMakeLists.txt
index a9d46ca..865d278 100644
--- a/Tests/PDBDirectoryAndName/CMakeLists.txt
+++ b/Tests/PDBDirectoryAndName/CMakeLists.txt
@@ -53,6 +53,11 @@ target_link_libraries(myexe2 mylibA mylibD)
 #-----------------------------------------------------------------------------
 # Check that PDB files actually appear where expected.
 
+# The PDB_NAME and PDB_OUTPUT_DIRECTORY options do not work in VS 6.
+if("${CMAKE_GENERATOR}" MATCHES "Visual Studio 6")
+  return()
+endif()
+
 set(pdbs "")
 foreach(t ${my_targets})
   get_property(pdb_name TARGET ${t} PROPERTY PDB_NAME)
-- 
cgit v0.12


From 2ccca05fade0014dbfbce906b20ab4073ecd8d9c Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Sat, 29 Sep 2012 06:36:46 -0400
Subject: Run PDBDirectoryAndName test on MSVC and Intel

Move it out of the condition that also accepts MinGW/MSYS.
Teach the test to allow the Intel for Windows compiler but
do not verify the results because the compiler does not
seem to write PDB output in all cases.
---
 Tests/CMakeLists.txt                     | 2 +-
 Tests/PDBDirectoryAndName/CMakeLists.txt | 9 +++++++--
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 4d071cb..ae69ce8 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -1254,12 +1254,12 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
 
   if(CMAKE_TEST_MSVC)
     ADD_TEST_MACRO(ForceInclude foo)
+    ADD_TEST_MACRO(PDBDirectoryAndName myexe)
     ADD_TEST_MACRO(PrecompiledHeader foo)
   endif()
   if(CMAKE_TEST_MSVC OR
       "${CMAKE_TEST_GENERATOR}" MATCHES "(MSYS|MinGW) Makefiles")
     ADD_TEST_MACRO(ModuleDefinition example_exe)
-    ADD_TEST_MACRO(PDBDirectoryAndName myexe)
   endif()
 
   ADD_TEST_MACRO(CheckCompilerRelatedVariables CheckCompilerRelatedVariables)
diff --git a/Tests/PDBDirectoryAndName/CMakeLists.txt b/Tests/PDBDirectoryAndName/CMakeLists.txt
index 865d278..bc2f013 100644
--- a/Tests/PDBDirectoryAndName/CMakeLists.txt
+++ b/Tests/PDBDirectoryAndName/CMakeLists.txt
@@ -1,8 +1,9 @@
 cmake_minimum_required(VERSION 2.8)
 project(PDBDirectoryAndName C)
 
-if(NOT MSVC)
-    MESSAGE(FATAL_ERROR "The PDB file test works only with MSVC")
+# Make sure the proper compiler is in use.
+if(NOT MSVC AND NOT "${CMAKE_C_COMPILER_ID}" MATCHES "^(Intel)$")
+  message(FATAL_ERROR "The PDBDirectoryAndName test works only with MSVC or Intel")
 endif()
 
 set(my_targets "")
@@ -57,6 +58,10 @@ target_link_libraries(myexe2 mylibA mylibD)
 if("${CMAKE_GENERATOR}" MATCHES "Visual Studio 6")
   return()
 endif()
+# PDB output not fully implemented for Intel
+if("${CMAKE_C_COMPILER_ID}" MATCHES "^(Intel)$")
+  return()
+endif()
 
 set(pdbs "")
 foreach(t ${my_targets})
-- 
cgit v0.12