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>
This commit is contained in:
parent
d550801a3d
commit
3f60dbf148
|
@ -1210,6 +1210,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
|
|||
false,
|
||||
"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.",
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -335,7 +335,7 @@ 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());
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ struct cmTarget::OutputInfo
|
|||
{
|
||||
std::string OutDir;
|
||||
std::string ImpDir;
|
||||
std::string PdbDir;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -740,6 +741,18 @@ void cmTarget::DefineProperties(cmake *cm)
|
|||
"This is a configuration-specific version of OUTPUT_NAME. "
|
||||
"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.",
|
||||
|
@ -1189,6 +1202,23 @@ void cmTarget::DefineProperties(cmake *cm)
|
|||
"Per-configuration output directory for RUNTIME target files.",
|
||||
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.",
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -2563,6 +2596,17 @@ std::string cmTarget::GetDirectory(const char* config, bool implib)
|
|||
return "";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -3879,6 +3945,65 @@ bool cmTarget::ComputeOutputDir(const char* config,
|
|||
return usesDefaultOutputDir;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 += "/";
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
|
@ -0,0 +1,5 @@
|
|||
extern int mylibA();
|
||||
extern int mylibB();
|
||||
extern int mylibC();
|
||||
extern int mylibD();
|
||||
int main() { return mylibA() + mylibB() + mylibC() + mylibD(); }
|
|
@ -0,0 +1,3 @@
|
|||
extern int mylibA();
|
||||
extern int mylibD();
|
||||
int main() { return mylibA() + mylibD(); }
|
|
@ -0,0 +1 @@
|
|||
__declspec(dllexport) int mylibA() { return 1; }
|
|
@ -0,0 +1 @@
|
|||
int mylibB() { return -1; }
|
|
@ -0,0 +1 @@
|
|||
__declspec(dllexport) int mylibC() { return 1; }
|
|
@ -0,0 +1 @@
|
|||
int mylibD() { return -1; }
|
Loading…
Reference in New Issue