diff options
author | Yuchen Deng <loaden@gmail.com> | 2012-09-25 01:30:42 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2012-09-25 19:23:35 (GMT) |
commit | 3f60dbf1484575f4c28a15c89e1af071648c8f2d (patch) | |
tree | 2ff89c5574c9515a4f1a61d210dfbcc7b020af56 | |
parent | d550801a3df96b991caf918435025aa233130bb4 (diff) | |
download | CMake-3f60dbf1484575f4c28a15c89e1af071648c8f2d.zip CMake-3f60dbf1484575f4c28a15c89e1af071648c8f2d.tar.gz CMake-3f60dbf1484575f4c28a15c89e1af071648c8f2d.tar.bz2 |
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>
-rw-r--r-- | Source/cmDocumentVariables.cxx | 9 | ||||
-rw-r--r-- | Source/cmLocalVisualStudio7Generator.cxx | 6 | ||||
-rw-r--r-- | Source/cmMakefileExecutableTargetGenerator.cxx | 7 | ||||
-rw-r--r-- | Source/cmMakefileLibraryTargetGenerator.cxx | 6 | ||||
-rw-r--r-- | Source/cmMakefileTargetGenerator.cxx | 2 | ||||
-rw-r--r-- | Source/cmNinjaTargetGenerator.cxx | 4 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 131 | ||||
-rw-r--r-- | Source/cmTarget.h | 7 | ||||
-rw-r--r-- | Source/cmVisualStudio10TargetGenerator.cxx | 8 | ||||
-rw-r--r-- | Tests/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Tests/PDBDirectoryAndName/CMakeLists.txt | 43 | ||||
-rw-r--r-- | Tests/PDBDirectoryAndName/myexe.c | 5 | ||||
-rw-r--r-- | Tests/PDBDirectoryAndName/myexe2.c | 3 | ||||
-rw-r--r-- | Tests/PDBDirectoryAndName/mylibA.c | 1 | ||||
-rw-r--r-- | Tests/PDBDirectoryAndName/mylibB.c | 1 | ||||
-rw-r--r-- | Tests/PDBDirectoryAndName/mylibC.c | 1 | ||||
-rw-r--r-- | Tests/PDBDirectoryAndName/mylibD.c | 1 |
17 files changed, 220 insertions, 16 deletions
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; } |