Merge topic 'msvc-compiler-pdb-files'

fba51b09 MSVC: Add properties to configure compiler PDB files (#14762)
3737860a cmTarget: Add per-config compilation info
718a9532 cmTarget: Refactor ComputePDBOutputDir interface
aae5184c Help: Refactor PDB_NAME and PDB_OUTPUT_DIRECTORY docs
b4aac0ca Makefile: Fix per-config linker PDB output directory
This commit is contained in:
Brad King 2014-02-26 09:38:51 -05:00 committed by CMake Topic Stage
commit 6223621e9a
27 changed files with 331 additions and 33 deletions

View File

@ -100,6 +100,10 @@ Properties on Targets
/prop_tgt/COMPILE_DEFINITIONS /prop_tgt/COMPILE_DEFINITIONS
/prop_tgt/COMPILE_FLAGS /prop_tgt/COMPILE_FLAGS
/prop_tgt/COMPILE_OPTIONS /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_OUTPUT_NAME
/prop_tgt/CONFIG_POSTFIX /prop_tgt/CONFIG_POSTFIX
/prop_tgt/DEBUG_POSTFIX /prop_tgt/DEBUG_POSTFIX

View File

@ -198,6 +198,8 @@ Variables that Control the Build
/variable/CMAKE_AUTOUIC /variable/CMAKE_AUTOUIC
/variable/CMAKE_AUTOUIC_OPTIONS /variable/CMAKE_AUTOUIC_OPTIONS
/variable/CMAKE_BUILD_WITH_INSTALL_RPATH /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_CONFIG_POSTFIX
/variable/CMAKE_DEBUG_POSTFIX /variable/CMAKE_DEBUG_POSTFIX
/variable/CMAKE_EXE_LINKER_FLAGS_CONFIG /variable/CMAKE_EXE_LINKER_FLAGS_CONFIG

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -7,7 +7,5 @@ linker for an executable or shared library target.
This property specifies the base name for the debug symbols file. This property specifies the base name for the debug symbols file.
If not set, the logical target name is used by default. If not set, the logical target name is used by default.
.. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_NAME`
.. include:: PDB_NOTE.txt .. include:: PDB_NOTE.txt
This property is not implemented by the :generator:`Visual Studio 6`
generator.

View File

@ -6,5 +6,5 @@ generated by the linker for an executable or shared library target.
This is the configuration-specific version of :prop_tgt:`PDB_NAME`. This is the configuration-specific version of :prop_tgt:`PDB_NAME`.
This property is not implemented by the :generator:`Visual Studio 6` .. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_NAME_<CONFIG>`
generator. .. include:: PDB_NOTE.txt

View File

@ -3,6 +3,10 @@
is invoked to produce them so they have no linker-generated ``.pdb`` file is invoked to produce them so they have no linker-generated ``.pdb`` file
containing debug symbols. containing debug symbols.
The compiler-generated program database files specified by the MSVC The linker-generated program database files are specified by the
``/Fd`` flag are not the same as linker-generated program database ``/pdb`` linker flag and are not the same as compiler-generated
files and so are not influenced by this property. program database files specified by the ``/Fd`` compiler flag.
Use the |COMPILE_PDB_XXX| property to specify the latter.
This property is not implemented by the :generator:`Visual Studio 6`
generator.

View File

@ -9,7 +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 value of the :variable:`CMAKE_PDB_OUTPUT_DIRECTORY` variable if it is
set when a target is created. set when a target is created.
.. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY`
.. include:: PDB_NOTE.txt .. include:: PDB_NOTE.txt
This property is not implemented by the :generator:`Visual Studio 6`
generator.

View File

@ -11,5 +11,5 @@ property is initialized by the value of the
:variable:`CMAKE_PDB_OUTPUT_DIRECTORY_<CONFIG>` variable if it is :variable:`CMAKE_PDB_OUTPUT_DIRECTORY_<CONFIG>` variable if it is
set when a target is created. set when a target is created.
This property is not implemented by the :generator:`Visual Studio 6` .. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY_<CONFIG>`
generator. .. include:: PDB_NOTE.txt

View File

@ -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``).

View File

@ -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.

View File

@ -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.

View File

@ -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}_CREATE_STATIC_LIBRARY "<CMAKE_LINKER> /lib ${CMAKE_CL_NOLOGO} <LINK_FLAGS> /out:<TARGET> <OBJECTS> ")
set(CMAKE_${lang}_COMPILE_OBJECT 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 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}") "<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 set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE

View File

@ -901,6 +901,13 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable,
return replaceValues.TargetPDB; return replaceValues.TargetPDB;
} }
} }
if(replaceValues.TargetCompilePDB)
{
if(variable == "TARGET_COMPILE_PDB")
{
return replaceValues.TargetCompilePDB;
}
}
if(replaceValues.DependencyFile ) if(replaceValues.DependencyFile )
{ {
if(variable == "DEP_FILE") if(variable == "DEP_FILE")

View File

@ -245,6 +245,7 @@ public:
} }
cmTarget* CMTarget; cmTarget* CMTarget;
const char* TargetPDB; const char* TargetPDB;
const char* TargetCompilePDB;
const char* TargetVersionMajor; const char* TargetVersionMajor;
const char* TargetVersionMinor; const char* TargetVersionMinor;
const char* Language; const char* Language;

View File

@ -660,7 +660,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
switch(target.GetType()) switch(target.GetType())
{ {
case cmTarget::OBJECT_LIBRARY: case cmTarget::OBJECT_LIBRARY:
targetBuilds = false; // TODO: PDB for object library? targetBuilds = false; // no manifest tool for object library
case cmTarget::STATIC_LIBRARY: case cmTarget::STATIC_LIBRARY:
projectType = "typeStaticLibrary"; projectType = "typeStaticLibrary";
configType = "4"; configType = "4";
@ -846,6 +846,17 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
targetOptions.OutputFlagMap(fout, "\t\t\t\t"); targetOptions.OutputFlagMap(fout, "\t\t\t\t");
targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n", "CXX"); targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n", "CXX");
fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n"; 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 fout << "/>\n"; // end of <Tool Name=VCCLCompilerTool
tool = "VCCustomBuildTool"; tool = "VCCustomBuildTool";
if(this->FortranProject) if(this->FortranProject)

View File

@ -129,7 +129,11 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
} }
} }
std::string pdbOutputPath = this->Target->GetPDBDirectory(); 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()); cmSystemTools::MakeDirectory(pdbOutputPath.c_str());
pdbOutputPath += "/"; pdbOutputPath += "/";

View File

@ -321,7 +321,11 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
} }
} }
std::string pdbOutputPath = this->Target->GetPDBDirectory(); 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()); cmSystemTools::MakeDirectory(pdbOutputPath.c_str());
pdbOutputPath += "/"; pdbOutputPath += "/";

View File

@ -624,9 +624,11 @@ cmMakefileTargetGenerator
std::string targetOutPathReal; std::string targetOutPathReal;
std::string targetOutPathPDB; std::string targetOutPathPDB;
std::string targetOutPathCompilePDB;
{ {
std::string targetFullPathReal; std::string targetFullPathReal;
std::string targetFullPathPDB; std::string targetFullPathPDB;
std::string targetFullPathCompilePDB;
if(this->Target->GetType() == cmTarget::EXECUTABLE || if(this->Target->GetType() == cmTarget::EXECUTABLE ||
this->Target->GetType() == cmTarget::STATIC_LIBRARY || this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
this->Target->GetType() == cmTarget::SHARED_LIBRARY || this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
@ -638,12 +640,26 @@ cmMakefileTargetGenerator
targetFullPathPDB += "/"; targetFullPathPDB += "/";
targetFullPathPDB += this->Target->GetPDBName(this->ConfigName); 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(), targetOutPathReal = this->Convert(targetFullPathReal.c_str(),
cmLocalGenerator::START_OUTPUT, cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::SHELL); cmLocalGenerator::SHELL);
targetOutPathPDB = targetOutPathPDB =
this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::NONE, this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::NONE,
cmLocalGenerator::SHELL); cmLocalGenerator::SHELL);
targetOutPathCompilePDB =
this->Convert(targetFullPathCompilePDB.c_str(),
cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::SHELL);
} }
cmLocalGenerator::RuleVariables vars; cmLocalGenerator::RuleVariables vars;
vars.RuleLauncher = "RULE_LAUNCH_COMPILE"; vars.RuleLauncher = "RULE_LAUNCH_COMPILE";
@ -651,6 +667,7 @@ cmMakefileTargetGenerator
vars.Language = lang; vars.Language = lang;
vars.Target = targetOutPathReal.c_str(); vars.Target = targetOutPathReal.c_str();
vars.TargetPDB = targetOutPathPDB.c_str(); vars.TargetPDB = targetOutPathPDB.c_str();
vars.TargetCompilePDB = targetOutPathCompilePDB.c_str();
vars.Source = sourceFile.c_str(); vars.Source = sourceFile.c_str();
std::string shellObj = std::string shellObj =
this->Convert(obj.c_str(), this->Convert(obj.c_str(),

View File

@ -320,6 +320,7 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const
mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID")) mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID"))
{ {
std::string pdbPath; std::string pdbPath;
std::string compilePdbPath;
if(this->Target->GetType() == cmTarget::EXECUTABLE || if(this->Target->GetType() == cmTarget::EXECUTABLE ||
this->Target->GetType() == cmTarget::STATIC_LIBRARY || this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
this->Target->GetType() == cmTarget::SHARED_LIBRARY || this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
@ -329,11 +330,25 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const
pdbPath += "/"; pdbPath += "/";
pdbPath += this->Target->GetPDBName(this->GetConfigName()); 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( vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
ConvertToNinjaPath(pdbPath.c_str()).c_str(), ConvertToNinjaPath(pdbPath.c_str()).c_str(),
cmLocalGenerator::SHELL); cmLocalGenerator::SHELL);
vars["TARGET_COMPILE_PDB"] =
this->GetLocalGenerator()->ConvertToOutputFormat(
ConvertToNinjaPath(compilePdbPath.c_str()).c_str(),
cmLocalGenerator::SHELL);
EnsureParentDirectoryExists(pdbPath); EnsureParentDirectoryExists(pdbPath);
EnsureParentDirectoryExists(compilePdbPath);
return true; return true;
} }
return false; return false;
@ -362,6 +377,7 @@ cmNinjaTargetGenerator
vars.Object = "$out"; vars.Object = "$out";
vars.Defines = "$DEFINES"; vars.Defines = "$DEFINES";
vars.TargetPDB = "$TARGET_PDB"; vars.TargetPDB = "$TARGET_PDB";
vars.TargetCompilePDB = "$TARGET_COMPILE_PDB";
vars.ObjectDir = "$OBJECT_DIR"; vars.ObjectDir = "$OBJECT_DIR";
cmMakefile* mf = this->GetMakefile(); cmMakefile* mf = this->GetMakefile();

View File

@ -71,6 +71,12 @@ struct cmTarget::ImportInfo
cmTarget::LinkInterface LinkInterface; cmTarget::LinkInterface LinkInterface;
}; };
//----------------------------------------------------------------------------
struct cmTarget::CompileInfo
{
std::string CompilePdbDir;
};
struct TargetConfigPair : public std::pair<cmTarget const* , std::string> { struct TargetConfigPair : public std::pair<cmTarget const* , std::string> {
TargetConfigPair(cmTarget const* tgt, const std::string &config) TargetConfigPair(cmTarget const* tgt, const std::string &config)
: std::pair<cmTarget const* , std::string>(tgt, config) {} : std::pair<cmTarget const* , std::string>(tgt, config) {}
@ -119,6 +125,9 @@ public:
ImportInfoMapType; ImportInfoMapType;
ImportInfoMapType ImportInfoMap; ImportInfoMapType ImportInfoMap;
typedef std::map<std::string, cmTarget::CompileInfo> CompileInfoMapType;
CompileInfoMapType CompileInfoMap;
// Cache link implementation computation from each configuration. // Cache link implementation computation from each configuration.
typedef std::map<TargetConfigPair, typedef std::map<TargetConfigPair,
cmTarget::LinkImplementation> LinkImplMapType; cmTarget::LinkImplementation> LinkImplMapType;
@ -270,6 +279,7 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->SetPropertyDefault("LIBRARY_OUTPUT_DIRECTORY", 0); this->SetPropertyDefault("LIBRARY_OUTPUT_DIRECTORY", 0);
this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", 0); this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", 0);
this->SetPropertyDefault("PDB_OUTPUT_DIRECTORY", 0); this->SetPropertyDefault("PDB_OUTPUT_DIRECTORY", 0);
this->SetPropertyDefault("COMPILE_PDB_OUTPUT_DIRECTORY", 0);
this->SetPropertyDefault("Fortran_FORMAT", 0); this->SetPropertyDefault("Fortran_FORMAT", 0);
this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0); this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0);
this->SetPropertyDefault("GNUtoMS", 0); this->SetPropertyDefault("GNUtoMS", 0);
@ -298,6 +308,7 @@ void cmTarget::SetMakefile(cmMakefile* mf)
"LIBRARY_OUTPUT_DIRECTORY_", "LIBRARY_OUTPUT_DIRECTORY_",
"RUNTIME_OUTPUT_DIRECTORY_", "RUNTIME_OUTPUT_DIRECTORY_",
"PDB_OUTPUT_DIRECTORY_", "PDB_OUTPUT_DIRECTORY_",
"COMPILE_PDB_OUTPUT_DIRECTORY_",
"MAP_IMPORTED_CONFIG_", "MAP_IMPORTED_CONFIG_",
0}; 0};
for(std::vector<std::string>::iterator ci = configNames.begin(); for(std::vector<std::string>::iterator ci = configNames.begin();
@ -2361,7 +2372,7 @@ cmTarget::OutputInfo const* cmTarget::GetOutputInfo(const char* config) const
OutputInfo info; OutputInfo info;
this->ComputeOutputDir(config, false, info.OutDir); this->ComputeOutputDir(config, false, info.OutDir);
this->ComputeOutputDir(config, true, info.ImpDir); this->ComputeOutputDir(config, true, info.ImpDir);
if(!this->ComputePDBOutputDir(config, info.PdbDir)) if(!this->ComputePDBOutputDir("PDB", config, info.PdbDir))
{ {
info.PdbDir = info.OutDir; info.PdbDir = info.OutDir;
} }
@ -2371,6 +2382,45 @@ cmTarget::OutputInfo const* cmTarget::GetOutputInfo(const char* config) const
return &i->second; return &i->second;
} }
//----------------------------------------------------------------------------
cmTarget::CompileInfo const* cmTarget::GetCompileInfo(const char* config) const
{
// There is no compile information for imported targets.
if(this->IsImported())
{
return 0;
}
if(this->GetType() > cmTarget::OBJECT_LIBRARY)
{
std::string msg = "cmTarget::GetCompileInfo called for ";
msg += this->GetName();
msg += " which has type ";
msg += cmTarget::GetTargetTypeName(this->GetType());
this->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR, msg);
abort();
return 0;
}
// Lookup/compute/cache the compile information for this configuration.
std::string config_upper;
if(config && *config)
{
config_upper = cmSystemTools::UpperCase(config);
}
typedef cmTargetInternals::CompileInfoMapType CompileInfoMapType;
CompileInfoMapType::const_iterator i =
this->Internal->CompileInfoMap.find(config_upper);
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;
}
return &i->second;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string cmTarget::GetDirectory(const char* config, bool implib) const std::string cmTarget::GetDirectory(const char* config, bool implib) const
{ {
@ -2400,6 +2450,16 @@ std::string cmTarget::GetPDBDirectory(const char* config) const
return ""; 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 const char* cmTarget::GetLocation(const char* config) const
{ {
@ -3060,6 +3120,49 @@ std::string cmTarget::GetPDBName(const char* config) const
return prefix+base+".pdb"; 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 bool cmTarget::HasSOName(const char* config) const
{ {
@ -4005,13 +4108,13 @@ bool cmTarget::ComputeOutputDir(const char* config,
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmTarget::ComputePDBOutputDir(const char* config, std::string& out) const bool cmTarget::ComputePDBOutputDir(const char* kind, const char* config,
std::string& out) const
{ {
// Look for a target property defining the target output directory // Look for a target property defining the target output directory
// based on the target type. // based on the target type.
std::string targetTypeName = "PDB";
const char* propertyName = 0; const char* propertyName = 0;
std::string propertyNameStr = targetTypeName; std::string propertyNameStr = kind;
if(!propertyNameStr.empty()) if(!propertyNameStr.empty())
{ {
propertyNameStr += "_OUTPUT_DIRECTORY"; propertyNameStr += "_OUTPUT_DIRECTORY";
@ -4021,7 +4124,7 @@ bool cmTarget::ComputePDBOutputDir(const char* config, std::string& out) const
// Check for a per-configuration output directory target property. // Check for a per-configuration output directory target property.
std::string configUpper = cmSystemTools::UpperCase(config? config : ""); std::string configUpper = cmSystemTools::UpperCase(config? config : "");
const char* configProp = 0; const char* configProp = 0;
std::string configPropStr = targetTypeName; std::string configPropStr = kind;
if(!configPropStr.empty()) if(!configPropStr.empty())
{ {
configPropStr += "_OUTPUT_DIRECTORY_"; configPropStr += "_OUTPUT_DIRECTORY_";

View File

@ -320,7 +320,13 @@ public:
If the configuration name is given then the generator will add its If the configuration name is given then the generator will add its
subdirectory for that configuration. Otherwise just the canonical subdirectory for that configuration. Otherwise just the canonical
pdb output directory is given. */ pdb output directory is given. */
std::string GetPDBDirectory(const char* config = 0) const; 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 /** Get the location of the target in the build tree for the given
configuration. This location is suitable for use as the LOCATION configuration. This location is suitable for use as the LOCATION
@ -350,7 +356,13 @@ public:
const char* config=0, bool implib = false) const; const char* config=0, bool implib = false) const;
/** Get the name of the pdb file for the target. */ /** Get the name of the pdb file for the target. */
std::string GetPDBName(const char* config=0) const; 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. */ /** Whether this library has soname enabled and platform supports it. */
bool HasSOName(const char* config) const; bool HasSOName(const char* config) const;
@ -685,7 +697,8 @@ private:
OutputInfo const* GetOutputInfo(const char* config) const; OutputInfo const* GetOutputInfo(const char* config) const;
bool bool
ComputeOutputDir(const char* config, bool implib, std::string& out) const; ComputeOutputDir(const char* config, bool implib, std::string& out) const;
bool ComputePDBOutputDir(const char* config, std::string& out) const; bool ComputePDBOutputDir(const char* kind, const char* config,
std::string& out) const;
// Cache import information from properties for each configuration. // Cache import information from properties for each configuration.
struct ImportInfo; struct ImportInfo;
@ -694,6 +707,10 @@ private:
void ComputeImportInfo(std::string const& desired_config, ImportInfo& info, void ComputeImportInfo(std::string const& desired_config, ImportInfo& info,
cmTarget const* head) const; cmTarget const* head) const;
// Cache target compile paths for each configuration.
struct CompileInfo;
CompileInfo const* GetCompileInfo(const char* config) const;
mutable cmTargetLinkInformationMap LinkInformation; mutable cmTargetLinkInformationMap LinkInformation;
void CheckPropertyCompatibility(cmComputeLinkInformation *info, void CheckPropertyCompatibility(cmComputeLinkInformation *info,
const char* config) const; const char* config) const;

View File

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

View File

@ -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") message(FATAL_ERROR "The PDBDirectoryAndName test works only with MSVC or Intel")
endif() 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 "") set(my_targets "")
add_library(mylibA SHARED mylibA.c) add_library(mylibA SHARED mylibA.c)
@ -17,12 +24,12 @@ list(APPEND my_targets mylibA)
add_library(mylibB STATIC mylibB.c) add_library(mylibB STATIC mylibB.c)
set_target_properties(mylibB PROPERTIES set_target_properties(mylibB PROPERTIES
PDB_NAME "mylibB_Special" COMPILE_PDB_NAME "mylibB_Special"
PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibB_PDB" COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibB_PDB"
) )
# TODO: The only .pdb available for a static library is that generated if(NOT NO_COMPILE_PDB)
# by the compiler /Fd option which is not the same as the linker /pdb. list(APPEND my_targets mylibB)
# list(APPEND my_targets mylibB) endif()
add_library(mylibC SHARED mylibC.c) add_library(mylibC SHARED mylibC.c)
set_target_properties(mylibC PROPERTIES set_target_properties(mylibC PROPERTIES
@ -32,10 +39,11 @@ list(APPEND my_targets mylibC)
add_library(mylibD STATIC mylibD.c) add_library(mylibD STATIC mylibD.c)
set_target_properties(mylibD PROPERTIES set_target_properties(mylibD PROPERTIES
PDB_NAME "mylibD_Special" COMPILE_PDB_NAME "mylibD_Special"
) )
# TODO: See comment for mylibB. if(NOT NO_COMPILE_PDB)
# list(APPEND my_targets mylibD) list(APPEND my_targets mylibD)
endif()
add_executable(myexe myexe.c) add_executable(myexe myexe.c)
set_target_properties(myexe PROPERTIES set_target_properties(myexe PROPERTIES
@ -66,6 +74,12 @@ set(pdbs "")
foreach(t ${my_targets}) foreach(t ${my_targets})
get_property(pdb_name TARGET ${t} PROPERTY PDB_NAME) get_property(pdb_name TARGET ${t} PROPERTY PDB_NAME)
get_property(pdb_dir TARGET ${t} PROPERTY PDB_OUTPUT_DIRECTORY) 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) if(NOT pdb_dir)
set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR}) set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR})
endif() endif()