diff options
author | Brad King <brad.king@kitware.com> | 2015-08-06 13:38:27 (GMT) |
---|---|---|
committer | CMake Topic Stage <kwrobot@kitware.com> | 2015-08-06 13:38:27 (GMT) |
commit | 55706506c7bd84ded84a85042ac8bd72f4506411 (patch) | |
tree | ecfaa680d3b0dc8fdd4cf06e7e4f61439ae47aae /Source | |
parent | 73e3de381d87a635e303e2076a46cb739466c1a4 (diff) | |
parent | a309409ead0bde721a17e8b3c4e89fe6a2181423 (diff) | |
download | CMake-55706506c7bd84ded84a85042ac8bd72f4506411.zip CMake-55706506c7bd84ded84a85042ac8bd72f4506411.tar.gz CMake-55706506c7bd84ded84a85042ac8bd72f4506411.tar.bz2 |
Merge topic 'use-generator-target'
a309409e cmOrderDirectories: Port to cmGeneratorTarget.
f83e8402 cmGeneratorTarget: Move CompileInfoMap from cmTarget.
b3f0e353 cmGeneratorTarget: Move GetCompilePDBDirectory from cmTarget.
34c43741 cmGeneratorTarget: Move GetOutputName from cmTarget.
4329a71c cmComputeLinkDepends: Port to cmGeneratorTarget.
c93230ac cmComputeLinkInformation: Port to cmGeneratorTarget.
ee26add4 cmGeneratorTarget: Move IsBundleOnApple from cmTarget.
c8a5f5ae cmMakefileTargetGenerator: Add accessor for GeneratorTarget.
f8076644 cmGeneratorTarget: Move GetLinkClosure from cmTarget.
7c809fa2 cmGeneratorTarget: Move GetLinkerLanguage from cmTarget.
6da99de3 cmGeneratorTarget: Move GetFrameworkDirectory from cmTarget.
d6bb319b cmGeneratorTarget: Move GetFullName from cmTarget.
7a460852 cmGeneratorTarget: Move GetAppBundleDirectory from cmTarget.
d560bfd2 cmGeneratorTarget: Move GetInstallNameDir* from cmTarget.
89e2a080 cmGeneratorTarget: Move GetMacContentDirectory from cmTarget.
62720e44 cmGeneratorTarget: Move GetFullNameComponents from cmTarget.
...
Diffstat (limited to 'Source')
38 files changed, 2463 insertions, 2393 deletions
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 26ca375..4840e89 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -276,7 +276,8 @@ std::string cmCommonTargetGenerator::GetFrameworkFlags(std::string const& l) std::string flags; const char* cfg = this->LocalGenerator->GetConfigName().c_str(); - if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg)) + if(cmComputeLinkInformation* cli = + this->GeneratorTarget->GetLinkInformation(cfg)) { std::vector<std::string> const& frameworks = cli->GetFrameworkPaths(); for(std::vector<std::string>::const_iterator i = frameworks.begin(); @@ -384,7 +385,7 @@ cmCommonTargetGenerator::GetLinkedTargetDirectories() const std::vector<std::string> dirs; std::set<cmTarget const*> emitted; if (cmComputeLinkInformation* cli = - this->Target->GetLinkInformation(this->ConfigName)) + this->GeneratorTarget->GetLinkInformation(this->ConfigName)) { cmComputeLinkInformation::ItemVector const& items = cli->GetItems(); for(cmComputeLinkInformation::ItemVector::const_iterator diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index abd9877..8ba8847 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -173,18 +173,19 @@ items that we know the linker will re-use automatically (shared libs). //---------------------------------------------------------------------------- cmComputeLinkDepends -::cmComputeLinkDepends(cmTarget const* target, const std::string& config) +::cmComputeLinkDepends(const cmGeneratorTarget* target, + const std::string& config) { // Store context information. this->Target = target; - this->Makefile = this->Target->GetMakefile(); + this->Makefile = this->Target->Target->GetMakefile(); this->GlobalGenerator = this->Makefile->GetGlobalGenerator(); this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance(); // The configuration being linked. this->HasConfig = !config.empty(); this->Config = (this->HasConfig)? config : std::string(); - this->LinkType = this->Target->ComputeLinkType(this->Config); + this->LinkType = this->Target->Target->ComputeLinkType(this->Config); // Enable debug mode if requested. this->DebugMode = this->Makefile->IsOn("CMAKE_LINK_DEPENDS_DEBUG_MODE"); @@ -363,7 +364,7 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe) { // Follow the target dependencies. if(cmTarget::LinkInterface const* iface = - entry.Target->GetLinkInterface(this->Config, this->Target)) + entry.Target->GetLinkInterface(this->Config, this->Target->Target)) { const bool isIface = entry.Target->GetType() == cmTarget::INTERFACE_LIBRARY; @@ -461,7 +462,7 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep) if(entry.Target) { if(cmTarget::LinkInterface const* iface = - entry.Target->GetLinkInterface(this->Config, this->Target)) + entry.Target->GetLinkInterface(this->Config, this->Target->Target)) { // Follow public and private dependencies transitively. this->FollowSharedDeps(index, iface, true); @@ -552,7 +553,7 @@ void cmComputeLinkDepends::AddDirectLinkEntries() { // Add direct link dependencies in this configuration. cmTarget::LinkImplementation const* impl = - this->Target->GetLinkImplementation(this->Config); + this->Target->Target->GetLinkImplementation(this->Config); this->AddLinkEntries(-1, impl->Libraries); for(std::vector<cmLinkItem>::const_iterator wi = impl->WrongConfigLibraries.begin(); @@ -634,7 +635,7 @@ cmTarget const* cmComputeLinkDepends::FindTargetToLink(int depender_index, const std::string& name) { // Look for a target in the scope of the depender. - cmTarget const* from = this->Target; + cmTarget const* from = this->Target->Target; if(depender_index >= 0) { if(cmTarget const* depender = this->EntryList[depender_index].Target) @@ -932,7 +933,7 @@ int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl) if(cmTarget const* target = this->EntryList[*ni].Target) { if(cmTarget::LinkInterface const* iface = - target->GetLinkInterface(this->Config, this->Target)) + target->GetLinkInterface(this->Config, this->Target->Target)) { if(iface->Multiplicity > count) { diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index 51a08c5..b925a4f 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -22,6 +22,7 @@ class cmComputeComponentGraph; class cmGlobalGenerator; class cmMakefile; +class cmGeneratorTarget; class cmTarget; class cmake; @@ -31,7 +32,8 @@ class cmake; class cmComputeLinkDepends { public: - cmComputeLinkDepends(cmTarget const* target, const std::string& config); + cmComputeLinkDepends(cmGeneratorTarget const* target, + const std::string& config); ~cmComputeLinkDepends(); // Basic information about each link item. @@ -57,7 +59,7 @@ public: private: // Context information. - cmTarget const* Target; + cmGeneratorTarget const* Target; cmMakefile* Makefile; cmGlobalGenerator const* GlobalGenerator; cmake* CMakeInstance; diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index e63b44f..c3f36af 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -19,6 +19,7 @@ #include "cmOutputConverter.h" #include "cmMakefile.h" #include "cmTarget.h" +#include "cmGeneratorTarget.h" #include "cmake.h" #include "cmAlgorithms.h" @@ -241,11 +242,12 @@ because this need be done only for shared libraries without soname-s. //---------------------------------------------------------------------------- cmComputeLinkInformation -::cmComputeLinkInformation(cmTarget const* target, const std::string& config) +::cmComputeLinkInformation(const cmGeneratorTarget* target, + const std::string& config) { // Store context information. this->Target = target; - this->Makefile = this->Target->GetMakefile(); + this->Makefile = this->Target->Target->GetMakefile(); this->GlobalGenerator = this->Makefile->GetGlobalGenerator(); this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance(); @@ -280,14 +282,14 @@ cmComputeLinkInformation // Check whether we should skip dependencies on shared library files. this->LinkDependsNoShared = - this->Target->GetPropertyAsBool("LINK_DEPENDS_NO_SHARED"); + this->Target->Target->GetPropertyAsBool("LINK_DEPENDS_NO_SHARED"); // On platforms without import libraries there may be a special flag // to use when creating a plugin (module) that obtains symbols from // the program that will load it. this->LoaderFlag = 0; if(!this->UseImportLibrary && - this->Target->GetType() == cmTarget::MODULE_LIBRARY) + this->Target->Target->GetType() == cmTarget::MODULE_LIBRARY) { std::string loader_flag_var = "CMAKE_SHARED_MODULE_LOADER_"; loader_flag_var += this->LinkLanguage; @@ -305,10 +307,10 @@ cmComputeLinkInformation // Get options needed to specify RPATHs. this->RuntimeUseChrpath = false; - if(this->Target->GetType() != cmTarget::STATIC_LIBRARY) + if(this->Target->Target->GetType() != cmTarget::STATIC_LIBRARY) { const char* tType = - ((this->Target->GetType() == cmTarget::EXECUTABLE)? + ((this->Target->Target->GetType() == cmTarget::EXECUTABLE)? "EXECUTABLE" : "SHARED_LIBRARY"); std::string rtVar = "CMAKE_"; rtVar += tType; @@ -321,6 +323,7 @@ cmComputeLinkInformation this->RuntimeAlways = (this->Makefile-> GetSafeDefinition("CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH")); + this->RuntimeUseChrpath = this->Target->IsChrpathUsed(config); // Get options needed to help find dependent libraries. @@ -373,9 +376,9 @@ cmComputeLinkInformation // Add the search path entries requested by the user to path ordering. this->OrderLinkerSearchPath - ->AddUserDirectories(this->Target->GetLinkDirectories()); + ->AddUserDirectories(this->Target->Target->GetLinkDirectories()); this->OrderRuntimeSearchPath - ->AddUserDirectories(this->Target->GetLinkDirectories()); + ->AddUserDirectories(this->Target->Target->GetLinkDirectories()); // Set up the implicit link directories. this->LoadImplicitLinkInfo(); @@ -403,12 +406,13 @@ cmComputeLinkInformation // order to support such projects we need to add the directories // containing libraries linked with a full path to the -L path. this->OldLinkDirMode = - this->Target->GetPolicyStatusCMP0003() != cmPolicies::NEW; + this->Target->Target->GetPolicyStatusCMP0003() != cmPolicies::NEW; if(this->OldLinkDirMode) { // Construct a mask to not bother with this behavior for link // directories already specified by the user. - std::vector<std::string> const& dirs = this->Target->GetLinkDirectories(); + std::vector<std::string> const& dirs = + this->Target->Target->GetLinkDirectories(); this->OldLinkDirMask.insert(dirs.begin(), dirs.end()); } @@ -514,7 +518,8 @@ bool cmComputeLinkInformation::Compute() // Restore the target link type so the correct system runtime // libraries are found. - const char* lss = this->Target->GetProperty("LINK_SEARCH_END_STATIC"); + const char* lss = + this->Target->Target->GetProperty("LINK_SEARCH_END_STATIC"); if(cmSystemTools::IsOn(lss)) { this->SetCurrentLinkType(LinkStatic); @@ -567,7 +572,7 @@ bool cmComputeLinkInformation::Compute() "name." ; this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(), - this->Target->GetBacktrace()); + this->Target->Target->GetBacktrace()); } return true; @@ -577,7 +582,8 @@ bool cmComputeLinkInformation::Compute() void cmComputeLinkInformation::AddImplicitLinkInfo() { // The link closure lists all languages whose implicit info is needed. - cmTarget::LinkClosure const* lc=this->Target->GetLinkClosure(this->Config); + cmGeneratorTarget::LinkClosure const* lc = + this->Target->GetLinkClosure(this->Config); for(std::vector<std::string>::const_iterator li = lc->Languages.begin(); li != lc->Languages.end(); ++li) { @@ -756,15 +762,16 @@ void cmComputeLinkInformation::AddSharedDepItem(std::string const& item, return; } + cmGeneratorTarget *gtgt = 0; + // Get a full path to the dependent shared library. // Add it to the runtime path computation so that the target being // linked will be able to find it. std::string lib; if(tgt) { - cmGeneratorTarget *gtgt = tgt->GetMakefile() - ->GetGlobalGenerator() - ->GetGeneratorTarget(tgt); + gtgt = tgt->GetMakefile()->GetGlobalGenerator()->GetGeneratorTarget(tgt); + lib = gtgt->GetFullPath(this->Config, this->UseImportLibrary); this->AddLibraryRuntimeInfo(lib, tgt); } @@ -790,9 +797,9 @@ void cmComputeLinkInformation::AddSharedDepItem(std::string const& item, } if(order) { - if(tgt) + if(gtgt) { - std::string soName = tgt->GetSOName(this->Config); + std::string soName = gtgt->GetSOName(this->Config); const char* soname = soName.empty()? 0 : soName.c_str(); order->AddRuntimeLibrary(lib, soname); } @@ -854,7 +861,8 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo() } // Lookup the starting link type from the target (linked statically?). - const char* lss = this->Target->GetProperty("LINK_SEARCH_START_STATIC"); + const char* lss = + this->Target->Target->GetProperty("LINK_SEARCH_START_STATIC"); this->StartLinkType = cmSystemTools::IsOn(lss)? LinkStatic : LinkShared; this->CurrentLinkType = this->StartLinkType; } @@ -1140,7 +1148,7 @@ void cmComputeLinkInformation::AddFullItem(std::string const& item) // Full path libraries should specify a valid library file name. // See documentation of CMP0008. std::string generator = this->GlobalGenerator->GetName(); - if(this->Target->GetPolicyStatusCMP0008() != cmPolicies::NEW && + if(this->Target->Target->GetPolicyStatusCMP0008() != cmPolicies::NEW && (generator.find("Visual Studio") != generator.npos || generator.find("Xcode") != generator.npos)) { @@ -1221,7 +1229,7 @@ bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item) } // Check the policy for whether we should use the approach below. - switch (this->Target->GetPolicyStatusCMP0060()) + switch (this->Target->Target->GetPolicyStatusCMP0060()) { case cmPolicies::WARN: if (this->CMP0060Warn) @@ -1531,7 +1539,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item, this->OrderLinkerSearchPath->AddLinkLibrary(item); // Produce any needed message. - switch(this->Target->GetPolicyStatusCMP0008()) + switch(this->Target->Target->GetPolicyStatusCMP0008()) { case cmPolicies::WARN: { @@ -1548,7 +1556,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item, << " " << item << "\n" << "which is a full-path but not a valid library file name."; this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(), - this->Target->GetBacktrace()); + this->Target->Target->GetBacktrace()); } } case cmPolicies::OLD: @@ -1566,7 +1574,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item, << " " << item << "\n" << "which is a full-path but not a valid library file name."; this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(), - this->Target->GetBacktrace()); + this->Target->Target->GetBacktrace()); } break; } @@ -1583,7 +1591,7 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories() } // Enforce policy constraints. - switch(this->Target->GetPolicyStatusCMP0003()) + switch(this->Target->Target->GetPolicyStatusCMP0003()) { case cmPolicies::WARN: if(!this->CMakeInstance->GetState() @@ -1594,7 +1602,7 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories() std::ostringstream w; this->PrintLinkPolicyDiagnosis(w); this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(), - this->Target->GetBacktrace()); + this->Target->Target->GetBacktrace()); } case cmPolicies::OLD: // OLD behavior is to add the paths containing libraries with @@ -1610,7 +1618,7 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories() e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0003) << "\n"; this->PrintLinkPolicyDiagnosis(e); this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(), - this->Target->GetBacktrace()); + this->Target->Target->GetBacktrace()); return false; } } @@ -1804,7 +1812,10 @@ cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath, // Try to get the soname of the library. Only files with this name // could possibly conflict. - std::string soName = target->GetSOName(this->Config); + cmGeneratorTarget *gtgt = target->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(target); + std::string soName = gtgt->GetSOName(this->Config); const char* soname = soName.empty()? 0 : soName.c_str(); // Include this library in the runtime path ordering. @@ -1911,23 +1922,24 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, // build tree. bool linking_for_install = (for_install || - this->Target->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")); + this->Target->Target->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")); bool use_install_rpath = - (outputRuntime && this->Target->HaveInstallTreeRPATH() && + (outputRuntime && this->Target->Target->HaveInstallTreeRPATH() && linking_for_install); bool use_build_rpath = - (outputRuntime && this->Target->HaveBuildTreeRPATH(this->Config) && + (outputRuntime && this->Target->Target->HaveBuildTreeRPATH(this->Config) && !linking_for_install); bool use_link_rpath = outputRuntime && linking_for_install && !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH") && - this->Target->GetPropertyAsBool("INSTALL_RPATH_USE_LINK_PATH"); + this->Target->Target->GetPropertyAsBool("INSTALL_RPATH_USE_LINK_PATH"); // Construct the RPATH. std::set<std::string> emitted; if(use_install_rpath) { - const char* install_rpath = this->Target->GetProperty("INSTALL_RPATH"); + const char* install_rpath = + this->Target->Target->GetProperty("INSTALL_RPATH"); cmCLI_ExpandListUnique(install_rpath, runtimeDirs, emitted); } if(use_build_rpath || use_link_rpath) @@ -1999,7 +2011,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, // Add runtime paths required by the languages to always be // present. This is done even when skipping rpath support. { - cmTarget::LinkClosure const* lc = + cmGeneratorTarget::LinkClosure const* lc = this->Target->GetLinkClosure(this->Config); for(std::vector<std::string>::const_iterator li = lc->Languages.begin(); li != lc->Languages.end(); ++li) diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 3afbb92..8b83574 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -20,6 +20,7 @@ class cmake; class cmGlobalGenerator; class cmMakefile; class cmTarget; +class cmGeneratorTarget; class cmOrderDirectories; /** \class cmComputeLinkInformation @@ -28,7 +29,8 @@ class cmOrderDirectories; class cmComputeLinkInformation { public: - cmComputeLinkInformation(cmTarget const* target, const std::string& config); + cmComputeLinkInformation(cmGeneratorTarget const* target, + const std::string& config); ~cmComputeLinkInformation(); bool Compute(); @@ -72,7 +74,7 @@ private: std::set<cmTarget const*> SharedLibrariesLinked; // Context information. - cmTarget const* Target; + cmGeneratorTarget const* Target; cmMakefile* Makefile; cmGlobalGenerator* GlobalGenerator; cmake* CMakeInstance; diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 355fc00..fed0dbc 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -27,6 +27,7 @@ cmExportBuildFileGenerator::cmExportBuildFileGenerator() //---------------------------------------------------------------------------- bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) { + std::vector<cmGeneratorTarget*> allTargets; { std::string expectedTargets; std::string sep; @@ -68,7 +69,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) tei = this->Exports.begin(); tei != this->Exports.end(); ++tei) { - cmTarget* te = (*tei)->Target; + cmGeneratorTarget* gte = *tei; + cmTarget* te = gte->Target; this->GenerateImportTargetCode(os, te); te->AppendBuildInterfaceIncludes(); @@ -104,7 +106,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) cmGeneratorExpression::BuildInterface, properties, missingTargets); } - this->PopulateCompatibleInterfaceProperties(te, properties); + this->PopulateCompatibleInterfaceProperties(gte, properties); this->GenerateInterfaceProperties(te, os, properties); } @@ -331,12 +333,12 @@ cmExportBuildFileGenerator } std::string -cmExportBuildFileGenerator::InstallNameDir(cmTarget* target, +cmExportBuildFileGenerator::InstallNameDir(cmGeneratorTarget* target, const std::string& config) { std::string install_name_dir; - cmMakefile* mf = target->GetMakefile(); + cmMakefile* mf = target->Target->GetMakefile(); if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { install_name_dir = diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 4d8e062..ff3d2e1 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -71,7 +71,8 @@ protected: cmGeneratorTarget* target, ImportPropertyMap& properties); - std::string InstallNameDir(cmTarget* target, const std::string& config); + std::string InstallNameDir(cmGeneratorTarget* target, + const std::string& config); std::vector<std::string> FindNamespaces(cmMakefile* mf, const std::string& name); diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index a33cd59..cae60b7 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -525,7 +525,7 @@ void getPropertyContents(cmTarget const* tgt, const std::string& prop, } //---------------------------------------------------------------------------- -void getCompatibleInterfaceProperties(cmTarget *target, +void getCompatibleInterfaceProperties(cmGeneratorTarget *target, std::set<std::string> &ifaceProperties, const std::string& config) { @@ -533,7 +533,7 @@ void getCompatibleInterfaceProperties(cmTarget *target, if (!info) { - cmMakefile* mf = target->GetMakefile(); + cmMakefile* mf = target->Target->GetMakefile(); std::ostringstream e; e << "Exporting the target \"" << target->GetName() << "\" is not " "allowed since its linker language cannot be determined"; @@ -568,9 +568,10 @@ void getCompatibleInterfaceProperties(cmTarget *target, //---------------------------------------------------------------------------- void cmExportFileGenerator::PopulateCompatibleInterfaceProperties( - cmTarget *target, + cmGeneratorTarget *gtarget, ImportPropertyMap &properties) { + cmTarget *target = gtarget->Target; this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_BOOL", target, properties); this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_STRING", @@ -591,7 +592,7 @@ void cmExportFileGenerator::PopulateCompatibleInterfaceProperties( if (target->GetType() != cmTarget::INTERFACE_LIBRARY) { - getCompatibleInterfaceProperties(target, ifaceProperties, ""); + getCompatibleInterfaceProperties(gtarget, ifaceProperties, ""); std::vector<std::string> configNames; target->GetMakefile()->GetConfigurations(configNames); @@ -599,7 +600,7 @@ void cmExportFileGenerator::PopulateCompatibleInterfaceProperties( for (std::vector<std::string>::const_iterator ci = configNames.begin(); ci != configNames.end(); ++ci) { - getCompatibleInterfaceProperties(target, ifaceProperties, *ci); + getCompatibleInterfaceProperties(gtarget, ifaceProperties, *ci); } } @@ -888,14 +889,14 @@ cmExportFileGenerator { std::string prop; std::string value; - if(target->Target->HasSOName(config)) + if(target->HasSOName(config)) { if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { - value = this->InstallNameDir(target->Target, config); + value = this->InstallNameDir(target, config); } prop = "IMPORTED_SONAME"; - value += target->Target->GetSOName(config); + value += target->GetSOName(config); } else { diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index 2f33200..44f779b 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -132,7 +132,7 @@ protected: std::vector<std::string> &missingTargets); void PopulateInterfaceProperty(const std::string& propName, cmTarget *target, ImportPropertyMap &properties); - void PopulateCompatibleInterfaceProperties(cmTarget *target, + void PopulateCompatibleInterfaceProperties(cmGeneratorTarget *target, ImportPropertyMap &properties); void GenerateInterfaceProperties(cmTarget const* target, std::ostream& os, const ImportPropertyMap &properties); @@ -200,7 +200,7 @@ private: virtual void ReplaceInstallPrefix(std::string &input); - virtual std::string InstallNameDir(cmTarget* target, + virtual std::string InstallNameDir(cmGeneratorTarget* target, const std::string& config) = 0; }; diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 1d75f43..d55be11 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -193,7 +193,11 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", te, properties); - this->PopulateCompatibleInterfaceProperties(te, properties); + cmGeneratorTarget *gtgt = te->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(te); + + this->PopulateCompatibleInterfaceProperties(gtgt, properties); this->GenerateInterfaceProperties(te, os, properties); } @@ -358,7 +362,7 @@ cmExportInstallFileGenerator if(!properties.empty()) { // Get the rest of the target details. - cmGeneratorTarget *gtgt = te->Target->GetMakefile()->GetLocalGenerator() + cmGeneratorTarget *gtgt = te->Target->GetMakefile() ->GetGlobalGenerator()->GetGeneratorTarget(te->Target); this->SetImportDetailProperties(config, suffix, gtgt, properties, missingTargets); @@ -542,12 +546,12 @@ cmExportInstallFileGenerator } std::string -cmExportInstallFileGenerator::InstallNameDir(cmTarget* target, +cmExportInstallFileGenerator::InstallNameDir(cmGeneratorTarget* target, const std::string&) { std::string install_name_dir; - cmMakefile* mf = target->GetMakefile(); + cmMakefile* mf = target->Target->GetMakefile(); if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { install_name_dir = diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index 6f86ac9..b06fee5 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -83,7 +83,8 @@ protected: std::set<std::string>& importedLocations ); - std::string InstallNameDir(cmTarget* target, const std::string& config); + std::string InstallNameDir(cmGeneratorTarget* target, + const std::string& config); cmInstallExportGenerator* IEGen; diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index 94831f8..ba66531 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -125,12 +125,12 @@ cmExportTryCompileFileGenerator::PopulateProperties(cmTarget const* target, } std::string -cmExportTryCompileFileGenerator::InstallNameDir(cmTarget* target, +cmExportTryCompileFileGenerator::InstallNameDir(cmGeneratorTarget* target, const std::string& config) { std::string install_name_dir; - cmMakefile* mf = target->GetMakefile(); + cmMakefile* mf = target->Target->GetMakefile(); if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { install_name_dir = diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h index 749f3ef..8838eca 100644 --- a/Source/cmExportTryCompileFileGenerator.h +++ b/Source/cmExportTryCompileFileGenerator.h @@ -45,7 +45,7 @@ protected: ImportPropertyMap& properties, std::set<cmTarget const*> &emitted); - std::string InstallNameDir(cmTarget* target, + std::string InstallNameDir(cmGeneratorTarget* target, const std::string& config); private: std::string FindTargets(const std::string& prop, cmTarget const* tgt, diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index f3527ff..a86c2bc 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -990,6 +990,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode assert(target); + cmGeneratorTarget* gtgt = + context->Makefile->GetGlobalGenerator()->GetGeneratorTarget(target); + if (propertyName == "LINKER_LANGUAGE") { if (target->LinkLanguagePropagatesToDependents() && @@ -1001,7 +1004,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode "link libraries for a static library"); return std::string(); } - return target->GetLinkerLanguage(context->Config); + return gtgt->GetLinkerLanguage(context->Config); } cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, @@ -1135,40 +1138,40 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode { return linkedTargetsContent; } - if (target->IsLinkInterfaceDependentBoolProperty(propertyName, - context->Config)) + if (gtgt->IsLinkInterfaceDependentBoolProperty(propertyName, + context->Config)) { context->HadContextSensitiveCondition = true; - return target->GetLinkInterfaceDependentBoolProperty( + return gtgt->GetLinkInterfaceDependentBoolProperty( propertyName, context->Config) ? "1" : "0"; } - if (target->IsLinkInterfaceDependentStringProperty(propertyName, - context->Config)) + if (gtgt->IsLinkInterfaceDependentStringProperty(propertyName, + context->Config)) { context->HadContextSensitiveCondition = true; const char *propContent = - target->GetLinkInterfaceDependentStringProperty( + gtgt->GetLinkInterfaceDependentStringProperty( propertyName, context->Config); return propContent ? propContent : ""; } - if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName, - context->Config)) + if (gtgt->IsLinkInterfaceDependentNumberMinProperty(propertyName, + context->Config)) { context->HadContextSensitiveCondition = true; const char *propContent = - target->GetLinkInterfaceDependentNumberMinProperty( + gtgt->GetLinkInterfaceDependentNumberMinProperty( propertyName, context->Config); return propContent ? propContent : ""; } - if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName, - context->Config)) + if (gtgt->IsLinkInterfaceDependentNumberMaxProperty(propertyName, + context->Config)) { context->HadContextSensitiveCondition = true; const char *propContent = - target->GetLinkInterfaceDependentNumberMaxProperty( + gtgt->GetLinkInterfaceDependentNumberMaxProperty( propertyName, context->Config); return propContent ? propContent : ""; @@ -1180,22 +1183,22 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode if (!target->IsImported() && dagCheckerParent && !dagCheckerParent->EvaluatingLinkLibraries()) { - if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName, - context->Config)) + if (gtgt->IsLinkInterfaceDependentNumberMinProperty(propertyName, + context->Config)) { context->HadContextSensitiveCondition = true; const char *propContent = - target->GetLinkInterfaceDependentNumberMinProperty( + gtgt->GetLinkInterfaceDependentNumberMinProperty( propertyName, context->Config); return propContent ? propContent : ""; } - if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName, - context->Config)) + if (gtgt->IsLinkInterfaceDependentNumberMaxProperty(propertyName, + context->Config)) { context->HadContextSensitiveCondition = true; const char *propContent = - target->GetLinkInterfaceDependentNumberMaxProperty( + gtgt->GetLinkInterfaceDependentNumberMaxProperty( propertyName, context->Config); return propContent ? propContent : ""; @@ -1584,7 +1587,7 @@ struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag> } std::string result = target->Target->GetDirectory(context->Config); result += "/"; - result += target->Target->GetSOName(context->Config); + result += target->GetSOName(context->Config); return result; } }; @@ -1597,7 +1600,7 @@ struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag> cmGeneratorExpressionContext *context, const GeneratorExpressionContent *content) { - std::string language = target->Target->GetLinkerLanguage(context->Config); + std::string language = target->GetLinkerLanguage(context->Config); std::string pdbSupportVar = "CMAKE_" + language + "_LINKER_SUPPORTS_PDB"; @@ -1622,7 +1625,7 @@ struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag> std::string result = target->Target->GetPDBDirectory(context->Config); result += "/"; - result += target->Target->GetPDBName(context->Config); + result += target->GetPDBName(context->Config); return result; } }; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index bd57b3d..c831704 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -24,8 +24,16 @@ #include <queue> +#include <errno.h> #include "assert.h" +#if defined(CMAKE_BUILD_WITH_CMAKE) +#include <cmsys/hash_set.hxx> +#define UNORDERED_SET cmsys::hash_set +#else +#define UNORDERED_SET std::set +#endif + //---------------------------------------------------------------------------- void reportBadObjLib(std::vector<cmSourceFile*> const& badObjLib, cmTarget *target, cmake *cm) @@ -229,6 +237,12 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) this->GlobalGenerator = this->Makefile->GetGlobalGenerator(); } +cmGeneratorTarget::~cmGeneratorTarget() +{ + cmDeleteAll(this->LinkInformation); + this->LinkInformation.clear(); +} + cmLocalGenerator* cmGeneratorTarget::GetLocalGenerator() const { return this->LocalGenerator; @@ -253,6 +267,54 @@ const char *cmGeneratorTarget::GetProperty(const std::string& prop) const } //---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetOutputName(const std::string& config, + bool implib) const +{ + std::vector<std::string> props; + std::string type = this->Target->GetOutputTargetType(implib); + std::string configUpper = cmSystemTools::UpperCase(config); + if(!type.empty() && !configUpper.empty()) + { + // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME_<CONFIG> + props.push_back(type + "_OUTPUT_NAME_" + configUpper); + } + if(!type.empty()) + { + // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME + props.push_back(type + "_OUTPUT_NAME"); + } + if(!configUpper.empty()) + { + // OUTPUT_NAME_<CONFIG> + props.push_back("OUTPUT_NAME_" + configUpper); + // <CONFIG>_OUTPUT_NAME + props.push_back(configUpper + "_OUTPUT_NAME"); + } + // OUTPUT_NAME + props.push_back("OUTPUT_NAME"); + + std::string outName; + for(std::vector<std::string>::const_iterator i = props.begin(); + i != props.end(); ++i) + { + if (const char* outNameProp = this->Target->GetProperty(*i)) + { + outName = outNameProp; + break; + } + } + + if (outName.empty()) + { + outName = this->GetName(); + } + + cmGeneratorExpression ge; + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(outName); + return cge->Evaluate(this->Makefile, config); +} + +//---------------------------------------------------------------------------- std::vector<cmSourceFile*> const* cmGeneratorTarget::GetSourceDepends(cmSourceFile const* sf) const { @@ -560,7 +622,7 @@ const char* cmGeneratorTarget::GetLocationForBuild() const if(this->Target->IsAppBundleOnApple()) { - std::string macdir = this->Target->BuildMacContentDirectory("", "", + std::string macdir = this->BuildMacContentDirectory("", "", false); if(!macdir.empty()) { @@ -569,7 +631,7 @@ const char* cmGeneratorTarget::GetLocationForBuild() const } } location += "/"; - location += this->Target->GetFullName("", false); + location += this->GetFullName("", false); return location.c_str(); } @@ -611,7 +673,7 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(const std::string& dir, } std::vector<cmTarget const*> const& deps = - this->Target->GetLinkImplementationClosure(config); + this->GetLinkImplementationClosure(config); for(std::vector<cmTarget const*>::const_iterator li = deps.begin(), le = deps.end(); li != le; ++li) { @@ -651,6 +713,691 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*> &files, //---------------------------------------------------------------------------- std::string +cmGeneratorTarget::GetCompilePDBName(const std::string& 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); + std::string configProp = "COMPILE_PDB_NAME_"; + configProp += configUpper; + const char* config_name = this->Target->GetProperty(configProp); + if(config_name && *config_name) + { + return prefix + config_name + ".pdb"; + } + + const char* name = this->Target->GetProperty("COMPILE_PDB_NAME"); + if(name && *name) + { + return prefix + name + ".pdb"; + } + + return ""; +} + +//---------------------------------------------------------------------------- +std::string +cmGeneratorTarget::GetCompilePDBPath(const std::string& config) const +{ + std::string dir = this->GetCompilePDBDirectory(config); + std::string name = this->GetCompilePDBName(config); + if(dir.empty() && !name.empty()) + { + dir = this->Target->GetPDBDirectory(config); + } + if(!dir.empty()) + { + dir += "/"; + } + return dir + name; +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::HasSOName(const std::string& config) const +{ + // soname is supported only for shared libraries and modules, + // and then only when the platform supports an soname flag. + return ((this->GetType() == cmTarget::SHARED_LIBRARY || + this->GetType() == cmTarget::MODULE_LIBRARY) && + !this->GetPropertyAsBool("NO_SONAME") && + this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config))); +} + +//---------------------------------------------------------------------------- +bool +cmGeneratorTarget::NeedRelinkBeforeInstall(const std::string& config) const +{ + // Only executables and shared libraries can have an rpath and may + // need relinking. + if(this->GetType() != cmTarget::EXECUTABLE && + this->GetType() != cmTarget::SHARED_LIBRARY && + this->GetType() != cmTarget::MODULE_LIBRARY) + { + return false; + } + + // If there is no install location this target will not be installed + // and therefore does not need relinking. + if(!this->Target->GetHaveInstallRule()) + { + return false; + } + + // If skipping all rpaths completely then no relinking is needed. + if(this->Makefile->IsOn("CMAKE_SKIP_RPATH")) + { + return false; + } + + // If building with the install-tree rpath no relinking is needed. + if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) + { + return false; + } + + // If chrpath is going to be used no relinking is needed. + if(this->IsChrpathUsed(config)) + { + return false; + } + + // Check for rpath support on this platform. + std::string ll = this->GetLinkerLanguage(config); + if(!ll.empty()) + { + std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; + flagVar += ll; + flagVar += "_FLAG"; + if(!this->Makefile->IsSet(flagVar)) + { + // There is no rpath support on this platform so nothing needs + // relinking. + return false; + } + } + else + { + // No linker language is known. This error will be reported by + // other code. + return false; + } + + // If either a build or install tree rpath is set then the rpath + // will likely change between the build tree and install tree and + // this target must be relinked. + return this->Target->HaveBuildTreeRPATH(config) + || this->Target->HaveInstallTreeRPATH(); +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const +{ + // Only certain target types have an rpath. + if(!(this->GetType() == cmTarget::SHARED_LIBRARY || + this->GetType() == cmTarget::MODULE_LIBRARY || + this->GetType() == cmTarget::EXECUTABLE)) + { + return false; + } + + // If the target will not be installed we do not need to change its + // rpath. + if(!this->Target->GetHaveInstallRule()) + { + return false; + } + + // Skip chrpath if skipping rpath altogether. + if(this->Makefile->IsOn("CMAKE_SKIP_RPATH")) + { + return false; + } + + // Skip chrpath if it does not need to be changed at install time. + if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) + { + return false; + } + + // Allow the user to disable builtin chrpath explicitly. + if(this->Makefile->IsOn("CMAKE_NO_BUILTIN_CHRPATH")) + { + return false; + } + + if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + return true; + } + +#if defined(CMAKE_USE_ELF_PARSER) + // Enable if the rpath flag uses a separator and the target uses ELF + // binaries. + std::string ll = this->GetLinkerLanguage(config); + if(!ll.empty()) + { + std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; + sepVar += ll; + sepVar += "_FLAG_SEP"; + const char* sep = this->Makefile->GetDefinition(sepVar); + if(sep && *sep) + { + // TODO: Add ELF check to ABI detection and get rid of + // CMAKE_EXECUTABLE_FORMAT. + if(const char* fmt = + this->Makefile->GetDefinition("CMAKE_EXECUTABLE_FORMAT")) + { + return strcmp(fmt, "ELF") == 0; + } + } + } +#endif + static_cast<void>(config); + return false; +} + + +//---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetSOName(const std::string& config) const +{ + if(this->Target->IsImported()) + { + // Lookup the imported soname. + if(cmTarget::ImportInfo const* info = this->Target->GetImportInfo(config)) + { + if(info->NoSOName) + { + // The imported library has no builtin soname so the name + // searched at runtime will be just the filename. + return cmSystemTools::GetFilenameName(info->Location); + } + else + { + // Use the soname given if any. + if(info->SOName.find("@rpath/") == 0) + { + return info->SOName.substr(6); + } + return info->SOName; + } + } + else + { + return ""; + } + } + else + { + // Compute the soname that will be built. + std::string name; + std::string soName; + std::string realName; + std::string impName; + std::string pdbName; + this->GetLibraryNames(name, soName, realName, + impName, pdbName, config); + return soName; + } +} + + +//---------------------------------------------------------------------------- +std::string +cmGeneratorTarget::GetAppBundleDirectory(const std::string& config, + bool contentOnly) const +{ + std::string fpath = this->GetFullName(config, false); + fpath += ".app/Contents"; + if(!contentOnly) + fpath += "/MacOS"; + return fpath; +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::IsBundleOnApple() const +{ + return this->Target->IsFrameworkOnApple() + || this->Target->IsAppBundleOnApple() + || this->Target->IsCFBundleOnApple(); +} + +//---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetCFBundleDirectory(const std::string& config, + bool contentOnly) const +{ + std::string fpath; + fpath += this->GetOutputName(config, false); + fpath += "."; + const char *ext = this->Target->GetProperty("BUNDLE_EXTENSION"); + if (!ext) + { + if (this->Target->IsXCTestOnApple()) + { + ext = "xctest"; + } + else + { + ext = "bundle"; + } + } + fpath += ext; + fpath += "/Contents"; + if(!contentOnly) + fpath += "/MacOS"; + return fpath; +} + +//---------------------------------------------------------------------------- +std::string +cmGeneratorTarget::GetFrameworkDirectory(const std::string& config, + bool rootDir) const +{ + std::string fpath; + fpath += this->GetOutputName(config, false); + fpath += ".framework"; + if(!rootDir) + { + fpath += "/Versions/"; + fpath += this->Target->GetFrameworkVersion(); + } + return fpath; +} + +//---------------------------------------------------------------------------- +std::string +cmGeneratorTarget::GetFullName(const std::string& config, bool implib) const +{ + if(this->Target->IsImported()) + { + return this->Target->GetFullNameImported(config, implib); + } + else + { + return this->GetFullNameInternal(config, implib); + } +} + +//---------------------------------------------------------------------------- +std::string +cmGeneratorTarget::GetInstallNameDirForBuildTree( + const std::string& config) const +{ + // If building directly for installation then the build tree install_name + // is the same as the install tree. + if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) + { + return this->GetInstallNameDirForInstallTree(); + } + + // Use the build tree directory for the target. + if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME") && + !this->Makefile->IsOn("CMAKE_SKIP_RPATH") && + !this->GetPropertyAsBool("SKIP_BUILD_RPATH")) + { + std::string dir; + if(this->Target->MacOSXRpathInstallNameDirDefault()) + { + dir = "@rpath"; + } + else + { + dir = this->Target->GetDirectory(config); + } + dir += "/"; + return dir; + } + else + { + return ""; + } +} + +//---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const +{ + if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) + { + std::string dir; + const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR"); + + if(!this->Makefile->IsOn("CMAKE_SKIP_RPATH") && + !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH")) + { + if(install_name_dir && *install_name_dir) + { + dir = install_name_dir; + dir += "/"; + } + } + if(!install_name_dir) + { + if(this->Target->MacOSXRpathInstallNameDirDefault()) + { + dir = "@rpath/"; + } + } + return dir; + } + else + { + return ""; + } +} + +//---------------------------------------------------------------------------- +class cmTargetCollectLinkLanguages +{ +public: + cmTargetCollectLinkLanguages(cmGeneratorTarget const* target, + const std::string& config, + UNORDERED_SET<std::string>& languages, + cmTarget const* head): + Config(config), Languages(languages), HeadTarget(head), + Makefile(target->Target->GetMakefile()), Target(target) + { this->Visited.insert(target->Target); } + + void Visit(cmLinkItem const& item) + { + if(!item.Target) + { + if(item.find("::") != std::string::npos) + { + bool noMessage = false; + cmake::MessageType messageType = cmake::FATAL_ERROR; + std::stringstream e; + switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0028)) + { + case cmPolicies::WARN: + { + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0028) << "\n"; + messageType = cmake::AUTHOR_WARNING; + } + break; + case cmPolicies::OLD: + noMessage = true; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + // Issue the fatal message. + break; + } + + if(!noMessage) + { + e << "Target \"" << this->Target->GetName() + << "\" links to target \"" << item + << "\" but the target was not found. Perhaps a find_package() " + "call is missing for an IMPORTED target, or an ALIAS target is " + "missing?"; + this->Makefile->GetCMakeInstance()->IssueMessage( + messageType, e.str(), this->Target->Target->GetBacktrace()); + } + } + return; + } + if(!this->Visited.insert(item.Target).second) + { + return; + } + + cmTarget::LinkInterface const* iface = + item.Target->GetLinkInterface(this->Config, this->HeadTarget); + if(!iface) { return; } + + for(std::vector<std::string>::const_iterator + li = iface->Languages.begin(); li != iface->Languages.end(); ++li) + { + this->Languages.insert(*li); + } + + for(std::vector<cmLinkItem>::const_iterator + li = iface->Libraries.begin(); li != iface->Libraries.end(); ++li) + { + this->Visit(*li); + } + } +private: + std::string Config; + UNORDERED_SET<std::string>& Languages; + cmTarget const* HeadTarget; + cmMakefile* Makefile; + const cmGeneratorTarget* Target; + std::set<cmTarget const*> Visited; +}; + +//---------------------------------------------------------------------------- +cmGeneratorTarget::LinkClosure const* +cmGeneratorTarget::GetLinkClosure(const std::string& config) const +{ + std::string key(cmSystemTools::UpperCase(config)); + LinkClosureMapType::iterator + i = this->LinkClosureMap.find(key); + if(i == this->LinkClosureMap.end()) + { + LinkClosure lc; + this->ComputeLinkClosure(config, lc); + LinkClosureMapType::value_type entry(key, lc); + i = this->LinkClosureMap.insert(entry).first; + } + return &i->second; +} + +//---------------------------------------------------------------------------- +class cmTargetSelectLinker +{ + int Preference; + cmGeneratorTarget const* Target; + cmMakefile* Makefile; + cmGlobalGenerator* GG; + std::set<std::string> Preferred; +public: + cmTargetSelectLinker(cmGeneratorTarget const* target) + : Preference(0), Target(target) + { + this->Makefile = this->Target->Makefile; + this->GG = this->Makefile->GetGlobalGenerator(); + } + void Consider(const char* lang) + { + int preference = this->GG->GetLinkerPreference(lang); + if(preference > this->Preference) + { + this->Preference = preference; + this->Preferred.clear(); + } + if(preference == this->Preference) + { + this->Preferred.insert(lang); + } + } + std::string Choose() + { + if(this->Preferred.empty()) + { + return ""; + } + else if(this->Preferred.size() > 1) + { + std::stringstream e; + e << "Target " << this->Target->GetName() + << " contains multiple languages with the highest linker preference" + << " (" << this->Preference << "):\n"; + for(std::set<std::string>::const_iterator + li = this->Preferred.begin(); li != this->Preferred.end(); ++li) + { + e << " " << *li << "\n"; + } + e << "Set the LINKER_LANGUAGE property for this target."; + cmake* cm = this->Makefile->GetCMakeInstance(); + cm->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->Target->Target->GetBacktrace()); + } + return *this->Preferred.begin(); + } +}; + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::ComputeLinkClosure(const std::string& config, + LinkClosure& lc) const +{ + // Get languages built in this target. + UNORDERED_SET<std::string> languages; + cmTarget::LinkImplementation const* impl = + this->Target->GetLinkImplementation(config); + for(std::vector<std::string>::const_iterator li = impl->Languages.begin(); + li != impl->Languages.end(); ++li) + { + languages.insert(*li); + } + + // Add interface languages from linked targets. + cmTargetCollectLinkLanguages cll(this, config, languages, this->Target); + for(std::vector<cmLinkImplItem>::const_iterator li = impl->Libraries.begin(); + li != impl->Libraries.end(); ++li) + { + cll.Visit(*li); + } + + // Store the transitive closure of languages. + for(UNORDERED_SET<std::string>::const_iterator li = languages.begin(); + li != languages.end(); ++li) + { + lc.Languages.push_back(*li); + } + + // Choose the language whose linker should be used. + if(this->GetProperty("HAS_CXX")) + { + lc.LinkerLanguage = "CXX"; + } + else if(const char* linkerLang = this->GetProperty("LINKER_LANGUAGE")) + { + lc.LinkerLanguage = linkerLang; + } + else + { + // Find the language with the highest preference value. + cmTargetSelectLinker tsl(this); + + // First select from the languages compiled directly in this target. + for(std::vector<std::string>::const_iterator li = impl->Languages.begin(); + li != impl->Languages.end(); ++li) + { + tsl.Consider(li->c_str()); + } + + // Now consider languages that propagate from linked targets. + for(UNORDERED_SET<std::string>::const_iterator sit = languages.begin(); + sit != languages.end(); ++sit) + { + std::string propagates = "CMAKE_"+*sit+"_LINKER_PREFERENCE_PROPAGATES"; + if(this->Makefile->IsOn(propagates)) + { + tsl.Consider(sit->c_str()); + } + } + + lc.LinkerLanguage = tsl.Choose(); + } +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::GetFullNameComponents(std::string& prefix, + std::string& base, + std::string& suffix, + const std::string& config, + bool implib) const +{ + this->GetFullNameInternal(config, implib, prefix, base, suffix); +} + +//---------------------------------------------------------------------------- +std::string +cmGeneratorTarget::BuildMacContentDirectory(const std::string& base, + const std::string& config, + bool contentOnly) const +{ + std::string fpath = base; + if(this->Target->IsAppBundleOnApple()) + { + fpath += this->GetAppBundleDirectory(config, contentOnly); + } + if(this->Target->IsFrameworkOnApple()) + { + fpath += this->GetFrameworkDirectory(config, contentOnly); + } + if(this->Target->IsCFBundleOnApple()) + { + fpath += this->GetCFBundleDirectory(config, contentOnly); + } + return fpath; +} + +//---------------------------------------------------------------------------- +std::string +cmGeneratorTarget::GetMacContentDirectory(const std::string& config, + bool implib) const +{ + // Start with the output directory for the target. + std::string fpath = this->Target->GetDirectory(config, implib); + fpath += "/"; + bool contentOnly = true; + if(this->Target->IsFrameworkOnApple()) + { + // additional files with a framework go into the version specific + // directory + contentOnly = false; + } + fpath = this->BuildMacContentDirectory(fpath, config, contentOnly); + return fpath; +} + + +//---------------------------------------------------------------------------- +cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo( + const std::string& 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->Target->GetType()); + this->Makefile->IssueMessage(cmake::INTERNAL_ERROR, msg); + return 0; + } + + // Lookup/compute/cache the compile information for this configuration. + std::string config_upper; + if(!config.empty()) + { + config_upper = cmSystemTools::UpperCase(config); + } + CompileInfoMapType::const_iterator i = + this->CompileInfoMap.find(config_upper); + if(i == this->CompileInfoMap.end()) + { + CompileInfo info; + this->Target + ->ComputePDBOutputDir("COMPILE_PDB", config, info.CompilePdbDir); + CompileInfoMapType::value_type entry(config_upper, info); + i = this->CompileInfoMap.insert(entry).first; + } + return &i->second; +} + +//---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetModuleDefinitionFile(const std::string& config) const { std::string data; @@ -700,6 +1447,79 @@ cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs, } //---------------------------------------------------------------------------- +void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string> &result, + const std::string& config) const +{ + const char *prop + = this->GetLinkInterfaceDependentStringProperty("AUTOUIC_OPTIONS", + config); + if (!prop) + { + return; + } + cmGeneratorExpression ge; + + cmGeneratorExpressionDAGChecker dagChecker( + this->GetName(), + "AUTOUIC_OPTIONS", 0, 0); + cmSystemTools::ExpandListArgument(ge.Parse(prop) + ->Evaluate(this->Makefile, + config, + false, + this->Target, + &dagChecker), + result); +} + +//---------------------------------------------------------------------------- +void processILibs(const std::string& config, + cmTarget const* headTarget, + cmLinkItem const& item, + std::vector<cmTarget const*>& tgts, + std::set<cmTarget const*>& emitted) +{ + if (item.Target && emitted.insert(item.Target).second) + { + tgts.push_back(item.Target); + if(cmTarget::LinkInterfaceLibraries const* iface = + item.Target->GetLinkInterfaceLibraries(config, headTarget, true)) + { + for(std::vector<cmLinkItem>::const_iterator + it = iface->Libraries.begin(); + it != iface->Libraries.end(); ++it) + { + processILibs(config, headTarget, *it, tgts, emitted); + } + } + } +} + +//---------------------------------------------------------------------------- +const std::vector<const cmTarget*>& +cmGeneratorTarget::GetLinkImplementationClosure( + const std::string& config) const +{ + LinkImplClosure& tgts = + this->LinkImplClosureMap[config]; + if(!tgts.Done) + { + tgts.Done = true; + std::set<cmTarget const*> emitted; + + cmTarget::LinkImplementationLibraries const* impl + = this->Target->GetLinkImplementationLibraries(config); + + for(std::vector<cmLinkImplItem>::const_iterator + it = impl->Libraries.begin(); + it != impl->Libraries.end(); ++it) + { + processILibs(config, this->Target, *it, tgts , emitted); + } + } + return tgts; +} + +//---------------------------------------------------------------------------- class cmTargetTraceDependencies { public: @@ -1044,6 +1864,16 @@ void cmGeneratorTarget::TraceDependencies() tracer.Trace(); } +std::string +cmGeneratorTarget::GetCompilePDBDirectory(const std::string& config) const +{ + if(CompileInfo const* info = this->GetCompileInfo(config)) + { + return info->CompilePdbDir; + } + return ""; +} + //---------------------------------------------------------------------------- void cmGeneratorTarget::GetAppleArchs(const std::string& config, std::vector<std::string>& archVec) const @@ -1125,14 +1955,13 @@ void cmGeneratorTarget::GenerateTargetManifest( std::string pdbName; if(this->GetType() == cmTarget::EXECUTABLE) { - this->Target->GetExecutableNames(name, realName, impName, pdbName, - config); + this->GetExecutableNames(name, realName, impName, pdbName, config); } else if(this->GetType() == cmTarget::STATIC_LIBRARY || this->GetType() == cmTarget::SHARED_LIBRARY || this->GetType() == cmTarget::MODULE_LIBRARY) { - this->Target->GetLibraryNames(name, soName, realName, impName, pdbName, + this->GetLibraryNames(name, soName, realName, impName, pdbName, config); } else @@ -1204,14 +2033,14 @@ std::string cmGeneratorTarget::NormalGetFullPath(const std::string& config, fpath += "/"; if(this->Target->IsAppBundleOnApple()) { - fpath = this->Target->BuildMacContentDirectory(fpath, config, false); + fpath = this->BuildMacContentDirectory(fpath, config, false); fpath += "/"; } // Add the full name of the target. if(implib) { - fpath += this->Target->GetFullName(config, true); + fpath += this->GetFullName(config, true); } else if(realname) { @@ -1219,7 +2048,7 @@ std::string cmGeneratorTarget::NormalGetFullPath(const std::string& config, } else { - fpath += this->Target->GetFullName(config, false); + fpath += this->GetFullName(config, false); } return fpath; } @@ -1245,7 +2074,7 @@ cmGeneratorTarget::NormalGetRealName(const std::string& config) const std::string realName; std::string impName; std::string pdbName; - this->Target->GetExecutableNames(name, realName, impName, pdbName, config); + this->GetExecutableNames(name, realName, impName, pdbName, config); return realName; } else @@ -1256,12 +2085,344 @@ cmGeneratorTarget::NormalGetRealName(const std::string& config) const std::string realName; std::string impName; std::string pdbName; - this->Target->GetLibraryNames(name, soName, realName, - impName, pdbName, config); + this->GetLibraryNames(name, soName, realName, + impName, pdbName, config); return realName; } } +//---------------------------------------------------------------------------- +void cmGeneratorTarget::GetLibraryNames(std::string& name, + std::string& soName, + std::string& realName, + std::string& impName, + std::string& pdbName, + const std::string& config) const +{ + // This should not be called for imported targets. + // TODO: Split cmTarget into a class hierarchy to get compile-time + // enforcement of the limited imported target API. + if(this->Target->IsImported()) + { + std::string msg = "GetLibraryNames called on imported target: "; + msg += this->GetName(); + this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, + msg); + return; + } + + // Check for library version properties. + const char* version = this->GetProperty("VERSION"); + const char* soversion = this->GetProperty("SOVERSION"); + if(!this->HasSOName(config) || + this->Target->IsFrameworkOnApple()) + { + // Versioning is supported only for shared libraries and modules, + // and then only when the platform supports an soname flag. + version = 0; + soversion = 0; + } + if(version && !soversion) + { + // The soversion must be set if the library version is set. Use + // the library version as the soversion. + soversion = version; + } + if(!version && soversion) + { + // Use the soversion as the library version. + version = soversion; + } + + // Get the components of the library name. + std::string prefix; + std::string base; + std::string suffix; + this->GetFullNameInternal(config, false, prefix, base, suffix); + + // The library name. + name = prefix+base+suffix; + + if(this->Target->IsFrameworkOnApple()) + { + realName = prefix; + realName += "Versions/"; + realName += this->Target->GetFrameworkVersion(); + realName += "/"; + realName += base; + soName = realName; + } + else + { + // The library's soname. + this->Target->ComputeVersionedName(soName, prefix, base, suffix, + name, soversion); + + // The library's real name on disk. + this->Target->ComputeVersionedName(realName, prefix, base, suffix, + name, version); + } + + // The import library name. + if(this->GetType() == cmTarget::SHARED_LIBRARY || + this->GetType() == cmTarget::MODULE_LIBRARY) + { + impName = this->GetFullNameInternal(config, true); + } + else + { + impName = ""; + } + + // The program database file name. + pdbName = this->GetPDBName(config); +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::GetExecutableNames(std::string& name, + std::string& realName, + std::string& impName, + std::string& pdbName, + const std::string& config) const +{ + // This should not be called for imported targets. + // TODO: Split cmTarget into a class hierarchy to get compile-time + // enforcement of the limited imported target API. + if(this->Target->IsImported()) + { + std::string msg = + "GetExecutableNames called on imported target: "; + msg += this->GetName(); + this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg); + } + + // This versioning is supported only for executables and then only + // when the platform supports symbolic links. +#if defined(_WIN32) && !defined(__CYGWIN__) + const char* version = 0; +#else + // Check for executable version properties. + const char* version = this->GetProperty("VERSION"); + if(this->GetType() != cmTarget::EXECUTABLE || this->Makefile->IsOn("XCODE")) + { + version = 0; + } +#endif + + // Get the components of the executable name. + std::string prefix; + std::string base; + std::string suffix; + this->GetFullNameInternal(config, false, prefix, base, suffix); + + // The executable name. + name = prefix+base+suffix; + + // The executable's real name on disk. +#if defined(__CYGWIN__) + realName = prefix+base; +#else + realName = name; +#endif + if(version) + { + realName += "-"; + realName += version; + } +#if defined(__CYGWIN__) + realName += suffix; +#endif + + // The import library name. + impName = this->GetFullNameInternal(config, true); + + // The program database file name. + pdbName = this->GetPDBName(config); +} + +//---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetFullNameInternal(const std::string& config, + bool implib) const +{ + std::string prefix; + std::string base; + std::string suffix; + this->GetFullNameInternal(config, implib, prefix, base, suffix); + return prefix+base+suffix; +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::GetFullNameInternal(const std::string& config, + bool implib, + std::string& outPrefix, + std::string& outBase, + std::string& outSuffix) const +{ + // Use just the target name for non-main target types. + if(this->GetType() != cmTarget::STATIC_LIBRARY && + this->GetType() != cmTarget::SHARED_LIBRARY && + this->GetType() != cmTarget::MODULE_LIBRARY && + this->GetType() != cmTarget::EXECUTABLE) + { + outPrefix = ""; + outBase = this->GetName(); + outSuffix = ""; + return; + } + + // Return an empty name for the import library if this platform + // does not support import libraries. + if(implib && + !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) + { + outPrefix = ""; + outBase = ""; + outSuffix = ""; + return; + } + + // The implib option is only allowed for shared libraries, module + // libraries, and executables. + if(this->GetType() != cmTarget::SHARED_LIBRARY && + this->GetType() != cmTarget::MODULE_LIBRARY && + this->GetType() != cmTarget::EXECUTABLE) + { + implib = false; + } + + // Compute the full name for main target types. + const char* targetPrefix = (implib + ? this->GetProperty("IMPORT_PREFIX") + : this->GetProperty("PREFIX")); + const char* targetSuffix = (implib + ? this->GetProperty("IMPORT_SUFFIX") + : this->GetProperty("SUFFIX")); + const char* configPostfix = 0; + if(!config.empty()) + { + std::string configProp = cmSystemTools::UpperCase(config); + configProp += "_POSTFIX"; + configPostfix = this->GetProperty(configProp); + // Mac application bundles and frameworks have no postfix. + if(configPostfix && + (this->Target->IsAppBundleOnApple() + || this->Target->IsFrameworkOnApple())) + { + configPostfix = 0; + } + } + const char* prefixVar = this->Target->GetPrefixVariableInternal(implib); + const char* suffixVar = this->Target->GetSuffixVariableInternal(implib); + + // Check for language-specific default prefix and suffix. + std::string ll = this->GetLinkerLanguage(config); + if(!ll.empty()) + { + if(!targetSuffix && suffixVar && *suffixVar) + { + std::string langSuff = suffixVar + std::string("_") + ll; + targetSuffix = this->Makefile->GetDefinition(langSuff); + } + if(!targetPrefix && prefixVar && *prefixVar) + { + std::string langPrefix = prefixVar + std::string("_") + ll; + targetPrefix = this->Makefile->GetDefinition(langPrefix); + } + } + + // if there is no prefix on the target use the cmake definition + if(!targetPrefix && prefixVar) + { + targetPrefix = this->Makefile->GetSafeDefinition(prefixVar); + } + // if there is no suffix on the target use the cmake definition + if(!targetSuffix && suffixVar) + { + targetSuffix = this->Makefile->GetSafeDefinition(suffixVar); + } + + // frameworks have directory prefix but no suffix + std::string fw_prefix; + if(this->Target->IsFrameworkOnApple()) + { + fw_prefix = this->GetOutputName(config, false); + fw_prefix += ".framework/"; + targetPrefix = fw_prefix.c_str(); + targetSuffix = 0; + } + + if(this->Target->IsCFBundleOnApple()) + { + fw_prefix = this->GetCFBundleDirectory(config, false); + fw_prefix += "/"; + targetPrefix = fw_prefix.c_str(); + targetSuffix = 0; + } + + // Begin the final name with the prefix. + outPrefix = targetPrefix?targetPrefix:""; + + // Append the target name or property-specified name. + outBase += this->GetOutputName(config, implib); + + // Append the per-configuration postfix. + outBase += configPostfix?configPostfix:""; + + // Name shared libraries with their version number on some platforms. + if(const char* soversion = this->GetProperty("SOVERSION")) + { + if(this->GetType() == cmTarget::SHARED_LIBRARY && !implib && + this->Makefile->IsOn("CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION")) + { + outBase += "-"; + outBase += soversion; + } + } + + // Append the suffix. + outSuffix = targetSuffix?targetSuffix:""; +} + + +//---------------------------------------------------------------------------- +std::string +cmGeneratorTarget::GetLinkerLanguage(const std::string& config) const +{ + return this->GetLinkClosure(config)->LinkerLanguage; +} + +//---------------------------------------------------------------------------- +std::string cmGeneratorTarget::GetPDBName(const std::string& config) const +{ + std::string prefix; + std::string base; + std::string suffix; + this->GetFullNameInternal(config, false, prefix, base, suffix); + + std::vector<std::string> props; + std::string configUpper = + cmSystemTools::UpperCase(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)) + { + base = outName; + break; + } + } + return prefix+base+".pdb"; +} + bool cmStrictTargetComparison::operator()(cmTarget const* t1, cmTarget const* t2) const { @@ -1367,3 +2528,797 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const } } } + +//---------------------------------------------------------------------------- +const cmGeneratorTarget::CompatibleInterfacesBase& +cmGeneratorTarget::GetCompatibleInterfaces(std::string const& config) const +{ + cmGeneratorTarget::CompatibleInterfaces& compat = + this->CompatibleInterfacesMap[config]; + if(!compat.Done) + { + compat.Done = true; + compat.PropsBool.insert("POSITION_INDEPENDENT_CODE"); + compat.PropsString.insert("AUTOUIC_OPTIONS"); + std::vector<cmTarget const*> const& deps = + this->GetLinkImplementationClosure(config); + for(std::vector<cmTarget const*>::const_iterator li = deps.begin(); + li != deps.end(); ++li) + { +#define CM_READ_COMPATIBLE_INTERFACE(X, x) \ + if(const char* prop = (*li)->GetProperty("COMPATIBLE_INTERFACE_" #X)) \ + { \ + std::vector<std::string> props; \ + cmSystemTools::ExpandListArgument(prop, props); \ + compat.Props##x.insert(props.begin(), props.end()); \ + } + CM_READ_COMPATIBLE_INTERFACE(BOOL, Bool) + CM_READ_COMPATIBLE_INTERFACE(STRING, String) + CM_READ_COMPATIBLE_INTERFACE(NUMBER_MIN, NumberMin) + CM_READ_COMPATIBLE_INTERFACE(NUMBER_MAX, NumberMax) +#undef CM_READ_COMPATIBLE_INTERFACE + } + } + return compat; +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::IsLinkInterfaceDependentBoolProperty( + const std::string &p, const std::string& config) const +{ + if (this->Target->GetType() == cmTarget::OBJECT_LIBRARY + || this->Target->GetType() == cmTarget::INTERFACE_LIBRARY) + { + return false; + } + return this->GetCompatibleInterfaces(config).PropsBool.count(p) > 0; +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::IsLinkInterfaceDependentStringProperty( + const std::string &p, const std::string& config) const +{ + if (this->Target->GetType() == cmTarget::OBJECT_LIBRARY + || this->Target->GetType() == cmTarget::INTERFACE_LIBRARY) + { + return false; + } + return this->GetCompatibleInterfaces(config).PropsString.count(p) > 0; +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::IsLinkInterfaceDependentNumberMinProperty( + const std::string &p, const std::string& config) const +{ + if (this->Target->GetType() == cmTarget::OBJECT_LIBRARY + || this->Target->GetType() == cmTarget::INTERFACE_LIBRARY) + { + return false; + } + return this->GetCompatibleInterfaces(config).PropsNumberMin.count(p) > 0; +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::IsLinkInterfaceDependentNumberMaxProperty( + const std::string &p, const std::string& config) const +{ + if (this->Target->GetType() == cmTarget::OBJECT_LIBRARY + || this->Target->GetType() == cmTarget::INTERFACE_LIBRARY) + { + return false; + } + return this->GetCompatibleInterfaces(config).PropsNumberMax.count(p) > 0; +} + +enum CompatibleType +{ + BoolType, + StringType, + NumberMinType, + NumberMaxType +}; + +template<typename PropertyType> +PropertyType getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt, + const std::string& prop, + const std::string& config, + CompatibleType, + PropertyType *); + +template<> +bool getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt, + const std::string& prop, + const std::string& config, + CompatibleType, bool *) +{ + return tgt->GetLinkInterfaceDependentBoolProperty(prop, config); +} + +template<> +const char * getLinkInterfaceDependentProperty(cmGeneratorTarget const* tgt, + const std::string& prop, + const std::string& config, + CompatibleType t, + const char **) +{ + switch(t) + { + case BoolType: + assert(0 && "String compatibility check function called for boolean"); + return 0; + case StringType: + return tgt->GetLinkInterfaceDependentStringProperty(prop, config); + case NumberMinType: + return tgt->GetLinkInterfaceDependentNumberMinProperty(prop, config); + case NumberMaxType: + return tgt->GetLinkInterfaceDependentNumberMaxProperty(prop, config); + } + assert(0 && "Unreachable!"); + return 0; +} + +//---------------------------------------------------------------------------- +template<typename PropertyType> +void checkPropertyConsistency(cmGeneratorTarget const* depender, + cmTarget const* dependee, + const std::string& propName, + std::set<std::string> &emitted, + const std::string& config, + CompatibleType t, + PropertyType *) +{ + const char *prop = dependee->GetProperty(propName); + if (!prop) + { + return; + } + + std::vector<std::string> props; + cmSystemTools::ExpandListArgument(prop, props); + std::string pdir = + dependee->GetMakefile()->GetRequiredDefinition("CMAKE_ROOT"); + pdir += "/Help/prop_tgt/"; + + for(std::vector<std::string>::iterator pi = props.begin(); + pi != props.end(); ++pi) + { + std::string pname = cmSystemTools::HelpFileName(*pi); + std::string pfile = pdir + pname + ".rst"; + if(cmSystemTools::FileExists(pfile.c_str(), true)) + { + std::ostringstream e; + e << "Target \"" << dependee->GetName() << "\" has property \"" + << *pi << "\" listed in its " << propName << " property. " + "This is not allowed. Only user-defined properties may appear " + "listed in the " << propName << " property."; + depender->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + if(emitted.insert(*pi).second) + { + getLinkInterfaceDependentProperty<PropertyType>(depender, *pi, config, + t, 0); + if (cmSystemTools::GetErrorOccuredFlag()) + { + return; + } + } + } +} + +static std::string intersect(const std::set<std::string> &s1, + const std::set<std::string> &s2) +{ + std::set<std::string> intersect; + std::set_intersection(s1.begin(),s1.end(), + s2.begin(),s2.end(), + std::inserter(intersect,intersect.begin())); + if (!intersect.empty()) + { + return *intersect.begin(); + } + return ""; +} + +static std::string intersect(const std::set<std::string> &s1, + const std::set<std::string> &s2, + const std::set<std::string> &s3) +{ + std::string result; + result = intersect(s1, s2); + if (!result.empty()) + return result; + result = intersect(s1, s3); + if (!result.empty()) + return result; + return intersect(s2, s3); +} + +static std::string intersect(const std::set<std::string> &s1, + const std::set<std::string> &s2, + const std::set<std::string> &s3, + const std::set<std::string> &s4) +{ + std::string result; + result = intersect(s1, s2); + if (!result.empty()) + return result; + result = intersect(s1, s3); + if (!result.empty()) + return result; + result = intersect(s1, s4); + if (!result.empty()) + return result; + return intersect(s2, s3, s4); +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::CheckPropertyCompatibility( + cmComputeLinkInformation *info, const std::string& config) const +{ + const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); + + std::set<std::string> emittedBools; + static std::string strBool = "COMPATIBLE_INTERFACE_BOOL"; + std::set<std::string> emittedStrings; + static std::string strString = "COMPATIBLE_INTERFACE_STRING"; + std::set<std::string> emittedMinNumbers; + static std::string strNumMin = "COMPATIBLE_INTERFACE_NUMBER_MIN"; + std::set<std::string> emittedMaxNumbers; + static std::string strNumMax = "COMPATIBLE_INTERFACE_NUMBER_MAX"; + + for(cmComputeLinkInformation::ItemVector::const_iterator li = + deps.begin(); li != deps.end(); ++li) + { + if (!li->Target) + { + continue; + } + + checkPropertyConsistency<bool>(this, li->Target, + strBool, + emittedBools, config, BoolType, 0); + if (cmSystemTools::GetErrorOccuredFlag()) + { + return; + } + checkPropertyConsistency<const char *>(this, li->Target, + strString, + emittedStrings, config, + StringType, 0); + if (cmSystemTools::GetErrorOccuredFlag()) + { + return; + } + checkPropertyConsistency<const char *>(this, li->Target, + strNumMin, + emittedMinNumbers, config, + NumberMinType, 0); + if (cmSystemTools::GetErrorOccuredFlag()) + { + return; + } + checkPropertyConsistency<const char *>(this, li->Target, + strNumMax, + emittedMaxNumbers, config, + NumberMaxType, 0); + if (cmSystemTools::GetErrorOccuredFlag()) + { + return; + } + } + + std::string prop = intersect(emittedBools, + emittedStrings, + emittedMinNumbers, + emittedMaxNumbers); + + if (!prop.empty()) + { + // Use a sorted std::vector to keep the error message sorted. + std::vector<std::string> props; + std::set<std::string>::const_iterator i = emittedBools.find(prop); + if (i != emittedBools.end()) + { + props.push_back(strBool); + } + i = emittedStrings.find(prop); + if (i != emittedStrings.end()) + { + props.push_back(strString); + } + i = emittedMinNumbers.find(prop); + if (i != emittedMinNumbers.end()) + { + props.push_back(strNumMin); + } + i = emittedMaxNumbers.find(prop); + if (i != emittedMaxNumbers.end()) + { + props.push_back(strNumMax); + } + std::sort(props.begin(), props.end()); + + std::string propsString = cmJoin(cmMakeRange(props).retreat(1), ", "); + propsString += " and the " + props.back(); + + std::ostringstream e; + e << "Property \"" << prop << "\" appears in both the " + << propsString << + " property in the dependencies of target \"" << this->GetName() << + "\". This is not allowed. A property may only require compatibility " + "in a boolean interpretation, a numeric minimum, a numeric maximum or a " + "string interpretation, but not a mixture."; + this->LocalGenerator->IssueMessage(cmake::FATAL_ERROR, e.str()); + } +} + +//---------------------------------------------------------------------------- +std::string compatibilityType(CompatibleType t) +{ + switch(t) + { + case BoolType: + return "Boolean compatibility"; + case StringType: + return "String compatibility"; + case NumberMaxType: + return "Numeric maximum compatibility"; + case NumberMinType: + return "Numeric minimum compatibility"; + } + assert(0 && "Unreachable!"); + return ""; +} + +//---------------------------------------------------------------------------- +std::string compatibilityAgree(CompatibleType t, bool dominant) +{ + switch(t) + { + case BoolType: + case StringType: + return dominant ? "(Disagree)\n" : "(Agree)\n"; + case NumberMaxType: + case NumberMinType: + return dominant ? "(Dominant)\n" : "(Ignored)\n"; + } + assert(0 && "Unreachable!"); + return ""; +} + +//---------------------------------------------------------------------------- +template<typename PropertyType> +PropertyType getTypedProperty(cmTarget const* tgt, const std::string& prop); + +//---------------------------------------------------------------------------- +template<> +bool getTypedProperty<bool>(cmTarget const* tgt, const std::string& prop) +{ + return tgt->GetPropertyAsBool(prop); +} + +//---------------------------------------------------------------------------- +template<> +const char *getTypedProperty<const char *>(cmTarget const* tgt, + const std::string& prop) +{ + return tgt->GetProperty(prop); +} + +template<typename PropertyType> +std::string valueAsString(PropertyType); +template<> +std::string valueAsString<bool>(bool value) +{ + return value ? "TRUE" : "FALSE"; +} +template<> +std::string valueAsString<const char*>(const char* value) +{ + return value ? value : "(unset)"; +} + +template<typename PropertyType> +PropertyType impliedValue(PropertyType); +template<> +bool impliedValue<bool>(bool) +{ + return false; +} +template<> +const char* impliedValue<const char*>(const char*) +{ + return ""; +} + +//---------------------------------------------------------------------------- +template<typename PropertyType> +std::pair<bool, PropertyType> consistentProperty(PropertyType lhs, + PropertyType rhs, + CompatibleType t); + +//---------------------------------------------------------------------------- +template<> +std::pair<bool, bool> consistentProperty(bool lhs, bool rhs, + CompatibleType) +{ + return std::make_pair(lhs == rhs, lhs); +} + +//---------------------------------------------------------------------------- +std::pair<bool, const char*> consistentStringProperty(const char *lhs, + const char *rhs) +{ + const bool b = strcmp(lhs, rhs) == 0; + return std::make_pair(b, b ? lhs : 0); +} + +//---------------------------------------------------------------------------- +std::pair<bool, const char*> consistentNumberProperty(const char *lhs, + const char *rhs, + CompatibleType t) +{ + char *pEnd; + + const char* const null_ptr = 0; + + long lnum = strtol(lhs, &pEnd, 0); + if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE) + { + return std::pair<bool, const char*>(false, null_ptr); + } + + long rnum = strtol(rhs, &pEnd, 0); + if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE) + { + return std::pair<bool, const char*>(false, null_ptr); + } + + if (t == NumberMaxType) + { + return std::make_pair(true, std::max(lnum, rnum) == lnum ? lhs : rhs); + } + else + { + return std::make_pair(true, std::min(lnum, rnum) == lnum ? lhs : rhs); + } +} + +//---------------------------------------------------------------------------- +template<> +std::pair<bool, const char*> consistentProperty(const char *lhs, + const char *rhs, + CompatibleType t) +{ + if (!lhs && !rhs) + { + return std::make_pair(true, lhs); + } + if (!lhs) + { + return std::make_pair(true, rhs); + } + if (!rhs) + { + return std::make_pair(true, lhs); + } + + const char* const null_ptr = 0; + + switch(t) + { + case BoolType: + assert(0 && "consistentProperty for strings called with BoolType"); + return std::pair<bool, const char*>(false, null_ptr); + case StringType: + return consistentStringProperty(lhs, rhs); + case NumberMinType: + case NumberMaxType: + return consistentNumberProperty(lhs, rhs, t); + } + assert(0 && "Unreachable!"); + return std::pair<bool, const char*>(false, null_ptr); +} + +//---------------------------------------------------------------------------- +template<typename PropertyType> +PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, + const std::string &p, + const std::string& config, + const char *defaultValue, + CompatibleType t, + PropertyType *) +{ + PropertyType propContent = getTypedProperty<PropertyType>(tgt->Target, p); + const bool explicitlySet = tgt->Target->GetProperties() + .find(p) + != tgt->Target->GetProperties().end(); + const bool impliedByUse = + tgt->Target->IsNullImpliedByLinkLibraries(p); + assert((impliedByUse ^ explicitlySet) + || (!impliedByUse && !explicitlySet)); + + std::vector<cmTarget const*> const& deps = + tgt->GetLinkImplementationClosure(config); + + if(deps.empty()) + { + return propContent; + } + bool propInitialized = explicitlySet; + + std::string report = " * Target \""; + report += tgt->GetName(); + if (explicitlySet) + { + report += "\" has property content \""; + report += valueAsString<PropertyType>(propContent); + report += "\"\n"; + } + else if (impliedByUse) + { + report += "\" property is implied by use.\n"; + } + else + { + report += "\" property not set.\n"; + } + + std::string interfaceProperty = "INTERFACE_" + p; + for(std::vector<cmTarget const*>::const_iterator li = + deps.begin(); + li != deps.end(); ++li) + { + // An error should be reported if one dependency + // has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other + // has INTERFACE_POSITION_INDEPENDENT_CODE OFF, or if the + // target itself has a POSITION_INDEPENDENT_CODE which disagrees + // with a dependency. + + cmTarget const* theTarget = *li; + + const bool ifaceIsSet = theTarget->GetProperties() + .find(interfaceProperty) + != theTarget->GetProperties().end(); + PropertyType ifacePropContent = + getTypedProperty<PropertyType>(theTarget, + interfaceProperty); + + std::string reportEntry; + if (ifaceIsSet) + { + reportEntry += " * Target \""; + reportEntry += theTarget->GetName(); + reportEntry += "\" property value \""; + reportEntry += valueAsString<PropertyType>(ifacePropContent); + reportEntry += "\" "; + } + + if (explicitlySet) + { + if (ifaceIsSet) + { + std::pair<bool, PropertyType> consistent = + consistentProperty(propContent, + ifacePropContent, t); + report += reportEntry; + report += compatibilityAgree(t, propContent != consistent.second); + if (!consistent.first) + { + std::ostringstream e; + e << "Property " << p << " on target \"" + << tgt->GetName() << "\" does\nnot match the " + "INTERFACE_" << p << " property requirement\nof " + "dependency \"" << theTarget->GetName() << "\".\n"; + cmSystemTools::Error(e.str().c_str()); + break; + } + else + { + propContent = consistent.second; + continue; + } + } + else + { + // Explicitly set on target and not set in iface. Can't disagree. + continue; + } + } + else if (impliedByUse) + { + propContent = impliedValue<PropertyType>(propContent); + + if (ifaceIsSet) + { + std::pair<bool, PropertyType> consistent = + consistentProperty(propContent, + ifacePropContent, t); + report += reportEntry; + report += compatibilityAgree(t, propContent != consistent.second); + if (!consistent.first) + { + std::ostringstream e; + e << "Property " << p << " on target \"" + << tgt->GetName() << "\" is\nimplied to be " << defaultValue + << " because it was used to determine the link libraries\n" + "already. The INTERFACE_" << p << " property on\ndependency \"" + << theTarget->GetName() << "\" is in conflict.\n"; + cmSystemTools::Error(e.str().c_str()); + break; + } + else + { + propContent = consistent.second; + continue; + } + } + else + { + // Implicitly set on target and not set in iface. Can't disagree. + continue; + } + } + else + { + if (ifaceIsSet) + { + if (propInitialized) + { + std::pair<bool, PropertyType> consistent = + consistentProperty(propContent, + ifacePropContent, t); + report += reportEntry; + report += compatibilityAgree(t, propContent != consistent.second); + if (!consistent.first) + { + std::ostringstream e; + e << "The INTERFACE_" << p << " property of \"" + << theTarget->GetName() << "\" does\nnot agree with the value " + "of " << p << " already determined\nfor \"" + << tgt->GetName() << "\".\n"; + cmSystemTools::Error(e.str().c_str()); + break; + } + else + { + propContent = consistent.second; + continue; + } + } + else + { + report += reportEntry + "(Interface set)\n"; + propContent = ifacePropContent; + propInitialized = true; + } + } + else + { + // Not set. Nothing to agree on. + continue; + } + } + } + + tgt->ReportPropertyOrigin(p, valueAsString<PropertyType>(propContent), + report, compatibilityType(t)); + return propContent; +} + +//---------------------------------------------------------------------------- +bool cmGeneratorTarget::GetLinkInterfaceDependentBoolProperty( + const std::string &p, const std::string& config) const +{ + return checkInterfacePropertyCompatibility<bool>(this, p, config, + "FALSE", + BoolType, 0); +} + +//---------------------------------------------------------------------------- +const char* cmGeneratorTarget::GetLinkInterfaceDependentStringProperty( + const std::string &p, + const std::string& config) const +{ + return checkInterfacePropertyCompatibility<const char *>(this, + p, + config, + "empty", + StringType, 0); +} + +//---------------------------------------------------------------------------- +const char * cmGeneratorTarget::GetLinkInterfaceDependentNumberMinProperty( + const std::string &p, + const std::string& config) const +{ + return checkInterfacePropertyCompatibility<const char *>(this, + p, + config, + "empty", + NumberMinType, 0); +} + +//---------------------------------------------------------------------------- +const char * cmGeneratorTarget::GetLinkInterfaceDependentNumberMaxProperty( + const std::string &p, + const std::string& config) const +{ + return checkInterfacePropertyCompatibility<const char *>(this, + p, + config, + "empty", + NumberMaxType, 0); +} + +//---------------------------------------------------------------------------- +cmComputeLinkInformation* +cmGeneratorTarget::GetLinkInformation(const std::string& config) const +{ + // Lookup any existing information for this configuration. + std::string key(cmSystemTools::UpperCase(config)); + cmTargetLinkInformationMap::iterator + i = this->LinkInformation.find(key); + if(i == this->LinkInformation.end()) + { + // Compute information for this configuration. + cmComputeLinkInformation* info = + new cmComputeLinkInformation(this, config); + if(!info || !info->Compute()) + { + delete info; + info = 0; + } + + // Store the information for this configuration. + cmTargetLinkInformationMap::value_type entry(key, info); + i = this->LinkInformation.insert(entry).first; + + if (info) + { + this->CheckPropertyCompatibility(info, config); + } + } + return i->second; +} + +//---------------------------------------------------------------------------- +void +cmGeneratorTarget::ReportPropertyOrigin(const std::string &p, + const std::string &result, + const std::string &report, + const std::string &compatibilityType) const +{ + std::vector<std::string> debugProperties; + const char *debugProp = this->Target->GetMakefile() + ->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) + { + cmSystemTools::ExpandListArgument(debugProp, debugProperties); + } + + bool debugOrigin = !this->DebugCompatiblePropertiesDone[p] + && std::find(debugProperties.begin(), + debugProperties.end(), + p) + != debugProperties.end(); + + if (this->Target->GetMakefile()->IsConfigured()) + { + this->DebugCompatiblePropertiesDone[p] = true; + } + if (!debugOrigin) + { + return; + } + + std::string areport = compatibilityType; + areport += std::string(" of property \"") + p + "\" for target \""; + areport += std::string(this->GetName()); + areport += "\" (result: \""; + areport += result; + areport += "\"):\n" + report; + + this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG, areport); +} diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index a584c71..68e7a8a 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -20,11 +20,13 @@ class cmLocalGenerator; class cmMakefile; class cmSourceFile; class cmTarget; +class cmComputeLinkInformation; class cmGeneratorTarget { public: cmGeneratorTarget(cmTarget*, cmLocalGenerator* lg); + ~cmGeneratorTarget(); cmLocalGenerator* GetLocalGenerator() const; @@ -36,6 +38,9 @@ public: location is suitable for use as the LOCATION target property. */ const char* GetLocationForBuild() const; + cmComputeLinkInformation* + GetLinkInformation(const std::string& config) const; + int GetType() const; std::string GetName() const; const char *GetProperty(const std::string& prop) const; @@ -82,6 +87,26 @@ public: bool GetFeatureAsBool(const std::string& feature, const std::string& config) const; + bool IsLinkInterfaceDependentBoolProperty(const std::string &p, + const std::string& config) const; + bool IsLinkInterfaceDependentStringProperty(const std::string &p, + const std::string& config) const; + bool IsLinkInterfaceDependentNumberMinProperty(const std::string &p, + const std::string& config) const; + bool IsLinkInterfaceDependentNumberMaxProperty(const std::string &p, + const std::string& config) const; + + bool GetLinkInterfaceDependentBoolProperty(const std::string &p, + const std::string& config) const; + + const char *GetLinkInterfaceDependentStringProperty(const std::string &p, + const std::string& config) const; + const char *GetLinkInterfaceDependentNumberMinProperty(const std::string &p, + const std::string& config) const; + const char *GetLinkInterfaceDependentNumberMaxProperty(const std::string &p, + const std::string& config) const; + + /** Get the full path to the target according to the settings in its makefile and the configuration type. */ std::string GetFullPath(const std::string& config="", bool implib = false, @@ -90,6 +115,53 @@ public: bool realname) const; std::string NormalGetRealName(const std::string& config) const; + /** @return the Mac App directory without the base */ + std::string GetAppBundleDirectory(const std::string& config, + bool contentOnly) const; + + /** Return whether this target is an executable Bundle, a framework + or CFBundle on Apple. */ + bool IsBundleOnApple() const; + + /** Get the full name of the target according to the settings in its + makefile. */ + std::string GetFullName(const std::string& config="", + bool implib = false) const; + + /** @return the Mac framework directory without the base. */ + std::string GetFrameworkDirectory(const std::string& config, + bool rootDir) const; + + /** @return the Mac CFBundle directory without the base */ + std::string GetCFBundleDirectory(const std::string& config, + bool contentOnly) const; + + /** Return the install name directory for the target in the + * build tree. For example: "\@rpath/", "\@loader_path/", + * or "/full/path/to/library". */ + std::string GetInstallNameDirForBuildTree(const std::string& config) const; + + /** Return the install name directory for the target in the + * install tree. For example: "\@rpath/" or "\@loader_path/". */ + std::string GetInstallNameDirForInstallTree() const; + + /** Get the soname of the target. Allowed only for a shared library. */ + std::string GetSOName(const std::string& config) const; + + void GetFullNameComponents(std::string& prefix, + std::string& base, std::string& suffix, + const std::string& config="", + bool implib = false) const; + + /** Append to @a base the mac content directory and return it. */ + std::string BuildMacContentDirectory(const std::string& base, + const std::string& config = "", + bool contentOnly = true) const; + + /** @return the mac content directory for this target. */ + std::string GetMacContentDirectory(const std::string& config = 0, + bool implib = false) const; + cmTarget* Target; cmMakefile* Makefile; cmLocalGenerator* LocalGenerator; @@ -97,6 +169,20 @@ public: std::string GetModuleDefinitionFile(const std::string& config) const; + /** Link information from the transitive closure of the link + implementation and the interfaces of its dependencies. */ + struct LinkClosure + { + // The preferred linker language. + std::string LinkerLanguage; + + // Languages whose runtime libraries must be linked. + std::vector<std::string> Languages; + }; + + LinkClosure const* GetLinkClosure(const std::string& config) const; + void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const; + /** Full path with trailing slash to the top-level directory holding object files for this target. Includes the build time config name placeholder if needed for the generator. */ @@ -128,10 +214,41 @@ public: */ void TraceDependencies(); + /** 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 std::string& config = "") const; + /** Get sources that must be built before the given source. */ std::vector<cmSourceFile*> const* GetSourceDepends(cmSourceFile const* sf) const; + /** Get the name of the pdb file for the target. */ + std::string GetPDBName(const std::string& config="") const; + + /** Whether this library has soname enabled and platform supports it. */ + bool HasSOName(const std::string& config) const; + + struct CompileInfo + { + std::string CompilePdbDir; + }; + + CompileInfo const* GetCompileInfo(const std::string& config) const; + + typedef std::map<std::string, CompileInfo> CompileInfoMapType; + mutable CompileInfoMapType CompileInfoMap; + + /** Get the name of the compiler pdb file for the target. */ + std::string GetCompilePDBName(const std::string& config="") const; + + /** Get the path for the MSVC /Fd option for this target. */ + std::string GetCompilePDBPath(const std::string& config="") const; + + // Get the target base name. + std::string GetOutputName(const std::string& config, bool implib) const; + /** * Flags for a given source file as used in this target. Typically assigned * via SET_TARGET_PROPERTIES when the property is a list of source files. @@ -153,6 +270,33 @@ public: SourceFileType Type; const char* MacFolder; // location inside Mac content folders }; + void GetAutoUicOptions(std::vector<std::string> &result, + const std::string& config) const; + + /** Get the names of the executable needed to generate a build rule + that takes into account executable version numbers. This should + be called only on an executable target. */ + void GetExecutableNames(std::string& name, std::string& realName, + std::string& impName, std::string& pdbName, + const std::string& config) const; + + /** Get the names of the library needed to generate a build rule + that takes into account shared library version numbers. This + should be called only on a library target. */ + void GetLibraryNames(std::string& name, std::string& soName, + std::string& realName, std::string& impName, + std::string& pdbName, const std::string& config) const; + + /** + * Compute whether this target must be relinked before installing. + */ + bool NeedRelinkBeforeInstall(const std::string& config) const; + + /** Return true if builtin chrpath will work for this target */ + bool IsChrpathUsed(const std::string& config) const; + + ///! Return the preferred linker language for this target + std::string GetLinkerLanguage(const std::string& config = "") const; struct SourceFileFlags GetTargetSourceFileFlags(const cmSourceFile* sf) const; @@ -168,12 +312,16 @@ public: std::vector<cmSourceFile const*> XamlSources; }; + void ReportPropertyOrigin(const std::string &p, + const std::string &result, + const std::string &report, + const std::string &compatibilityType) const; + private: friend class cmTargetTraceDependencies; struct SourceEntry { std::vector<cmSourceFile*> Depends; }; typedef std::map<cmSourceFile const*, SourceEntry> SourceEntriesType; SourceEntriesType SourceEntries; - mutable std::map<cmSourceFile const*, std::string> Objects; std::set<cmSourceFile const*> ExplicitObjectName; mutable std::map<std::string, std::vector<std::string> > SystemIncludesCache; @@ -182,8 +330,55 @@ private: mutable bool SourceFileFlagsConstructed; mutable std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap; + mutable std::map<std::string, bool> DebugCompatiblePropertiesDone; + + std::string GetFullNameInternal(const std::string& config, + bool implib) const; + void GetFullNameInternal(const std::string& config, bool implib, + std::string& outPrefix, std::string& outBase, + std::string& outSuffix) const; + + typedef std::map<std::string, LinkClosure> LinkClosureMapType; + mutable LinkClosureMapType LinkClosureMap; + + struct CompatibleInterfacesBase + { + std::set<std::string> PropsBool; + std::set<std::string> PropsString; + std::set<std::string> PropsNumberMax; + std::set<std::string> PropsNumberMin; + }; + CompatibleInterfacesBase const& + GetCompatibleInterfaces(std::string const& config) const; + + struct CompatibleInterfaces: public CompatibleInterfacesBase + { + CompatibleInterfaces(): Done(false) {} + bool Done; + }; + mutable std::map<std::string, CompatibleInterfaces> CompatibleInterfacesMap; + + typedef std::map<std::string, cmComputeLinkInformation*> + cmTargetLinkInformationMap; + mutable cmTargetLinkInformationMap LinkInformation; + + void CheckPropertyCompatibility(cmComputeLinkInformation *info, + const std::string& config) const; + cmGeneratorTarget(cmGeneratorTarget const&); void operator=(cmGeneratorTarget const&); + + struct LinkImplClosure: public std::vector<cmTarget const*> + { + LinkImplClosure(): Done(false) {} + bool Done; + }; + mutable std::map<std::string, LinkImplClosure> LinkImplClosureMap; + +public: + std::vector<cmTarget const*> const& + GetLinkImplementationClosure(const std::string& config) const; + }; struct cmStrictTargetComparison { diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 2f9265a..1e57c33 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -128,7 +128,8 @@ void cmGhsMultiTargetGenerator::Generate() { config = "RELEASE"; } - const std::string language(this->Target->GetLinkerLanguage(config)); + const std::string language( + this->GeneratorTarget->GetLinkerLanguage(config)); config = cmSystemTools::UpperCase(config); this->DynamicDownload = this->DetermineIfDynamicDownload(config, language); if (this->DynamicDownload) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index cc7f78b..088f0e1 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -911,9 +911,7 @@ cmGlobalNinjaGenerator case cmTarget::STATIC_LIBRARY: case cmTarget::MODULE_LIBRARY: { - cmGeneratorTarget *gtgt = target->GetMakefile()->GetLocalGenerator() - ->GetGlobalGenerator() - ->GetGeneratorTarget(target); + cmGeneratorTarget *gtgt = this->GetGeneratorTarget(target); outputs.push_back(ng->ConvertToNinjaPath( gtgt->GetFullPath(configName, false, realname))); break; diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index edf2705..69747a4 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -482,7 +482,7 @@ cmGlobalUnixMakefileGenerator3 // Add this to the list of depends rules in this directory. if((!check_all || !gtarget->GetPropertyAsBool("EXCLUDE_FROM_ALL")) && (!check_relink || - gtarget->Target + gtarget ->NeedRelinkBeforeInstall(lg->GetConfigName()))) { std::string tname = lg->GetRelativeTargetDirectory(*gtarget->Target); @@ -691,7 +691,7 @@ cmGlobalUnixMakefileGenerator3 // Add a local name for the rule to relink the target before // installation. - if(gtarget->Target + if(gtarget ->NeedRelinkBeforeInstall(lg->GetConfigName())) { makeTargetName = lg->GetRelativeTargetDirectory(*gtarget->Target); @@ -876,7 +876,7 @@ cmGlobalUnixMakefileGenerator3 name, depends, commands, true); // Add rules to prepare the target for installation. - if(gtarget->Target + if(gtarget ->NeedRelinkBeforeInstall(lg->GetConfigName())) { localName = lg->GetRelativeTargetDirectory(*gtarget->Target); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 7dea107..5006828 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1376,7 +1376,8 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget& cmtarget) return; } - std::string llang = cmtarget.GetLinkerLanguage("NOCONFIG"); + cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&cmtarget); + std::string llang = gtgt->GetLinkerLanguage("NOCONFIG"); if(llang.empty()) { return; } // If the language is compiled as a source trust Xcode to link with it. @@ -1824,7 +1825,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, AddCompileOptions(flags, &target, lang, configName); } - std::string llang = target.GetLinkerLanguage(configName); + cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target); + std::string llang = gtgt->GetLinkerLanguage(configName); if(binary && llang.empty()) { cmSystemTools::Error @@ -1850,7 +1852,6 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, // Add the export symbol definition for shared library objects. this->AppendDefines(ppDefs, exportMacro); } - cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target); std::vector<std::string> targetDefines; target.GetCompileDefinitions(targetDefines, configName, "C"); this->AppendDefines(ppDefs, targetDefines); @@ -1940,11 +1941,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, std::string pnprefix; std::string pnbase; std::string pnsuffix; - target.GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName); + gtgt->GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName); const char* version = target.GetProperty("VERSION"); const char* soversion = target.GetProperty("SOVERSION"); - if(!target.HasSOName(configName) || target.IsFrameworkOnApple()) + if(!gtgt->HasSOName(configName) || target.IsFrameworkOnApple()) { version = 0; soversion = 0; @@ -2202,7 +2203,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, } } // Add framework search paths needed for linking. - if(cmComputeLinkInformation* cli = target.GetLinkInformation(configName)) + if(cmComputeLinkInformation* cli = gtgt->GetLinkInformation(configName)) { std::vector<std::string> const& fwDirs = cli->GetFrameworkPaths(); for(std::vector<std::string>::const_iterator fdi = fwDirs.begin(); @@ -2331,7 +2332,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, if(target.GetType() == cmTarget::SHARED_LIBRARY) { // Get the install_name directory for the build tree. - install_name_dir = target.GetInstallNameDirForBuildTree(configName); + install_name_dir = gtgt->GetInstallNameDirForBuildTree(configName); // Xcode doesn't create the correct install_name in some cases. // That is, if the INSTALL_PATH is empty, or if we have versioning // of dylib libraries, we want to specify the install_name. @@ -2345,7 +2346,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, install_name += install_name_dir; install_name += "/"; } - install_name += target.GetSOName(configName); + install_name += gtgt->GetSOName(configName); if((realName != soName) || install_name_dir.empty()) { @@ -2358,7 +2359,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, this->CreateString(install_name_dir.c_str())); // Create the LD_RUNPATH_SEARCH_PATHS - cmComputeLinkInformation* pcli = target.GetLinkInformation(configName); + cmComputeLinkInformation* pcli = gtgt->GetLinkInformation(configName); if(pcli) { std::string search_paths; @@ -2742,7 +2743,8 @@ cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget& cmtarget, } else { - fullName = cmtarget.GetFullName(defConfig.c_str()); + cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&cmtarget); + fullName = gtgt->GetFullName(defConfig.c_str()); } fileRef->AddAttribute("path", this->CreateString(fullName.c_str())); fileRef->AddAttribute("refType", this->CreateString("0")); @@ -2964,7 +2966,8 @@ void cmGlobalXCodeGenerator } // Compute the link library and directory information. - cmComputeLinkInformation* pcli = cmtarget->GetLinkInformation(configName); + cmGeneratorTarget* gtgt = this->GetGeneratorTarget(cmtarget); + cmComputeLinkInformation* pcli = gtgt->GetLinkInformation(configName); if(!pcli) { continue; @@ -3687,7 +3690,7 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( std::string universalFile = universal; universalFile += *arch; universalFile += "/"; - universalFile += t->GetFullName(configName); + universalFile += gt->GetFullName(configName); makefileStream << "\t/bin/rm -f " << this->ConvertToRelativeForMake(universalFile.c_str()) diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 01d4b77..30cf175 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -18,6 +18,7 @@ #include "cmMakefile.h" #include "cmGeneratorTarget.h" #include "cmake.h" +#include "cmGeneratorTarget.h" #include <assert.h> @@ -72,7 +73,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os, { // Compute the build tree directory from which to copy the target. std::string fromDirConfig; - if(this->Target->Target->NeedRelinkBeforeInstall(config)) + if(this->Target->NeedRelinkBeforeInstall(config)) { fromDirConfig = this->Target->Target->GetMakefile()->GetCurrentBinaryDirectory(); @@ -124,7 +125,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os, std::string targetNameReal; std::string targetNameImport; std::string targetNamePDB; - this->Target->Target->GetExecutableNames(targetName, targetNameReal, + this->Target->GetExecutableNames(targetName, targetNameReal, targetNameImport, targetNamePDB, config); if(this->ImportLibrary) @@ -184,7 +185,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os, std::string targetNameReal; std::string targetNameImport; std::string targetNamePDB; - this->Target->Target->GetLibraryNames(targetName, targetNameSO, + this->Target->GetLibraryNames(targetName, targetNameSO, targetNameReal, targetNameImport, targetNamePDB, config); @@ -371,13 +372,16 @@ cmInstallTargetGenerator::GetInstallFilename(cmTarget const* target, { std::string fname; // Compute the name of the library. + cmGeneratorTarget *gtgt = target->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(target); if(target->GetType() == cmTarget::EXECUTABLE) { std::string targetName; std::string targetNameReal; std::string targetNameImport; std::string targetNamePDB; - target->GetExecutableNames(targetName, targetNameReal, + gtgt->GetExecutableNames(targetName, targetNameReal, targetNameImport, targetNamePDB, config); if(nameType == NameImplib) @@ -407,7 +411,7 @@ cmInstallTargetGenerator::GetInstallFilename(cmTarget const* target, std::string targetNameReal; std::string targetNameImport; std::string targetNamePDB; - target->GetLibraryNames(targetName, targetNameSO, targetNameReal, + gtgt->GetLibraryNames(targetName, targetNameSO, targetNameReal, targetNameImport, targetNamePDB, config); if(nameType == NameImplib) { @@ -557,8 +561,7 @@ cmInstallTargetGenerator // Build a map of build-tree install_name to install-tree install_name for // shared libraries linked to this target. std::map<std::string, std::string> install_name_remap; - if(cmComputeLinkInformation* cli = - this->Target->Target->GetLinkInformation(config)) + if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config)) { std::set<cmTarget const*> const& sharedLibs = cli->GetSharedLibrariesLinked(); @@ -573,11 +576,14 @@ cmInstallTargetGenerator continue; } + cmGeneratorTarget *gtgt = tgt->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(tgt); // If the build tree and install tree use different path // components of the install_name field then we need to create a // mapping to be applied after installation. - std::string for_build = tgt->GetInstallNameDirForBuildTree(config); - std::string for_install = tgt->GetInstallNameDirForInstallTree(); + std::string for_build = gtgt->GetInstallNameDirForBuildTree(config); + std::string for_install = gtgt->GetInstallNameDirForInstallTree(); if(for_build != for_install) { // The directory portions differ. Append the filename to @@ -602,9 +608,9 @@ cmInstallTargetGenerator if(this->Target->GetType() == cmTarget::SHARED_LIBRARY) { std::string for_build = - this->Target->Target->GetInstallNameDirForBuildTree(config); + this->Target->GetInstallNameDirForBuildTree(config); std::string for_install = - this->Target->Target->GetInstallNameDirForInstallTree(); + this->Target->GetInstallNameDirForInstallTree(); if(this->Target->Target->IsFrameworkOnApple() && for_install.empty()) { @@ -653,11 +659,10 @@ cmInstallTargetGenerator std::string const& toDestDirPath) { // Skip the chrpath if the target does not need it. - if(this->ImportLibrary || !this->Target->Target->IsChrpathUsed(config)) + if(this->ImportLibrary || !this->Target->IsChrpathUsed(config)) { return; } - // Skip if on Apple if(this->Target->Target->GetMakefile() ->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) @@ -667,8 +672,7 @@ cmInstallTargetGenerator // Get the link information for this target. // It can provide the RPATH. - cmComputeLinkInformation* cli = - this->Target->Target->GetLinkInformation(config); + cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config); if(!cli) { return; @@ -693,15 +697,14 @@ cmInstallTargetGenerator std::string const& toDestDirPath) { // Skip the chrpath if the target does not need it. - if(this->ImportLibrary || !this->Target->Target->IsChrpathUsed(config)) + if(this->ImportLibrary || !this->Target->IsChrpathUsed(config)) { return; } // Get the link information for this target. // It can provide the RPATH. - cmComputeLinkInformation* cli = - this->Target->Target->GetLinkInformation(config); + cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config); if(!cli) { return; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index ea0f658..a831d88 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1401,7 +1401,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, linkFlags += this->Makefile->GetSafeDefinition(build); linkFlags += " "; } - std::string linkLanguage = target->Target->GetLinkerLanguage(buildType); + std::string linkLanguage = target->GetLinkerLanguage(buildType); if(linkLanguage.empty()) { cmSystemTools::Error @@ -1516,7 +1516,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries, bool escapeAllowMakeVars = !forResponseFile; std::ostringstream fout; std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - cmComputeLinkInformation* pcli = tgt.Target->GetLinkInformation(config); + cmComputeLinkInformation* pcli = tgt.GetLinkInformation(config); if(!pcli) { return; @@ -2107,7 +2107,9 @@ void cmLocalGenerator::AddCMP0018Flags(std::string &flags, return; } - if (target->GetLinkInterfaceDependentBoolProperty( + cmGeneratorTarget* gtgt = + this->GlobalGenerator->GetGeneratorTarget(target); + if (gtgt->GetLinkInterfaceDependentBoolProperty( "POSITION_INDEPENDENT_CODE", config)) { diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 98bd0ab..ce370bc 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -486,8 +486,7 @@ void cmLocalUnixMakefileGenerator3 // Add a local name for the rule to relink the target before // installation. - if(t->second->Target - ->NeedRelinkBeforeInstall(this->ConfigName)) + if(t->second->NeedRelinkBeforeInstall(this->ConfigName)) { makeTargetName = this->GetRelativeTargetDirectory(*t->second->Target); makeTargetName += "/preinstall"; diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index cab5a47..29e1034 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -1115,10 +1115,12 @@ void cmLocalVisualStudio6Generator cmTarget* tgt = this->GlobalGenerator->FindTarget(j->first.c_str()); if(tgt) { + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(tgt); lib = cmSystemTools::GetFilenameWithoutExtension - (tgt->GetFullName().c_str()); + (gt->GetFullName().c_str()); libDebug = cmSystemTools::GetFilenameWithoutExtension - (tgt->GetFullName("Debug").c_str()); + (gt->GetFullName("Debug").c_str()); lib += ".lib"; libDebug += ".lib"; } @@ -1258,8 +1260,8 @@ void cmLocalVisualStudio6Generator extraLinkOptionsRelWithDebInfo += targetLinkFlags; } - - + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); // Get standard libraries for this language. if(targetBuilds) @@ -1268,10 +1270,10 @@ void cmLocalVisualStudio6Generator std::vector<std::string> configs; target.GetMakefile()->GetConfigurations(configs); std::vector<std::string>::const_iterator it = configs.begin(); - const std::string& linkLanguage = target.GetLinkerLanguage(*it); + const std::string& linkLanguage = gt->GetLinkerLanguage(*it); for ( ; it != configs.end(); ++it) { - const std::string& configLinkLanguage = target.GetLinkerLanguage(*it); + const std::string& configLinkLanguage = gt->GetLinkerLanguage(*it); if (configLinkLanguage != linkLanguage) { cmSystemTools::Error @@ -1328,11 +1330,11 @@ void cmLocalVisualStudio6Generator target.GetType() == cmTarget::SHARED_LIBRARY || target.GetType() == cmTarget::MODULE_LIBRARY) { - outputName = target.GetFullName(); - outputNameDebug = target.GetFullName("Debug"); - outputNameRelease = target.GetFullName("Release"); - outputNameMinSizeRel = target.GetFullName("MinSizeRel"); - outputNameRelWithDebInfo = target.GetFullName("RelWithDebInfo"); + outputName = gt->GetFullName(); + outputNameDebug = gt->GetFullName("Debug"); + outputNameRelease = gt->GetFullName("Release"); + outputNameMinSizeRel = gt->GetFullName("MinSizeRel"); + outputNameRelWithDebInfo = gt->GetFullName("RelWithDebInfo"); } else if(target.GetType() == cmTarget::OBJECT_LIBRARY) { @@ -1429,10 +1431,10 @@ void cmLocalVisualStudio6Generator fullPathImpRelease += "/"; fullPathImpMinSizeRel += "/"; fullPathImpRelWithDebInfo += "/"; - fullPathImpDebug += target.GetFullName("Debug", true); - fullPathImpRelease += target.GetFullName("Release", true); - fullPathImpMinSizeRel += target.GetFullName("MinSizeRel", true); - fullPathImpRelWithDebInfo += target.GetFullName("RelWithDebInfo", true); + fullPathImpDebug += gt->GetFullName("Debug", true); + fullPathImpRelease += gt->GetFullName("Release", true); + fullPathImpMinSizeRel += gt->GetFullName("MinSizeRel", true); + fullPathImpRelWithDebInfo += gt->GetFullName("RelWithDebInfo", true); targetImplibFlagDebug = "/implib:"; targetImplibFlagRelease = "/implib:"; @@ -1701,10 +1703,10 @@ void cmLocalVisualStudio6Generator std::vector<std::string> configs; target.GetMakefile()->GetConfigurations(configs); std::vector<std::string>::const_iterator it = configs.begin(); - const std::string& linkLanguage = target.GetLinkerLanguage(*it); + const std::string& linkLanguage = gt->GetLinkerLanguage(*it); for ( ; it != configs.end(); ++it) { - const std::string& configLinkLanguage = target.GetLinkerLanguage(*it); + const std::string& configLinkLanguage = gt->GetLinkerLanguage(*it); if (configLinkLanguage != linkLanguage) { cmSystemTools::Error @@ -1846,8 +1848,10 @@ void cmLocalVisualStudio6Generator const std::string extraOptions, std::string& options) { + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); // Compute the link information for this configuration. - cmComputeLinkInformation* pcli = target.GetLinkInformation(configName); + cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName); if(!pcli) { return; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 572dbde..a38a061 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -664,6 +664,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, const char* configType = "10"; const char* projectType = 0; bool targetBuilds = true; + + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + switch(target.GetType()) { case cmTarget::OBJECT_LIBRARY: @@ -696,7 +700,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, { const std::string& linkLanguage = (this->FortranProject? std::string("Fortran"): - target.GetLinkerLanguage(configName)); + gt->GetLinkerLanguage(configName)); if(linkLanguage.empty()) { cmSystemTools::Error @@ -758,8 +762,6 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, targetOptions.Parse(flags.c_str()); targetOptions.Parse(defineFlags.c_str()); targetOptions.ParseFinish(); - cmGeneratorTarget* gt = - this->GlobalGenerator->GetGeneratorTarget(&target); std::vector<std::string> targetDefines; target.GetCompileDefinitions(targetDefines, configName, "CXX"); targetOptions.AddDefines(targetDefines); @@ -803,7 +805,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, if (this->FortranProject) { // Intel Fortran >= 15.0 uses TargetName property. - std::string targetNameFull = target.GetFullName(configName); + std::string targetNameFull = gt->GetFullName(configName); std::string targetName = cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull); std::string targetExt = @@ -881,7 +883,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, if(target.GetType() <= cmTarget::OBJECT_LIBRARY) { // Specify the compiler program database file if configured. - std::string pdb = target.GetCompilePDBPath(configName); + std::string pdb = gt->GetCompilePDBPath(configName); if(!pdb.empty()) { fout << "\t\t\t\tProgramDataBaseFileName=\"" @@ -1074,6 +1076,9 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, this->ConvertToOutputFormat(this->ModuleDefinitionFile, SHELL); linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str()); } + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + if (target.GetType() == cmTarget::SHARED_LIBRARY && this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")) { @@ -1104,7 +1109,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, } case cmTarget::STATIC_LIBRARY: { - std::string targetNameFull = target.GetFullName(configName); + std::string targetNameFull = gt->GetFullName(configName); std::string libpath = target.GetDirectory(configName); libpath += "/"; libpath += targetNameFull; @@ -1144,11 +1149,11 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, std::string targetNameFull; std::string targetNameImport; std::string targetNamePDB; - target.GetLibraryNames(targetName, targetNameSO, targetNameFull, + gt->GetLibraryNames(targetName, targetNameSO, targetNameFull, targetNameImport, targetNamePDB, configName); // Compute the link library and directory information. - cmComputeLinkInformation* pcli = target.GetLinkInformation(configName); + cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName); if(!pcli) { return; @@ -1241,11 +1246,11 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, std::string targetNameFull; std::string targetNameImport; std::string targetNamePDB; - target.GetExecutableNames(targetName, targetNameFull, + gt->GetExecutableNames(targetName, targetNameFull, targetNameImport, targetNamePDB, configName); // Compute the link library and directory information. - cmComputeLinkInformation* pcli = target.GetLinkInformation(configName); + cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName); if(!pcli) { return; @@ -1632,7 +1637,7 @@ cmLocalVisualStudio7GeneratorFCInfo lg->GlobalGenerator->GetLanguageFromExtension (sf.GetExtension().c_str()); const std::string& sourceLang = lg->GetSourceFileLanguage(sf); - const std::string& linkLanguage = target.GetLinkerLanguage(i->c_str()); + const std::string& linkLanguage = gt->GetLinkerLanguage(i->c_str()); bool needForceLang = false; // source file does not match its extension language if(lang != sourceLang) diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 416063f..ccb0974 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -25,7 +25,7 @@ cmMakefileExecutableTargetGenerator cmMakefileTargetGenerator(target) { this->CustomCommandDriver = OnDepends; - this->Target->GetExecutableNames( + this->GeneratorTarget->GetExecutableNames( this->TargetNameOut, this->TargetNameReal, this->TargetNameImport, this->TargetNamePDB, this->ConfigName); @@ -58,7 +58,7 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles() // write the link rules this->WriteExecutableRule(false); - if(this->Target->NeedRelinkBeforeInstall(this->ConfigName)) + if(this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) { // Write rules to link an installable version of the target. this->WriteExecutableRule(true); @@ -94,7 +94,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) std::string targetNameReal; std::string targetNameImport; std::string targetNamePDB; - this->Target->GetExecutableNames + this->GeneratorTarget->GetExecutableNames (targetName, targetNameReal, targetNameImport, targetNamePDB, this->ConfigName); @@ -130,7 +130,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) } std::string compilePdbOutputPath = - this->Target->GetCompilePDBDirectory(this->ConfigName); + this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName); cmSystemTools::MakeDirectory(compilePdbOutputPath.c_str()); std::string pdbOutputPath = this->Target->GetPDBDirectory(this->ConfigName); @@ -161,7 +161,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Get the language to use for linking this executable. std::string linkLanguage = - this->Target->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); // Make sure we have a link language. if(linkLanguage.empty()) diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 696dcc4..2f995e8 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -28,7 +28,7 @@ cmMakefileLibraryTargetGenerator this->CustomCommandDriver = OnDepends; if (this->Target->GetType() != cmTarget::INTERFACE_LIBRARY) { - this->Target->GetLibraryNames( + this->GeneratorTarget->GetLibraryNames( this->TargetNameOut, this->TargetNameSO, this->TargetNameReal, this->TargetNameImport, this->TargetNamePDB, this->ConfigName); } @@ -69,7 +69,7 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles() break; case cmTarget::SHARED_LIBRARY: this->WriteSharedLibraryRules(false); - if(this->Target->NeedRelinkBeforeInstall(this->ConfigName)) + if(this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) { // Write rules to link an installable version of the target. this->WriteSharedLibraryRules(true); @@ -77,7 +77,7 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles() break; case cmTarget::MODULE_LIBRARY: this->WriteModuleLibraryRules(false); - if(this->Target->NeedRelinkBeforeInstall(this->ConfigName)) + if(this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName)) { // Write rules to link an installable version of the target. this->WriteModuleLibraryRules(true); @@ -133,7 +133,7 @@ void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules() void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules() { std::string linkLanguage = - this->Target->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); std::string linkRuleVar = "CMAKE_"; linkRuleVar += linkLanguage; linkRuleVar += "_CREATE_STATIC_LIBRARY"; @@ -159,7 +159,7 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) return; } std::string linkLanguage = - this->Target->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); std::string linkRuleVar = "CMAKE_"; linkRuleVar += linkLanguage; linkRuleVar += "_CREATE_SHARED_LIBRARY"; @@ -183,7 +183,7 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) { std::string linkLanguage = - this->Target->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); std::string linkRuleVar = "CMAKE_"; linkRuleVar += linkLanguage; linkRuleVar += "_CREATE_SHARED_MODULE"; @@ -206,7 +206,7 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink) { std::string linkLanguage = - this->Target->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); std::string linkRuleVar = "CMAKE_"; linkRuleVar += linkLanguage; linkRuleVar += "_CREATE_MACOSX_FRAMEWORK"; @@ -238,7 +238,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules // Get the language to use for linking this library. std::string linkLanguage = - this->Target->GetLinkerLanguage(this->ConfigName); + this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); // Make sure we have a link language. if(linkLanguage.empty()) @@ -266,7 +266,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules std::string targetNameReal; std::string targetNameImport; std::string targetNamePDB; - this->Target->GetLibraryNames( + this->GeneratorTarget->GetLibraryNames( targetName, targetNameSO, targetNameReal, targetNameImport, targetNamePDB, this->ConfigName); @@ -311,7 +311,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules } std::string compilePdbOutputPath = - this->Target->GetCompilePDBDirectory(this->ConfigName); + this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName); cmSystemTools::MakeDirectory(compilePdbOutputPath.c_str()); std::string pdbOutputPath = this->Target->GetPDBDirectory(this->ConfigName); @@ -653,7 +653,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules vars.Target = target.c_str(); vars.LinkLibraries = linkLibs.c_str(); vars.ObjectsQuoted = buildObjs.c_str(); - if (this->Target->HasSOName(this->ConfigName)) + if (this->GeneratorTarget->HasSOName(this->ConfigName)) { vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage); vars.TargetSOName= targetNameSO.c_str(); @@ -666,7 +666,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules { // Get the install_name directory for the build tree. install_name_dir = - this->Target->GetInstallNameDirForBuildTree(this->ConfigName); + this->GeneratorTarget->GetInstallNameDirForBuildTree(this->ConfigName); // Set the rule variable replacement value. if(install_name_dir.empty()) diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 5edc0f5..0b3df90 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -313,7 +313,7 @@ cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator() (cmSourceFile const& source, const char* pkgloc) { // Skip OS X content when not building a Framework or Bundle. - if(!this->Generator->GetTarget()->IsBundleOnApple()) + if(!this->Generator->GetGeneratorTarget()->IsBundleOnApple()) { return; } @@ -548,12 +548,12 @@ cmMakefileTargetGenerator this->GeneratorTarget->GetFullPath(this->ConfigName, false, true); targetFullPathPDB = this->Target->GetPDBDirectory(this->ConfigName); targetFullPathPDB += "/"; - targetFullPathPDB += this->Target->GetPDBName(this->ConfigName); + targetFullPathPDB += this->GeneratorTarget->GetPDBName(this->ConfigName); } if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY) { targetFullPathCompilePDB = - this->Target->GetCompilePDBPath(this->ConfigName); + this->GeneratorTarget->GetCompilePDBPath(this->ConfigName); if(targetFullPathCompilePDB.empty()) { targetFullPathCompilePDB = this->Target->GetSupportDirectory() + "/"; @@ -1446,7 +1446,8 @@ void cmMakefileTargetGenerator // Loop over all library dependencies. const char* cfg = this->LocalGenerator->GetConfigName().c_str(); - if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg)) + if(cmComputeLinkInformation* cli = + this->GeneratorTarget->GetLinkInformation(cfg)) { std::vector<std::string> const& libDeps = cli->GetDepends(); depends.insert(depends.end(), libDeps.begin(), libDeps.end()); @@ -1508,7 +1509,7 @@ std::string cmMakefileTargetGenerator::GetLinkRule( if(this->Target->HasImplibGNUtoMS()) { std::string ruleVar = "CMAKE_"; - ruleVar += this->Target->GetLinkerLanguage(this->ConfigName); + ruleVar += this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); ruleVar += "_GNUtoMS_RULE"; if(const char* rule = this->Makefile->GetDefinition(ruleVar)) { @@ -1662,7 +1663,8 @@ cmMakefileTargetGenerator { // Lookup the response file reference flag. std::string responseFlagVar = "CMAKE_"; - responseFlagVar += this->Target->GetLinkerLanguage(this->ConfigName); + responseFlagVar += this->GeneratorTarget + ->GetLinkerLanguage(this->ConfigName); responseFlagVar += "_RESPONSE_FILE_LINK_FLAG"; const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar); @@ -1706,7 +1708,8 @@ cmMakefileTargetGenerator // Lookup the response file reference flag. std::string responseFlagVar = "CMAKE_"; - responseFlagVar += this->Target->GetLinkerLanguage(this->ConfigName); + responseFlagVar += this->GeneratorTarget + ->GetLinkerLanguage(this->ConfigName); responseFlagVar += "_RESPONSE_FILE_LINK_FLAG"; const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar); diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index b885672..fd4527b 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -53,6 +53,7 @@ public: { return this->ProgressFileNameFull; } cmTarget* GetTarget() { return this->Target;} + cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget;} protected: diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index c9fa7c0..b855bea 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -40,16 +40,15 @@ cmNinjaNormalTargetGenerator(cmGeneratorTarget* target) , TargetNamePDB() , TargetLinkLanguage("") { - this->TargetLinkLanguage = target->Target - ->GetLinkerLanguage(this->GetConfigName()); + this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName()); if (target->GetType() == cmTarget::EXECUTABLE) - target->Target->GetExecutableNames(this->TargetNameOut, + this->GetGeneratorTarget()->GetExecutableNames(this->TargetNameOut, this->TargetNameReal, this->TargetNameImport, this->TargetNamePDB, GetLocalGenerator()->GetConfigName()); else - target->Target->GetLibraryNames(this->TargetNameOut, + this->GetGeneratorTarget()->GetLibraryNames(this->TargetNameOut, this->TargetNameSO, this->TargetNameReal, this->TargetNameImport, @@ -531,13 +530,14 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() vars["LANGUAGE_COMPILE_FLAGS"] = t; } - if (target.HasSOName(cfgName)) + if (this->GetGeneratorTarget()->HasSOName(cfgName)) { vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage); vars["SONAME"] = this->TargetNameSO; if (targetType == cmTarget::SHARED_LIBRARY) { - std::string install_dir = target.GetInstallNameDirForBuildTree(cfgName); + std::string install_dir = + this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(cfgName); if (!install_dir.empty()) { vars["INSTALLNAME_DIR"] = localGen.Convert(install_dir, @@ -569,7 +569,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() std::string prefix; std::string base; std::string suffix; - target.GetFullNameComponents(prefix, base, suffix); + this->GetGeneratorTarget()->GetFullNameComponents(prefix, base, suffix); std::string dbg_suffix = ".dbg"; // TODO: Where to document? if (mf->GetDefinition("CMAKE_DEBUG_SYMBOL_SUFFIX")) diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 4e4dc3f..07efa16 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -195,7 +195,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const return cmNinjaDeps(); cmComputeLinkInformation* cli = - this->Target->GetLinkInformation(this->GetConfigName()); + this->GeneratorTarget->GetLinkInformation(this->GetConfigName()); if(!cli) return cmNinjaDeps(); @@ -273,11 +273,12 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const { pdbPath = this->Target->GetPDBDirectory(this->GetConfigName()); pdbPath += "/"; - pdbPath += this->Target->GetPDBName(this->GetConfigName()); + pdbPath += this->GeneratorTarget->GetPDBName(this->GetConfigName()); } if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY) { - compilePdbPath = this->Target->GetCompilePDBPath(this->GetConfigName()); + compilePdbPath = + this->GeneratorTarget->GetCompilePDBPath(this->GetConfigName()); if(compilePdbPath.empty()) { compilePdbPath = this->Target->GetSupportDirectory() + "/"; @@ -741,7 +742,7 @@ cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( cmSourceFile const& source, const char* pkgloc) { // Skip OS X content when not building a Framework or Bundle. - if(!this->Generator->GetTarget()->IsBundleOnApple()) + if(!this->Generator->GetGeneratorTarget()->IsBundleOnApple()) { return; } diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx index 3bc0eb7..4fe99e3 100644 --- a/Source/cmOSXBundleGenerator.cxx +++ b/Source/cmOSXBundleGenerator.cxx @@ -47,7 +47,7 @@ void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName, // Compute bundle directory names. std::string out = outpath; out += "/"; - out += this->GT->Target->GetAppBundleDirectory(this->ConfigName, false); + out += this->GT->GetAppBundleDirectory(this->ConfigName, false); cmSystemTools::MakeDirectory(out.c_str()); this->Makefile->AddCMakeOutputFile(out); @@ -57,7 +57,7 @@ void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName, // to be set. std::string plist = outpath; plist += "/"; - plist += this->GT->Target->GetAppBundleDirectory(this->ConfigName, true); + plist += this->GT->GetAppBundleDirectory(this->ConfigName, true); plist += "/Info.plist"; this->LocalGenerator->GenerateAppleInfoPList(this->GT->Target, targetName, @@ -77,11 +77,11 @@ void cmOSXBundleGenerator::CreateFramework( // Compute the location of the top-level foo.framework directory. std::string contentdir = outpath + "/" + - this->GT->Target->GetFrameworkDirectory(this->ConfigName, true); + this->GT->GetFrameworkDirectory(this->ConfigName, true); contentdir += "/"; std::string newoutpath = outpath + "/" + - this->GT->Target->GetFrameworkDirectory(this->ConfigName, false); + this->GT->GetFrameworkDirectory(this->ConfigName, false); std::string frameworkVersion = this->GT->Target->GetFrameworkVersion(); @@ -172,14 +172,14 @@ void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName, // Compute bundle directory names. std::string out = root; out += "/"; - out += this->GT->Target->GetCFBundleDirectory(this->ConfigName, false); + out += this->GT->GetCFBundleDirectory(this->ConfigName, false); cmSystemTools::MakeDirectory(out.c_str()); this->Makefile->AddCMakeOutputFile(out); // Configure the Info.plist file. Note that it needs the executable name // to be set. std::string plist = root + "/" + - this->GT->Target->GetCFBundleDirectory(this->ConfigName, true); + this->GT->GetCFBundleDirectory(this->ConfigName, true); plist += "/Info.plist"; std::string name = cmSystemTools::GetFilenameName(targetName); this->LocalGenerator->GenerateAppleInfoPList(this->GT->Target, @@ -217,7 +217,7 @@ cmOSXBundleGenerator::InitMacOSXContentDirectory(const char* pkgloc) // Construct the full path to the content subdirectory. std::string macdir = - this->GT->Target->GetMacContentDirectory(this->ConfigName, + this->GT->GetMacContentDirectory(this->ConfigName, /*implib*/ false); macdir += "/"; macdir += pkgloc; diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx index a612437..35ee127 100644 --- a/Source/cmOrderDirectories.cxx +++ b/Source/cmOrderDirectories.cxx @@ -280,7 +280,7 @@ bool cmOrderDirectoriesConstraintLibrary::FindConflict(std::string const& dir) //---------------------------------------------------------------------------- cmOrderDirectories::cmOrderDirectories(cmGlobalGenerator* gg, - cmTarget const* target, + const cmGeneratorTarget* target, const char* purpose) { this->GlobalGenerator = gg; @@ -554,7 +554,8 @@ void cmOrderDirectories::FindImplicitConflicts() << text << "Some of these libraries may not be found correctly."; this->GlobalGenerator->GetCMakeInstance() - ->IssueMessage(cmake::WARNING, w.str(), this->Target->GetBacktrace()); + ->IssueMessage(cmake::WARNING, w.str(), + this->Target->Target->GetBacktrace()); } //---------------------------------------------------------------------------- @@ -635,5 +636,6 @@ void cmOrderDirectories::DiagnoseCycle() } e << "Some of these libraries may not be found correctly."; this->GlobalGenerator->GetCMakeInstance() - ->IssueMessage(cmake::WARNING, e.str(), this->Target->GetBacktrace()); + ->IssueMessage(cmake::WARNING, e.str(), + this->Target->Target->GetBacktrace()); } diff --git a/Source/cmOrderDirectories.h b/Source/cmOrderDirectories.h index cb5a51f..211c786 100644 --- a/Source/cmOrderDirectories.h +++ b/Source/cmOrderDirectories.h @@ -19,7 +19,7 @@ class cmGlobalGenerator; class cmOrderDirectoriesConstraint; class cmOrderDirectoriesConstraintLibrary; -class cmTarget; +class cmGeneratorTarget; /** \class cmOrderDirectories * \brief Compute a safe runtime path order for a set of shared libraries. @@ -27,7 +27,7 @@ class cmTarget; class cmOrderDirectories { public: - cmOrderDirectories(cmGlobalGenerator* gg, cmTarget const* target, + cmOrderDirectories(cmGlobalGenerator* gg, cmGeneratorTarget const* target, const char* purpose); ~cmOrderDirectories(); void AddRuntimeLibrary(std::string const& fullPath, const char* soname = 0); @@ -41,7 +41,7 @@ public: std::vector<std::string> const& GetOrderedDirectories(); private: cmGlobalGenerator* GlobalGenerator; - cmTarget const* Target; + cmGeneratorTarget const* Target; std::string Purpose; std::vector<std::string> OrderedDirectories; diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 1322dea..f1ba2f4 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -547,8 +547,11 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget const* target) { qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR"); } + cmGeneratorTarget *gtgt = target->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(target); if (const char *targetQtVersion = - target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "")) + gtgt->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "")) { qtVersion = targetQtVersion; } @@ -878,8 +881,11 @@ void cmQtAutoGenerators::MergeUicOptions(std::vector<std::string> &opts, static void GetUicOpts(cmTarget const* target, const std::string& config, std::string &optString) { + cmGeneratorTarget *gtgt = target->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(target); std::vector<std::string> opts; - target->GetAutoUicOptions(opts, config); + gtgt->GetAutoUicOptions(opts, config); optString = cmJoin(opts, ";"); } @@ -1147,6 +1153,9 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget const* target) std::string cmQtAutoGenerators::GetRccExecutable(cmTarget const* target) { + cmGeneratorTarget *gtgt = target->GetMakefile() + ->GetGlobalGenerator() + ->GetGeneratorTarget(target); cmMakefile *makefile = target->GetMakefile(); const char *qtVersion = makefile->GetDefinition("_target_qt_version"); if (!qtVersion) @@ -1157,8 +1166,7 @@ std::string cmQtAutoGenerators::GetRccExecutable(cmTarget const* target) qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR"); } if (const char *targetQtVersion = - target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", - "")) + gtgt->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "")) { qtVersion = targetQtVersion; } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index cf33791..1f8f07a 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -69,27 +69,6 @@ struct cmTarget::OutputInfo }; //---------------------------------------------------------------------------- -struct cmTarget::ImportInfo -{ - ImportInfo(): NoSOName(false), Multiplicity(0) {} - bool NoSOName; - int Multiplicity; - std::string Location; - std::string SOName; - std::string ImportLibrary; - std::string Languages; - std::string Libraries; - std::string LibrariesProp; - std::string SharedDeps; -}; - -//---------------------------------------------------------------------------- -struct cmTarget::CompileInfo -{ - std::string CompilePdbDir; -}; - -//---------------------------------------------------------------------------- class cmTargetInternals { public: @@ -147,9 +126,6 @@ public: typedef std::map<std::string, cmTarget::ImportInfo> ImportInfoMapType; ImportInfoMapType ImportInfoMap; - typedef std::map<std::string, cmTarget::CompileInfo> CompileInfoMapType; - CompileInfoMapType CompileInfoMap; - // Cache link implementation computation from each configuration. struct OptionalLinkImplementation: public cmTarget::LinkImplementation { @@ -175,23 +151,6 @@ public: HeadToLinkImplementationMap> LinkImplMapType; LinkImplMapType LinkImplMap; - typedef std::map<std::string, cmTarget::LinkClosure> LinkClosureMapType; - LinkClosureMapType LinkClosureMap; - - struct LinkImplClosure: public std::vector<cmTarget const*> - { - LinkImplClosure(): Done(false) {} - bool Done; - }; - std::map<std::string, LinkImplClosure> LinkImplClosureMap; - - struct CompatibleInterfaces: public cmTarget::CompatibleInterfaces - { - CompatibleInterfaces(): Done(false) {} - bool Done; - }; - std::map<std::string, CompatibleInterfaces> CompatibleInterfacesMap; - typedef std::map<std::string, std::vector<cmSourceFile*> > SourceFilesMapType; SourceFilesMapType SourceFilesMap; @@ -540,10 +499,7 @@ void cmTarget::ClearLinkMaps() this->Internal->LinkImplMap.clear(); this->Internal->LinkInterfaceMap.clear(); this->Internal->LinkInterfaceUsageRequirementsOnlyMap.clear(); - this->Internal->LinkClosureMap.clear(); this->Internal->SourceFilesMap.clear(); - cmDeleteAll(this->LinkInformation); - this->LinkInformation.clear(); } //---------------------------------------------------------------------------- @@ -625,13 +581,6 @@ bool cmTarget::IsXCTestOnApple() const } //---------------------------------------------------------------------------- -bool cmTarget::IsBundleOnApple() const -{ - return this->IsFrameworkOnApple() || this->IsAppBundleOnApple() || - this->IsCFBundleOnApple(); -} - -//---------------------------------------------------------------------------- static bool processSources(cmTarget const* tgt, const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries, std::vector<std::string> &srcs, @@ -2251,31 +2200,6 @@ static void processCompileOptions(cmTarget const* tgt, } //---------------------------------------------------------------------------- -void cmTarget::GetAutoUicOptions(std::vector<std::string> &result, - const std::string& config) const -{ - const char *prop - = this->GetLinkInterfaceDependentStringProperty("AUTOUIC_OPTIONS", - config); - if (!prop) - { - return; - } - cmGeneratorExpression ge; - - cmGeneratorExpressionDAGChecker dagChecker( - this->GetName(), - "AUTOUIC_OPTIONS", 0, 0); - cmSystemTools::ExpandListArgument(ge.Parse(prop) - ->Evaluate(this->Makefile, - config, - false, - this, - &dagChecker), - result); -} - -//---------------------------------------------------------------------------- void cmTarget::GetCompileOptions(std::vector<std::string> &result, const std::string& config, const std::string& language) const @@ -2671,45 +2595,6 @@ cmTarget::OutputInfo const* cmTarget::GetOutputInfo( } //---------------------------------------------------------------------------- -cmTarget::CompileInfo const* cmTarget::GetCompileInfo( - const std::string& 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); - return 0; - } - - // Lookup/compute/cache the compile information for this configuration. - std::string config_upper; - if(!config.empty()) - { - 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 std::string& config, bool implib) const { @@ -2740,16 +2625,6 @@ std::string cmTarget::GetPDBDirectory(const std::string& config) const } //---------------------------------------------------------------------------- -std::string cmTarget::GetCompilePDBDirectory(const std::string& config) const -{ - if(CompileInfo const* info = this->GetCompileInfo(config)) - { - return info->CompilePdbDir; - } - return ""; -} - -//---------------------------------------------------------------------------- const char* cmTarget::ImportedGetLocation(const std::string& config) const { static std::string location; @@ -3192,229 +3067,6 @@ bool cmTarget::GetPropertyAsBool(const std::string& prop) const } //---------------------------------------------------------------------------- -class cmTargetCollectLinkLanguages -{ -public: - cmTargetCollectLinkLanguages(cmTarget const* target, - const std::string& config, - UNORDERED_SET<std::string>& languages, - cmTarget const* head): - Config(config), Languages(languages), HeadTarget(head), - Makefile(target->GetMakefile()), Target(target) - { this->Visited.insert(target); } - - void Visit(cmLinkItem const& item) - { - if(!item.Target) - { - if(item.find("::") != std::string::npos) - { - bool noMessage = false; - cmake::MessageType messageType = cmake::FATAL_ERROR; - std::ostringstream e; - switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0028)) - { - case cmPolicies::WARN: - { - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0028) << "\n"; - messageType = cmake::AUTHOR_WARNING; - } - break; - case cmPolicies::OLD: - noMessage = true; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::NEW: - // Issue the fatal message. - break; - } - - if(!noMessage) - { - e << "Target \"" << this->Target->GetName() - << "\" links to target \"" << item - << "\" but the target was not found. Perhaps a find_package() " - "call is missing for an IMPORTED target, or an ALIAS target is " - "missing?"; - this->Makefile->GetCMakeInstance()->IssueMessage(messageType, - e.str(), - this->Target->GetBacktrace()); - } - } - return; - } - if(!this->Visited.insert(item.Target).second) - { - return; - } - - cmTarget::LinkInterface const* iface = - item.Target->GetLinkInterface(this->Config, this->HeadTarget); - if(!iface) { return; } - - for(std::vector<std::string>::const_iterator - li = iface->Languages.begin(); li != iface->Languages.end(); ++li) - { - this->Languages.insert(*li); - } - - for(std::vector<cmLinkItem>::const_iterator - li = iface->Libraries.begin(); li != iface->Libraries.end(); ++li) - { - this->Visit(*li); - } - } -private: - std::string Config; - UNORDERED_SET<std::string>& Languages; - cmTarget const* HeadTarget; - cmMakefile* Makefile; - const cmTarget* Target; - std::set<cmTarget const*> Visited; -}; - -//---------------------------------------------------------------------------- -std::string cmTarget::GetLinkerLanguage(const std::string& config) const -{ - return this->GetLinkClosure(config)->LinkerLanguage; -} - -//---------------------------------------------------------------------------- -cmTarget::LinkClosure const* -cmTarget::GetLinkClosure(const std::string& config) const -{ - std::string key(cmSystemTools::UpperCase(config)); - cmTargetInternals::LinkClosureMapType::iterator - i = this->Internal->LinkClosureMap.find(key); - if(i == this->Internal->LinkClosureMap.end()) - { - LinkClosure lc; - this->ComputeLinkClosure(config, lc); - cmTargetInternals::LinkClosureMapType::value_type entry(key, lc); - i = this->Internal->LinkClosureMap.insert(entry).first; - } - return &i->second; -} - -//---------------------------------------------------------------------------- -class cmTargetSelectLinker -{ - int Preference; - cmTarget const* Target; - cmMakefile* Makefile; - cmGlobalGenerator* GG; - UNORDERED_SET<std::string> Preferred; -public: - cmTargetSelectLinker(cmTarget const* target): Preference(0), Target(target) - { - this->Makefile = this->Target->GetMakefile(); - this->GG = this->Makefile->GetGlobalGenerator(); - } - void Consider(const std::string& lang) - { - int preference = this->GG->GetLinkerPreference(lang); - if(preference > this->Preference) - { - this->Preference = preference; - this->Preferred.clear(); - } - if(preference == this->Preference) - { - this->Preferred.insert(lang); - } - } - std::string Choose() - { - if(this->Preferred.empty()) - { - return ""; - } - else if(this->Preferred.size() > 1) - { - std::ostringstream e; - e << "Target " << this->Target->GetName() - << " contains multiple languages with the highest linker preference" - << " (" << this->Preference << "):\n"; - for(UNORDERED_SET<std::string>::const_iterator - li = this->Preferred.begin(); li != this->Preferred.end(); ++li) - { - e << " " << *li << "\n"; - } - e << "Set the LINKER_LANGUAGE property for this target."; - cmake* cm = this->Makefile->GetCMakeInstance(); - cm->IssueMessage(cmake::FATAL_ERROR, e.str(), - this->Target->GetBacktrace()); - } - return *this->Preferred.begin(); - } -}; - -//---------------------------------------------------------------------------- -void cmTarget::ComputeLinkClosure(const std::string& config, - LinkClosure& lc) const -{ - // Get languages built in this target. - UNORDERED_SET<std::string> languages; - LinkImplementation const* impl = this->GetLinkImplementation(config); - for(std::vector<std::string>::const_iterator li = impl->Languages.begin(); - li != impl->Languages.end(); ++li) - { - languages.insert(*li); - } - - // Add interface languages from linked targets. - cmTargetCollectLinkLanguages cll(this, config, languages, this); - for(std::vector<cmLinkImplItem>::const_iterator - li = impl->Libraries.begin(); - li != impl->Libraries.end(); ++li) - { - cll.Visit(*li); - } - - // Store the transitive closure of languages. - for(UNORDERED_SET<std::string>::const_iterator li = languages.begin(); - li != languages.end(); ++li) - { - lc.Languages.push_back(*li); - } - - // Choose the language whose linker should be used. - if(this->GetProperty("HAS_CXX")) - { - lc.LinkerLanguage = "CXX"; - } - else if(const char* linkerLang = this->GetProperty("LINKER_LANGUAGE")) - { - lc.LinkerLanguage = linkerLang; - } - else - { - // Find the language with the highest preference value. - cmTargetSelectLinker tsl(this); - - // First select from the languages compiled directly in this target. - for(std::vector<std::string>::const_iterator li = impl->Languages.begin(); - li != impl->Languages.end(); ++li) - { - tsl.Consider(*li); - } - - // Now consider languages that propagate from linked targets. - for(UNORDERED_SET<std::string>::const_iterator sit = languages.begin(); - sit != languages.end(); ++sit) - { - std::string propagates = "CMAKE_"+*sit+"_LINKER_PREFERENCE_PROPAGATES"; - if(this->Makefile->IsOn(propagates)) - { - tsl.Consider(*sit); - } - } - - lc.LinkerLanguage = tsl.Choose(); - } -} - -//---------------------------------------------------------------------------- void cmTarget::ExpandLinkItems(std::string const& prop, std::string const& value, std::string const& config, @@ -3517,133 +3169,6 @@ const char* cmTarget::GetPrefixVariableInternal(bool implib) const } //---------------------------------------------------------------------------- -std::string cmTarget::GetPDBName(const std::string& config) const -{ - std::string prefix; - std::string base; - std::string suffix; - this->GetFullNameInternal(config, false, prefix, base, suffix); - - std::vector<std::string> props; - std::string configUpper = cmSystemTools::UpperCase(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)) - { - base = outName; - break; - } - } - return prefix+base+".pdb"; -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetCompilePDBName(const std::string& 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); - std::string configProp = "COMPILE_PDB_NAME_"; - configProp += configUpper; - const char* config_name = this->GetProperty(configProp); - 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 std::string& 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 std::string& config) const -{ - // soname is supported only for shared libraries and modules, - // and then only when the platform supports an soname flag. - return ((this->GetType() == cmTarget::SHARED_LIBRARY || - this->GetType() == cmTarget::MODULE_LIBRARY) && - !this->GetPropertyAsBool("NO_SONAME") && - this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config))); -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetSOName(const std::string& config) const -{ - if(this->IsImported()) - { - // Lookup the imported soname. - if(cmTarget::ImportInfo const* info = this->GetImportInfo(config)) - { - if(info->NoSOName) - { - // The imported library has no builtin soname so the name - // searched at runtime will be just the filename. - return cmSystemTools::GetFilenameName(info->Location); - } - else - { - // Use the soname given if any. - if(info->SOName.find("@rpath/") == 0) - { - return info->SOName.substr(6); - } - return info->SOName; - } - } - else - { - return ""; - } - } - else - { - // Compute the soname that will be built. - std::string name; - std::string soName; - std::string realName; - std::string impName; - std::string pdbName; - this->GetLibraryNames(name, soName, realName, impName, pdbName, config); - return soName; - } -} - -//---------------------------------------------------------------------------- bool cmTarget::HasMacOSXRpathInstallNameDir(const std::string& config) const { bool install_name_is_rpath = false; @@ -3770,20 +3295,6 @@ bool cmTarget::IsImportedSharedLibWithoutSOName( } //---------------------------------------------------------------------------- -std::string cmTarget::GetFullName(const std::string& config, - bool implib) const -{ - if(this->IsImported()) - { - return this->GetFullNameImported(config, implib); - } - else - { - return this->GetFullNameInternal(config, implib); - } -} - -//---------------------------------------------------------------------------- std::string cmTarget::GetFullNameImported(const std::string& config, bool implib) const { @@ -3792,15 +3303,6 @@ cmTarget::GetFullNameImported(const std::string& config, bool implib) const } //---------------------------------------------------------------------------- -void cmTarget::GetFullNameComponents(std::string& prefix, std::string& base, - std::string& suffix, - const std::string& config, - bool implib) const -{ - this->GetFullNameInternal(config, implib, prefix, base, suffix); -} - -//---------------------------------------------------------------------------- std::string cmTarget::ImportedGetFullPath(const std::string& config, bool implib) const { @@ -3818,237 +3320,6 @@ cmTarget::ImportedGetFullPath(const std::string& config, bool implib) const } //---------------------------------------------------------------------------- -std::string -cmTarget::GetFullNameInternal(const std::string& config, bool implib) const -{ - std::string prefix; - std::string base; - std::string suffix; - this->GetFullNameInternal(config, implib, prefix, base, suffix); - return prefix+base+suffix; -} - -//---------------------------------------------------------------------------- -void cmTarget::GetFullNameInternal(const std::string& config, - bool implib, - std::string& outPrefix, - std::string& outBase, - std::string& outSuffix) const -{ - // Use just the target name for non-main target types. - if(this->GetType() != cmTarget::STATIC_LIBRARY && - this->GetType() != cmTarget::SHARED_LIBRARY && - this->GetType() != cmTarget::MODULE_LIBRARY && - this->GetType() != cmTarget::EXECUTABLE) - { - outPrefix = ""; - outBase = this->GetName(); - outSuffix = ""; - return; - } - - // Return an empty name for the import library if this platform - // does not support import libraries. - if(implib && - !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) - { - outPrefix = ""; - outBase = ""; - outSuffix = ""; - return; - } - - // The implib option is only allowed for shared libraries, module - // libraries, and executables. - if(this->GetType() != cmTarget::SHARED_LIBRARY && - this->GetType() != cmTarget::MODULE_LIBRARY && - this->GetType() != cmTarget::EXECUTABLE) - { - implib = false; - } - - // Compute the full name for main target types. - const char* targetPrefix = (implib - ? this->GetProperty("IMPORT_PREFIX") - : this->GetProperty("PREFIX")); - const char* targetSuffix = (implib - ? this->GetProperty("IMPORT_SUFFIX") - : this->GetProperty("SUFFIX")); - const char* configPostfix = 0; - if(!config.empty()) - { - std::string configProp = cmSystemTools::UpperCase(config); - configProp += "_POSTFIX"; - configPostfix = this->GetProperty(configProp); - // Mac application bundles and frameworks have no postfix. - if(configPostfix && - (this->IsAppBundleOnApple() || this->IsFrameworkOnApple())) - { - configPostfix = 0; - } - } - const char* prefixVar = this->GetPrefixVariableInternal(implib); - const char* suffixVar = this->GetSuffixVariableInternal(implib); - - // Check for language-specific default prefix and suffix. - std::string ll = this->GetLinkerLanguage(config); - if(!ll.empty()) - { - if(!targetSuffix && suffixVar && *suffixVar) - { - std::string langSuff = suffixVar + std::string("_") + ll; - targetSuffix = this->Makefile->GetDefinition(langSuff); - } - if(!targetPrefix && prefixVar && *prefixVar) - { - std::string langPrefix = prefixVar + std::string("_") + ll; - targetPrefix = this->Makefile->GetDefinition(langPrefix); - } - } - - // if there is no prefix on the target use the cmake definition - if(!targetPrefix && prefixVar) - { - targetPrefix = this->Makefile->GetSafeDefinition(prefixVar); - } - // if there is no suffix on the target use the cmake definition - if(!targetSuffix && suffixVar) - { - targetSuffix = this->Makefile->GetSafeDefinition(suffixVar); - } - - // frameworks have directory prefix but no suffix - std::string fw_prefix; - if(this->IsFrameworkOnApple()) - { - fw_prefix = this->GetOutputName(config, false); - fw_prefix += ".framework/"; - targetPrefix = fw_prefix.c_str(); - targetSuffix = 0; - } - - if(this->IsCFBundleOnApple()) - { - fw_prefix = this->GetCFBundleDirectory(config, false); - fw_prefix += "/"; - targetPrefix = fw_prefix.c_str(); - targetSuffix = 0; - } - - // Begin the final name with the prefix. - outPrefix = targetPrefix?targetPrefix:""; - - // Append the target name or property-specified name. - outBase += this->GetOutputName(config, implib); - - // Append the per-configuration postfix. - outBase += configPostfix?configPostfix:""; - - // Name shared libraries with their version number on some platforms. - if(const char* soversion = this->GetProperty("SOVERSION")) - { - if(this->GetType() == cmTarget::SHARED_LIBRARY && !implib && - this->Makefile->IsOn("CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION")) - { - outBase += "-"; - outBase += soversion; - } - } - - // Append the suffix. - outSuffix = targetSuffix?targetSuffix:""; -} - -//---------------------------------------------------------------------------- -void cmTarget::GetLibraryNames(std::string& name, - std::string& soName, - std::string& realName, - std::string& impName, - std::string& pdbName, - const std::string& config) const -{ - // This should not be called for imported targets. - // TODO: Split cmTarget into a class hierarchy to get compile-time - // enforcement of the limited imported target API. - if(this->IsImported()) - { - std::string msg = "GetLibraryNames called on imported target: "; - msg += this->GetName(); - this->Makefile->IssueMessage(cmake::INTERNAL_ERROR, - msg); - return; - } - - assert(this->GetType() != INTERFACE_LIBRARY); - - // Check for library version properties. - const char* version = this->GetProperty("VERSION"); - const char* soversion = this->GetProperty("SOVERSION"); - if(!this->HasSOName(config) || - this->Makefile->IsOn("CMAKE_PLATFORM_NO_VERSIONED_SONAME") || - this->IsFrameworkOnApple()) - { - // Versioning is supported only for shared libraries and modules, - // and then only when the platform supports an soname flag. - version = 0; - soversion = 0; - } - if(version && !soversion) - { - // The soversion must be set if the library version is set. Use - // the library version as the soversion. - soversion = version; - } - if(!version && soversion) - { - // Use the soversion as the library version. - version = soversion; - } - - // Get the components of the library name. - std::string prefix; - std::string base; - std::string suffix; - this->GetFullNameInternal(config, false, prefix, base, suffix); - - // The library name. - name = prefix+base+suffix; - - if(this->IsFrameworkOnApple()) - { - realName = prefix; - realName += "Versions/"; - realName += this->GetFrameworkVersion(); - realName += "/"; - realName += base; - soName = realName; - } - else - { - // The library's soname. - this->ComputeVersionedName(soName, prefix, base, suffix, - name, soversion); - // The library's real name on disk. - this->ComputeVersionedName(realName, prefix, base, suffix, - name, version); - } - - // The import library name. - if(this->GetType() == cmTarget::SHARED_LIBRARY || - this->GetType() == cmTarget::MODULE_LIBRARY) - { - impName = this->GetFullNameInternal(config, true); - } - else - { - impName = ""; - } - - // The program database file name. - pdbName = this->GetPDBName(config); -} - -//---------------------------------------------------------------------------- void cmTarget::ComputeVersionedName(std::string& vName, std::string const& prefix, std::string const& base, @@ -4066,68 +3337,6 @@ void cmTarget::ComputeVersionedName(std::string& vName, } //---------------------------------------------------------------------------- -void cmTarget::GetExecutableNames(std::string& name, - std::string& realName, - std::string& impName, - std::string& pdbName, - const std::string& config) const -{ - // This should not be called for imported targets. - // TODO: Split cmTarget into a class hierarchy to get compile-time - // enforcement of the limited imported target API. - if(this->IsImported()) - { - std::string msg = - "GetExecutableNames called on imported target: "; - msg += this->GetName(); - this->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR, msg); - } - - // This versioning is supported only for executables and then only - // when the platform supports symbolic links. -#if defined(_WIN32) && !defined(__CYGWIN__) - const char* version = 0; -#else - // Check for executable version properties. - const char* version = this->GetProperty("VERSION"); - if(this->GetType() != cmTarget::EXECUTABLE || this->Makefile->IsOn("XCODE")) - { - version = 0; - } -#endif - - // Get the components of the executable name. - std::string prefix; - std::string base; - std::string suffix; - this->GetFullNameInternal(config, false, prefix, base, suffix); - - // The executable name. - name = prefix+base+suffix; - - // The executable's real name on disk. -#if defined(__CYGWIN__) - realName = prefix+base; -#else - realName = name; -#endif - if(version) - { - realName += "-"; - realName += version; - } -#if defined(__CYGWIN__) - realName += suffix; -#endif - - // The import library name. - impName = this->GetFullNameInternal(config, true); - - // The program database file name. - pdbName = this->GetPDBName(config); -} - -//---------------------------------------------------------------------------- bool cmTarget::HasImplibGNUtoMS() const { return this->HasImportLibrary() && this->GetPropertyAsBool("GNUtoMS"); @@ -4189,137 +3398,6 @@ bool cmTarget::HaveInstallTreeRPATH() const } //---------------------------------------------------------------------------- -bool cmTarget::NeedRelinkBeforeInstall(const std::string& config) const -{ - // Only executables and shared libraries can have an rpath and may - // need relinking. - if(this->TargetTypeValue != cmTarget::EXECUTABLE && - this->TargetTypeValue != cmTarget::SHARED_LIBRARY && - this->TargetTypeValue != cmTarget::MODULE_LIBRARY) - { - return false; - } - - // If there is no install location this target will not be installed - // and therefore does not need relinking. - if(!this->GetHaveInstallRule()) - { - return false; - } - - // If skipping all rpaths completely then no relinking is needed. - if(this->Makefile->IsOn("CMAKE_SKIP_RPATH")) - { - return false; - } - - // If building with the install-tree rpath no relinking is needed. - if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) - { - return false; - } - - // If chrpath is going to be used no relinking is needed. - if(this->IsChrpathUsed(config)) - { - return false; - } - - // Check for rpath support on this platform. - std::string ll = this->GetLinkerLanguage(config); - if(!ll.empty()) - { - std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; - flagVar += ll; - flagVar += "_FLAG"; - if(!this->Makefile->IsSet(flagVar)) - { - // There is no rpath support on this platform so nothing needs - // relinking. - return false; - } - } - else - { - // No linker language is known. This error will be reported by - // other code. - return false; - } - - // If either a build or install tree rpath is set then the rpath - // will likely change between the build tree and install tree and - // this target must be relinked. - return this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH(); -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetInstallNameDirForBuildTree( - const std::string& config) const -{ - // If building directly for installation then the build tree install_name - // is the same as the install tree. - if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) - { - return GetInstallNameDirForInstallTree(); - } - - // Use the build tree directory for the target. - if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME") && - !this->Makefile->IsOn("CMAKE_SKIP_RPATH") && - !this->GetPropertyAsBool("SKIP_BUILD_RPATH")) - { - std::string dir; - bool macosx_rpath = this->MacOSXRpathInstallNameDirDefault(); - if(macosx_rpath) - { - dir = "@rpath"; - } - else - { - dir = this->GetDirectory(config); - } - dir += "/"; - return dir; - } - else - { - return ""; - } -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetInstallNameDirForInstallTree() const -{ - if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) - { - std::string dir; - const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR"); - - if(!this->Makefile->IsOn("CMAKE_SKIP_RPATH") && - !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH")) - { - if(install_name_dir && *install_name_dir) - { - dir = install_name_dir; - dir += "/"; - } - } - if(!install_name_dir) - { - if(this->MacOSXRpathInstallNameDirDefault()) - { - dir = "@rpath/"; - } - } - return dir; - } - else - { - return ""; - } -} - -//---------------------------------------------------------------------------- const char* cmTarget::GetOutputTargetType(bool implib) const { switch(this->GetType()) @@ -4527,54 +3605,6 @@ bool cmTarget::UsesDefaultOutputDir(const std::string& config, } //---------------------------------------------------------------------------- -std::string cmTarget::GetOutputName(const std::string& config, - bool implib) const -{ - std::vector<std::string> props; - std::string type = this->GetOutputTargetType(implib); - std::string configUpper = cmSystemTools::UpperCase(config); - if(!type.empty() && !configUpper.empty()) - { - // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME_<CONFIG> - props.push_back(type + "_OUTPUT_NAME_" + configUpper); - } - if(!type.empty()) - { - // <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME - props.push_back(type + "_OUTPUT_NAME"); - } - if(!configUpper.empty()) - { - // OUTPUT_NAME_<CONFIG> - props.push_back("OUTPUT_NAME_" + configUpper); - // <CONFIG>_OUTPUT_NAME - props.push_back(configUpper + "_OUTPUT_NAME"); - } - // OUTPUT_NAME - props.push_back("OUTPUT_NAME"); - - std::string outName; - for(std::vector<std::string>::const_iterator i = props.begin(); - i != props.end(); ++i) - { - if (const char* outNameProp = this->GetProperty(*i)) - { - outName = outNameProp; - break; - } - } - - if (outName.empty()) - { - outName = this->GetName(); - } - - cmGeneratorExpression ge; - cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(outName); - return cge->Evaluate(this->Makefile, config); -} - -//---------------------------------------------------------------------------- std::string cmTarget::GetFrameworkVersion() const { assert(this->GetType() != INTERFACE_LIBRARY); @@ -4627,500 +3657,6 @@ bool cmTarget::IsNullImpliedByLinkLibraries(const std::string &p) const } //---------------------------------------------------------------------------- -template<typename PropertyType> -PropertyType getTypedProperty(cmTarget const* tgt, const std::string& prop); - -//---------------------------------------------------------------------------- -template<> -bool getTypedProperty<bool>(cmTarget const* tgt, const std::string& prop) -{ - return tgt->GetPropertyAsBool(prop); -} - -//---------------------------------------------------------------------------- -template<> -const char *getTypedProperty<const char *>(cmTarget const* tgt, - const std::string& prop) -{ - return tgt->GetProperty(prop); -} - -enum CompatibleType -{ - BoolType, - StringType, - NumberMinType, - NumberMaxType -}; - -//---------------------------------------------------------------------------- -template<typename PropertyType> -std::pair<bool, PropertyType> consistentProperty(PropertyType lhs, - PropertyType rhs, - CompatibleType t); - -//---------------------------------------------------------------------------- -template<> -std::pair<bool, bool> consistentProperty(bool lhs, bool rhs, CompatibleType) -{ - return std::make_pair(lhs == rhs, lhs); -} - -//---------------------------------------------------------------------------- -std::pair<bool, const char*> consistentStringProperty(const char *lhs, - const char *rhs) -{ - const bool b = strcmp(lhs, rhs) == 0; - return std::make_pair(b, b ? lhs : 0); -} - -//---------------------------------------------------------------------------- -std::pair<bool, const char*> consistentNumberProperty(const char *lhs, - const char *rhs, - CompatibleType t) -{ - char *pEnd; - - const char* const null_ptr = 0; - - long lnum = strtol(lhs, &pEnd, 0); - if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE) - { - return std::pair<bool, const char*>(false, null_ptr); - } - - long rnum = strtol(rhs, &pEnd, 0); - if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE) - { - return std::pair<bool, const char*>(false, null_ptr); - } - - if (t == NumberMaxType) - { - return std::make_pair(true, std::max(lnum, rnum) == lnum ? lhs : rhs); - } - else - { - return std::make_pair(true, std::min(lnum, rnum) == lnum ? lhs : rhs); - } -} - -//---------------------------------------------------------------------------- -template<> -std::pair<bool, const char*> consistentProperty(const char *lhs, - const char *rhs, - CompatibleType t) -{ - if (!lhs && !rhs) - { - return std::make_pair(true, lhs); - } - if (!lhs) - { - return std::make_pair(true, rhs); - } - if (!rhs) - { - return std::make_pair(true, lhs); - } - - const char* const null_ptr = 0; - - switch(t) - { - case BoolType: - assert(0 && "consistentProperty for strings called with BoolType"); - return std::pair<bool, const char*>(false, null_ptr); - case StringType: - return consistentStringProperty(lhs, rhs); - case NumberMinType: - case NumberMaxType: - return consistentNumberProperty(lhs, rhs, t); - } - assert(0 && "Unreachable!"); - return std::pair<bool, const char*>(false, null_ptr); -} - -template<typename PropertyType> -PropertyType impliedValue(PropertyType); -template<> -bool impliedValue<bool>(bool) -{ - return false; -} -template<> -const char* impliedValue<const char*>(const char*) -{ - return ""; -} - - -template<typename PropertyType> -std::string valueAsString(PropertyType); -template<> -std::string valueAsString<bool>(bool value) -{ - return value ? "TRUE" : "FALSE"; -} -template<> -std::string valueAsString<const char*>(const char* value) -{ - return value ? value : "(unset)"; -} - -//---------------------------------------------------------------------------- -void -cmTarget::ReportPropertyOrigin(const std::string &p, - const std::string &result, - const std::string &report, - const std::string &compatibilityType) const -{ - std::vector<std::string> debugProperties; - const char *debugProp = - this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); - if (debugProp) - { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); - } - - bool debugOrigin = !this->DebugCompatiblePropertiesDone[p] - && std::find(debugProperties.begin(), - debugProperties.end(), - p) - != debugProperties.end(); - - if (this->Makefile->IsConfigured()) - { - this->DebugCompatiblePropertiesDone[p] = true; - } - if (!debugOrigin) - { - return; - } - - std::string areport = compatibilityType; - areport += std::string(" of property \"") + p + "\" for target \""; - areport += std::string(this->GetName()); - areport += "\" (result: \""; - areport += result; - areport += "\"):\n" + report; - - this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG, areport); -} - -//---------------------------------------------------------------------------- -std::string compatibilityType(CompatibleType t) -{ - switch(t) - { - case BoolType: - return "Boolean compatibility"; - case StringType: - return "String compatibility"; - case NumberMaxType: - return "Numeric maximum compatibility"; - case NumberMinType: - return "Numeric minimum compatibility"; - } - assert(0 && "Unreachable!"); - return ""; -} - -//---------------------------------------------------------------------------- -std::string compatibilityAgree(CompatibleType t, bool dominant) -{ - switch(t) - { - case BoolType: - case StringType: - return dominant ? "(Disagree)\n" : "(Agree)\n"; - case NumberMaxType: - case NumberMinType: - return dominant ? "(Dominant)\n" : "(Ignored)\n"; - } - assert(0 && "Unreachable!"); - return ""; -} - -//---------------------------------------------------------------------------- -template<typename PropertyType> -PropertyType checkInterfacePropertyCompatibility(cmTarget const* tgt, - const std::string &p, - const std::string& config, - const char *defaultValue, - CompatibleType t, - PropertyType *) -{ - PropertyType propContent = getTypedProperty<PropertyType>(tgt, p); - const bool explicitlySet = tgt->GetProperties() - .find(p) - != tgt->GetProperties().end(); - const bool impliedByUse = - tgt->IsNullImpliedByLinkLibraries(p); - assert((impliedByUse ^ explicitlySet) - || (!impliedByUse && !explicitlySet)); - - std::vector<cmTarget const*> const& deps = - tgt->GetLinkImplementationClosure(config); - - if(deps.empty()) - { - return propContent; - } - bool propInitialized = explicitlySet; - - std::string report = " * Target \""; - report += tgt->GetName(); - if (explicitlySet) - { - report += "\" has property content \""; - report += valueAsString<PropertyType>(propContent); - report += "\"\n"; - } - else if (impliedByUse) - { - report += "\" property is implied by use.\n"; - } - else - { - report += "\" property not set.\n"; - } - - std::string interfaceProperty = "INTERFACE_" + p; - for(std::vector<cmTarget const*>::const_iterator li = - deps.begin(); - li != deps.end(); ++li) - { - // An error should be reported if one dependency - // has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other - // has INTERFACE_POSITION_INDEPENDENT_CODE OFF, or if the - // target itself has a POSITION_INDEPENDENT_CODE which disagrees - // with a dependency. - - cmTarget const* theTarget = *li; - - const bool ifaceIsSet = theTarget->GetProperties() - .find(interfaceProperty) - != theTarget->GetProperties().end(); - PropertyType ifacePropContent = - getTypedProperty<PropertyType>(theTarget, - interfaceProperty); - - std::string reportEntry; - if (ifaceIsSet) - { - reportEntry += " * Target \""; - reportEntry += theTarget->GetName(); - reportEntry += "\" property value \""; - reportEntry += valueAsString<PropertyType>(ifacePropContent); - reportEntry += "\" "; - } - - if (explicitlySet) - { - if (ifaceIsSet) - { - std::pair<bool, PropertyType> consistent = - consistentProperty(propContent, - ifacePropContent, t); - report += reportEntry; - report += compatibilityAgree(t, propContent != consistent.second); - if (!consistent.first) - { - std::ostringstream e; - e << "Property " << p << " on target \"" - << tgt->GetName() << "\" does\nnot match the " - "INTERFACE_" << p << " property requirement\nof " - "dependency \"" << theTarget->GetName() << "\".\n"; - cmSystemTools::Error(e.str().c_str()); - break; - } - else - { - propContent = consistent.second; - continue; - } - } - else - { - // Explicitly set on target and not set in iface. Can't disagree. - continue; - } - } - else if (impliedByUse) - { - propContent = impliedValue<PropertyType>(propContent); - - if (ifaceIsSet) - { - std::pair<bool, PropertyType> consistent = - consistentProperty(propContent, - ifacePropContent, t); - report += reportEntry; - report += compatibilityAgree(t, propContent != consistent.second); - if (!consistent.first) - { - std::ostringstream e; - e << "Property " << p << " on target \"" - << tgt->GetName() << "\" is\nimplied to be " << defaultValue - << " because it was used to determine the link libraries\n" - "already. The INTERFACE_" << p << " property on\ndependency \"" - << theTarget->GetName() << "\" is in conflict.\n"; - cmSystemTools::Error(e.str().c_str()); - break; - } - else - { - propContent = consistent.second; - continue; - } - } - else - { - // Implicitly set on target and not set in iface. Can't disagree. - continue; - } - } - else - { - if (ifaceIsSet) - { - if (propInitialized) - { - std::pair<bool, PropertyType> consistent = - consistentProperty(propContent, - ifacePropContent, t); - report += reportEntry; - report += compatibilityAgree(t, propContent != consistent.second); - if (!consistent.first) - { - std::ostringstream e; - e << "The INTERFACE_" << p << " property of \"" - << theTarget->GetName() << "\" does\nnot agree with the value " - "of " << p << " already determined\nfor \"" - << tgt->GetName() << "\".\n"; - cmSystemTools::Error(e.str().c_str()); - break; - } - else - { - propContent = consistent.second; - continue; - } - } - else - { - report += reportEntry + "(Interface set)\n"; - propContent = ifacePropContent; - propInitialized = true; - } - } - else - { - // Not set. Nothing to agree on. - continue; - } - } - } - - tgt->ReportPropertyOrigin(p, valueAsString<PropertyType>(propContent), - report, compatibilityType(t)); - return propContent; -} - -//---------------------------------------------------------------------------- -bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, - const std::string& config) const -{ - return checkInterfacePropertyCompatibility<bool>(this, p, config, "FALSE", - BoolType, 0); -} - -//---------------------------------------------------------------------------- -const char * cmTarget::GetLinkInterfaceDependentStringProperty( - const std::string &p, - const std::string& config) const -{ - return checkInterfacePropertyCompatibility<const char *>(this, - p, - config, - "empty", - StringType, 0); -} - -//---------------------------------------------------------------------------- -const char * cmTarget::GetLinkInterfaceDependentNumberMinProperty( - const std::string &p, - const std::string& config) const -{ - return checkInterfacePropertyCompatibility<const char *>(this, - p, - config, - "empty", - NumberMinType, 0); -} - -//---------------------------------------------------------------------------- -const char * cmTarget::GetLinkInterfaceDependentNumberMaxProperty( - const std::string &p, - const std::string& config) const -{ - return checkInterfacePropertyCompatibility<const char *>(this, - p, - config, - "empty", - NumberMaxType, 0); -} - -//---------------------------------------------------------------------------- -bool cmTarget::IsLinkInterfaceDependentBoolProperty(const std::string &p, - const std::string& config) const -{ - if (this->TargetTypeValue == OBJECT_LIBRARY - || this->TargetTypeValue == INTERFACE_LIBRARY) - { - return false; - } - return this->GetCompatibleInterfaces(config).PropsBool.count(p) > 0; -} - -//---------------------------------------------------------------------------- -bool cmTarget::IsLinkInterfaceDependentStringProperty(const std::string &p, - const std::string& config) const -{ - if (this->TargetTypeValue == OBJECT_LIBRARY - || this->TargetTypeValue == INTERFACE_LIBRARY) - { - return false; - } - return this->GetCompatibleInterfaces(config).PropsString.count(p) > 0; -} - -//---------------------------------------------------------------------------- -bool cmTarget::IsLinkInterfaceDependentNumberMinProperty(const std::string &p, - const std::string& config) const -{ - if (this->TargetTypeValue == OBJECT_LIBRARY - || this->TargetTypeValue == INTERFACE_LIBRARY) - { - return false; - } - return this->GetCompatibleInterfaces(config).PropsNumberMin.count(p) > 0; -} - -//---------------------------------------------------------------------------- -bool cmTarget::IsLinkInterfaceDependentNumberMaxProperty(const std::string &p, - const std::string& config) const -{ - if (this->TargetTypeValue == OBJECT_LIBRARY - || this->TargetTypeValue == INTERFACE_LIBRARY) - { - return false; - } - return this->GetCompatibleInterfaces(config).PropsNumberMax.count(p) > 0; -} - -//---------------------------------------------------------------------------- void cmTarget::GetObjectLibrariesCMP0026(std::vector<cmTarget*>& objlibs) const { @@ -5206,73 +3742,6 @@ void cmTarget::GetLanguages(std::set<std::string>& languages, } //---------------------------------------------------------------------------- -bool cmTarget::IsChrpathUsed(const std::string& config) const -{ - // Only certain target types have an rpath. - if(!(this->GetType() == cmTarget::SHARED_LIBRARY || - this->GetType() == cmTarget::MODULE_LIBRARY || - this->GetType() == cmTarget::EXECUTABLE)) - { - return false; - } - - // If the target will not be installed we do not need to change its - // rpath. - if(!this->GetHaveInstallRule()) - { - return false; - } - - // Skip chrpath if skipping rpath altogether. - if(this->Makefile->IsOn("CMAKE_SKIP_RPATH")) - { - return false; - } - - // Skip chrpath if it does not need to be changed at install time. - if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) - { - return false; - } - - // Allow the user to disable builtin chrpath explicitly. - if(this->Makefile->IsOn("CMAKE_NO_BUILTIN_CHRPATH")) - { - return false; - } - - if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) - { - return true; - } - -#if defined(CMAKE_USE_ELF_PARSER) - // Enable if the rpath flag uses a separator and the target uses ELF - // binaries. - std::string ll = this->GetLinkerLanguage(config); - if(!ll.empty()) - { - std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; - sepVar += ll; - sepVar += "_FLAG_SEP"; - const char* sep = this->Makefile->GetDefinition(sepVar); - if(sep && *sep) - { - // TODO: Add ELF check to ABI detection and get rid of - // CMAKE_EXECUTABLE_FORMAT. - if(const char* fmt = - this->Makefile->GetDefinition("CMAKE_EXECUTABLE_FORMAT")) - { - return strcmp(fmt, "ELF") == 0; - } - } - } -#endif - static_cast<void>(config); - return false; -} - -//---------------------------------------------------------------------------- cmTarget::ImportInfo const* cmTarget::GetImportInfo(const std::string& config) const { @@ -5760,86 +4229,6 @@ cmTarget::GetImportLinkInterface(const std::string& config, } //---------------------------------------------------------------------------- -void processILibs(const std::string& config, - cmTarget const* headTarget, - cmLinkItem const& item, - std::vector<cmTarget const*>& tgts, - std::set<cmTarget const*>& emitted) -{ - if (item.Target && emitted.insert(item.Target).second) - { - tgts.push_back(item.Target); - if(cmTarget::LinkInterfaceLibraries const* iface = - item.Target->GetLinkInterfaceLibraries(config, headTarget, true)) - { - for(std::vector<cmLinkItem>::const_iterator - it = iface->Libraries.begin(); - it != iface->Libraries.end(); ++it) - { - processILibs(config, headTarget, *it, tgts, emitted); - } - } - } -} - -//---------------------------------------------------------------------------- -std::vector<cmTarget const*> const& -cmTarget::GetLinkImplementationClosure(const std::string& config) const -{ - cmTargetInternals::LinkImplClosure& tgts = - this->Internal->LinkImplClosureMap[config]; - if(!tgts.Done) - { - tgts.Done = true; - std::set<cmTarget const*> emitted; - - cmTarget::LinkImplementationLibraries const* impl - = this->GetLinkImplementationLibraries(config); - - for(std::vector<cmLinkImplItem>::const_iterator - it = impl->Libraries.begin(); - it != impl->Libraries.end(); ++it) - { - processILibs(config, this, *it, tgts , emitted); - } - } - return tgts; -} - -//---------------------------------------------------------------------------- -cmTarget::CompatibleInterfaces const& -cmTarget::GetCompatibleInterfaces(std::string const& config) const -{ - cmTargetInternals::CompatibleInterfaces& compat = - this->Internal->CompatibleInterfacesMap[config]; - if(!compat.Done) - { - compat.Done = true; - compat.PropsBool.insert("POSITION_INDEPENDENT_CODE"); - compat.PropsString.insert("AUTOUIC_OPTIONS"); - std::vector<cmTarget const*> const& deps = - this->GetLinkImplementationClosure(config); - for(std::vector<cmTarget const*>::const_iterator li = deps.begin(); - li != deps.end(); ++li) - { -#define CM_READ_COMPATIBLE_INTERFACE(X, x) \ - if(const char* prop = (*li)->GetProperty("COMPATIBLE_INTERFACE_" #X)) \ - { \ - std::vector<std::string> props; \ - cmSystemTools::ExpandListArgument(prop, props); \ - compat.Props##x.insert(props.begin(), props.end()); \ - } - CM_READ_COMPATIBLE_INTERFACE(BOOL, Bool) - CM_READ_COMPATIBLE_INTERFACE(STRING, String) - CM_READ_COMPATIBLE_INTERFACE(NUMBER_MIN, NumberMin) - CM_READ_COMPATIBLE_INTERFACE(NUMBER_MAX, NumberMax) -#undef CM_READ_COMPATIBLE_INTERFACE - } - } - return compat; -} - -//---------------------------------------------------------------------------- void cmTargetInternals::ComputeLinkInterfaceLibraries( cmTarget const* thisTarget, @@ -6396,382 +4785,6 @@ std::string cmTarget::CheckCMP0004(std::string const& item) const return lib; } -template<typename PropertyType> -PropertyType getLinkInterfaceDependentProperty(cmTarget const* tgt, - const std::string& prop, - const std::string& config, - CompatibleType, - PropertyType *); - -template<> -bool getLinkInterfaceDependentProperty(cmTarget const* tgt, - const std::string& prop, - const std::string& config, - CompatibleType, bool *) -{ - return tgt->GetLinkInterfaceDependentBoolProperty(prop, config); -} - -template<> -const char * getLinkInterfaceDependentProperty(cmTarget const* tgt, - const std::string& prop, - const std::string& config, - CompatibleType t, - const char **) -{ - switch(t) - { - case BoolType: - assert(0 && "String compatibility check function called for boolean"); - return 0; - case StringType: - return tgt->GetLinkInterfaceDependentStringProperty(prop, config); - case NumberMinType: - return tgt->GetLinkInterfaceDependentNumberMinProperty(prop, config); - case NumberMaxType: - return tgt->GetLinkInterfaceDependentNumberMaxProperty(prop, config); - } - assert(0 && "Unreachable!"); - return 0; -} - -//---------------------------------------------------------------------------- -template<typename PropertyType> -void checkPropertyConsistency(cmTarget const* depender, - cmTarget const* dependee, - const std::string& propName, - std::set<std::string> &emitted, - const std::string& config, - CompatibleType t, - PropertyType *) -{ - const char *prop = dependee->GetProperty(propName); - if (!prop) - { - return; - } - - std::vector<std::string> props; - cmSystemTools::ExpandListArgument(prop, props); - std::string pdir = - dependee->GetMakefile()->GetRequiredDefinition("CMAKE_ROOT"); - pdir += "/Help/prop_tgt/"; - - for(std::vector<std::string>::iterator pi = props.begin(); - pi != props.end(); ++pi) - { - std::string pname = cmSystemTools::HelpFileName(*pi); - std::string pfile = pdir + pname + ".rst"; - if(cmSystemTools::FileExists(pfile.c_str(), true)) - { - std::ostringstream e; - e << "Target \"" << dependee->GetName() << "\" has property \"" - << *pi << "\" listed in its " << propName << " property. " - "This is not allowed. Only user-defined properties may appear " - "listed in the " << propName << " property."; - depender->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str()); - return; - } - if(emitted.insert(*pi).second) - { - getLinkInterfaceDependentProperty<PropertyType>(depender, *pi, config, - t, 0); - if (cmSystemTools::GetErrorOccuredFlag()) - { - return; - } - } - } -} - -static std::string intersect(const std::set<std::string> &s1, - const std::set<std::string> &s2) -{ - std::set<std::string> intersect; - std::set_intersection(s1.begin(),s1.end(), - s2.begin(),s2.end(), - std::inserter(intersect,intersect.begin())); - if (!intersect.empty()) - { - return *intersect.begin(); - } - return ""; -} -static std::string intersect(const std::set<std::string> &s1, - const std::set<std::string> &s2, - const std::set<std::string> &s3) -{ - std::string result; - result = intersect(s1, s2); - if (!result.empty()) - return result; - result = intersect(s1, s3); - if (!result.empty()) - return result; - return intersect(s2, s3); -} -static std::string intersect(const std::set<std::string> &s1, - const std::set<std::string> &s2, - const std::set<std::string> &s3, - const std::set<std::string> &s4) -{ - std::string result; - result = intersect(s1, s2); - if (!result.empty()) - return result; - result = intersect(s1, s3); - if (!result.empty()) - return result; - result = intersect(s1, s4); - if (!result.empty()) - return result; - return intersect(s2, s3, s4); -} - -//---------------------------------------------------------------------------- -void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, - const std::string& config) const -{ - const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); - - std::set<std::string> emittedBools; - static std::string strBool = "COMPATIBLE_INTERFACE_BOOL"; - std::set<std::string> emittedStrings; - static std::string strString = "COMPATIBLE_INTERFACE_STRING"; - std::set<std::string> emittedMinNumbers; - static std::string strNumMin = "COMPATIBLE_INTERFACE_NUMBER_MIN"; - std::set<std::string> emittedMaxNumbers; - static std::string strNumMax = "COMPATIBLE_INTERFACE_NUMBER_MAX"; - - for(cmComputeLinkInformation::ItemVector::const_iterator li = - deps.begin(); - li != deps.end(); ++li) - { - if (!li->Target) - { - continue; - } - - checkPropertyConsistency<bool>(this, li->Target, - strBool, - emittedBools, config, BoolType, 0); - if (cmSystemTools::GetErrorOccuredFlag()) - { - return; - } - checkPropertyConsistency<const char *>(this, li->Target, - strString, - emittedStrings, config, - StringType, 0); - if (cmSystemTools::GetErrorOccuredFlag()) - { - return; - } - checkPropertyConsistency<const char *>(this, li->Target, - strNumMin, - emittedMinNumbers, config, - NumberMinType, 0); - if (cmSystemTools::GetErrorOccuredFlag()) - { - return; - } - checkPropertyConsistency<const char *>(this, li->Target, - strNumMax, - emittedMaxNumbers, config, - NumberMaxType, 0); - if (cmSystemTools::GetErrorOccuredFlag()) - { - return; - } - } - - std::string prop = intersect(emittedBools, - emittedStrings, - emittedMinNumbers, - emittedMaxNumbers); - - if (!prop.empty()) - { - // Use a sorted std::vector to keep the error message sorted. - std::vector<std::string> props; - std::set<std::string>::const_iterator i = emittedBools.find(prop); - if (i != emittedBools.end()) - { - props.push_back(strBool); - } - i = emittedStrings.find(prop); - if (i != emittedStrings.end()) - { - props.push_back(strString); - } - i = emittedMinNumbers.find(prop); - if (i != emittedMinNumbers.end()) - { - props.push_back(strNumMin); - } - i = emittedMaxNumbers.find(prop); - if (i != emittedMaxNumbers.end()) - { - props.push_back(strNumMax); - } - std::sort(props.begin(), props.end()); - - std::string propsString = cmJoin(cmMakeRange(props).retreat(1), ", "); - propsString += " and the " + props.back(); - - std::ostringstream e; - e << "Property \"" << prop << "\" appears in both the " - << propsString << - " property in the dependencies of target \"" << this->GetName() << - "\". This is not allowed. A property may only require compatibility " - "in a boolean interpretation, a numeric minimum, a numeric maximum or a " - "string interpretation, but not a mixture."; - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); - } -} - -//---------------------------------------------------------------------------- -cmComputeLinkInformation* -cmTarget::GetLinkInformation(const std::string& config) const -{ - // Lookup any existing information for this configuration. - std::string key(cmSystemTools::UpperCase(config)); - cmTargetLinkInformationMap::iterator - i = this->LinkInformation.find(key); - if(i == this->LinkInformation.end()) - { - // Compute information for this configuration. - cmComputeLinkInformation* info = - new cmComputeLinkInformation(this, config); - if(!info || !info->Compute()) - { - delete info; - info = 0; - } - - // Store the information for this configuration. - cmTargetLinkInformationMap::value_type entry(key, info); - i = this->LinkInformation.insert(entry).first; - - if (info) - { - this->CheckPropertyCompatibility(info, config); - } - } - return i->second; -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetFrameworkDirectory(const std::string& config, - bool rootDir) const -{ - std::string fpath; - fpath += this->GetOutputName(config, false); - fpath += ".framework"; - if(!rootDir) - { - fpath += "/Versions/"; - fpath += this->GetFrameworkVersion(); - } - return fpath; -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetCFBundleDirectory(const std::string& config, - bool contentOnly) const -{ - std::string fpath; - fpath += this->GetOutputName(config, false); - fpath += "."; - const char *ext = this->GetProperty("BUNDLE_EXTENSION"); - if (!ext) - { - if (this->IsXCTestOnApple()) - { - ext = "xctest"; - } - else - { - ext = "bundle"; - } - } - fpath += ext; - fpath += "/Contents"; - if(!contentOnly) - fpath += "/MacOS"; - return fpath; -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetAppBundleDirectory(const std::string& config, - bool contentOnly) const -{ - std::string fpath = this->GetFullName(config, false); - fpath += ".app/Contents"; - if(!contentOnly) - fpath += "/MacOS"; - return fpath; -} - -//---------------------------------------------------------------------------- -std::string cmTarget::BuildMacContentDirectory(const std::string& base, - const std::string& config, - bool contentOnly) const -{ - std::string fpath = base; - if(this->IsAppBundleOnApple()) - { - fpath += this->GetAppBundleDirectory(config, contentOnly); - } - if(this->IsFrameworkOnApple()) - { - fpath += this->GetFrameworkDirectory(config, contentOnly); - } - if(this->IsCFBundleOnApple()) - { - fpath += this->GetCFBundleDirectory(config, contentOnly); - } - return fpath; -} - -//---------------------------------------------------------------------------- -std::string cmTarget::GetMacContentDirectory(const std::string& config, - bool implib) const -{ - // Start with the output directory for the target. - std::string fpath = this->GetDirectory(config, implib); - fpath += "/"; - bool contentOnly = true; - if(this->IsFrameworkOnApple()) - { - // additional files with a framework go into the version specific - // directory - contentOnly = false; - } - fpath = this->BuildMacContentDirectory(fpath, config, contentOnly); - return fpath; -} - -//---------------------------------------------------------------------------- -cmTargetLinkInformationMap -::cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r): derived() -{ - // Ideally cmTarget instances should never be copied. However until - // we can make a sweep to remove that, this copy constructor avoids - // allowing the resources (LinkInformation) from getting copied. In - // the worst case this will lead to extra cmComputeLinkInformation - // instances. We also enforce in debug mode that the map be emptied - // when copied. - static_cast<void>(r); - assert(r.empty()); -} - -//---------------------------------------------------------------------------- -cmTargetLinkInformationMap::~cmTargetLinkInformationMap() -{ - cmDeleteAll(*this); -} - //---------------------------------------------------------------------------- cmTargetInternalPointer::cmTargetInternalPointer() { diff --git a/Source/cmTarget.h b/Source/cmTarget.h index f567d50..e3fbdfd 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -78,15 +78,6 @@ public: bool FromGenex; }; -struct cmTargetLinkInformationMap: - public std::map<std::string, cmComputeLinkInformation*> -{ - typedef std::map<std::string, cmComputeLinkInformation*> derived; - cmTargetLinkInformationMap() {} - cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r); - ~cmTargetLinkInformationMap(); -}; - class cmTargetInternals; class cmTargetInternalPointer { @@ -302,19 +293,6 @@ public: cmTarget const* headTarget, bool usage_requirements_only) const; - std::vector<cmTarget const*> const& - GetLinkImplementationClosure(const std::string& config) const; - - struct CompatibleInterfaces - { - std::set<std::string> PropsBool; - std::set<std::string> PropsString; - std::set<std::string> PropsNumberMax; - std::set<std::string> PropsNumberMin; - }; - CompatibleInterfaces const& - GetCompatibleInterfaces(std::string const& config) const; - /** The link implementation specifies the direct library dependencies needed by the object files of the target. */ struct LinkImplementationLibraries @@ -337,18 +315,6 @@ public: LinkImplementationLibraries const* GetLinkImplementationLibraries(const std::string& config) const; - /** Link information from the transitive closure of the link - implementation and the interfaces of its dependencies. */ - struct LinkClosure - { - // The preferred linker language. - std::string LinkerLanguage; - - // Languages whose runtime libraries must be linked. - std::vector<std::string> Languages; - }; - LinkClosure const* GetLinkClosure(const std::string& config) const; - cmTarget const* FindTargetToLink(std::string const& name) const; /** Strip off leading and trailing whitespace from an item named in @@ -368,12 +334,6 @@ public: pdb output directory is given. */ std::string GetPDBDirectory(const std::string& 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 std::string& config = "") const; - const char* ImportedGetLocation(const std::string& config) const; /** Get the target major and minor version numbers interpreted from @@ -387,33 +347,6 @@ public: void GetTargetVersion(bool soversion, int& major, int& minor, int& patch) const; - ///! Return the preferred linker language for this target - std::string GetLinkerLanguage(const std::string& config = "") const; - - /** Get the full name of the target according to the settings in its - makefile. */ - std::string GetFullName(const std::string& config="", - bool implib = false) const; - void GetFullNameComponents(std::string& prefix, - std::string& base, std::string& suffix, - const std::string& config="", - bool implib = false) const; - - /** Get the name of the pdb file for the target. */ - std::string GetPDBName(const std::string& config) const; - - /** Get the name of the compiler pdb file for the target. */ - std::string GetCompilePDBName(const std::string& config="") const; - - /** Get the path for the MSVC /Fd option for this target. */ - std::string GetCompilePDBPath(const std::string& config="") const; - - /** Whether this library has soname enabled and platform supports it. */ - bool HasSOName(const std::string& config) const; - - /** Get the soname of the target. Allowed only for a shared library. */ - std::string GetSOName(const std::string& config) const; - /** Whether this library has \@rpath and platform supports it. */ bool HasMacOSXRpathInstallNameDir(const std::string& config) const; @@ -424,21 +357,6 @@ public: no soname at all. */ bool IsImportedSharedLibWithoutSOName(const std::string& config) const; - /** Get the names of the library needed to generate a build rule - that takes into account shared library version numbers. This - should be called only on a library target. */ - void GetLibraryNames(std::string& name, std::string& soName, - std::string& realName, std::string& impName, - std::string& pdbName, const std::string& config) const; - - /** Get the names of the executable needed to generate a build rule - that takes into account executable version numbers. This should - be called only on an executable target. */ - void GetExecutableNames(std::string& name, std::string& realName, - std::string& impName, - std::string& pdbName, - const std::string& config) const; - /** Does this target have a GNU implib to convert to MS format? */ bool HasImplibGNUtoMS() const; @@ -447,29 +365,9 @@ public: bool GetImplibGNUtoMS(std::string const& gnuName, std::string& out, const char* newExt = 0) const; - /** - * Compute whether this target must be relinked before installing. - */ - bool NeedRelinkBeforeInstall(const std::string& config) const; - bool HaveBuildTreeRPATH(const std::string& config) const; bool HaveInstallTreeRPATH() const; - /** Return true if builtin chrpath will work for this target */ - bool IsChrpathUsed(const std::string& config) const; - - /** Return the install name directory for the target in the - * build tree. For example: "\@rpath/", "\@loader_path/", - * or "/full/path/to/library". */ - std::string GetInstallNameDirForBuildTree(const std::string& config) const; - - /** Return the install name directory for the target in the - * install tree. For example: "\@rpath/" or "\@loader_path/". */ - std::string GetInstallNameDirForInstallTree() const; - - cmComputeLinkInformation* - GetLinkInformation(const std::string& config) const; - // Get the properties cmPropertyMap &GetProperties() const { return this->Properties; } @@ -520,10 +418,6 @@ public: /** Return whether this target is an executable Bundle on Apple. */ bool IsAppBundleOnApple() const; - /** Return whether this target is an executable Bundle, a framework - or CFBundle on Apple. */ - bool IsBundleOnApple() const; - /** Return the framework version string. Undefined if IsFrameworkOnApple returns false. */ std::string GetFrameworkVersion() const; @@ -538,25 +432,9 @@ public: directory. */ bool UsesDefaultOutputDir(const std::string& config, bool implib) const; - /** @return the mac content directory for this target. */ - std::string GetMacContentDirectory(const std::string& config, - bool implib) const; - /** @return whether this target have a well defined output file name. */ bool HaveWellDefinedOutputFiles() const; - /** @return the Mac framework directory without the base. */ - std::string GetFrameworkDirectory(const std::string& config, - bool rootDir) const; - - /** @return the Mac CFBundle directory without the base */ - std::string GetCFBundleDirectory(const std::string& config, - bool contentOnly) const; - - /** @return the Mac App directory without the base */ - std::string GetAppBundleDirectory(const std::string& config, - bool contentOnly) const; - std::vector<std::string> GetIncludeDirectories( const std::string& config, const std::string& language) const; @@ -574,30 +452,10 @@ public: void GetCompileOptions(std::vector<std::string> &result, const std::string& config, const std::string& language) const; - void GetAutoUicOptions(std::vector<std::string> &result, - const std::string& config) const; void GetCompileFeatures(std::vector<std::string> &features, const std::string& config) const; bool IsNullImpliedByLinkLibraries(const std::string &p) const; - bool IsLinkInterfaceDependentBoolProperty(const std::string &p, - const std::string& config) const; - bool IsLinkInterfaceDependentStringProperty(const std::string &p, - const std::string& config) const; - bool IsLinkInterfaceDependentNumberMinProperty(const std::string &p, - const std::string& config) const; - bool IsLinkInterfaceDependentNumberMaxProperty(const std::string &p, - const std::string& config) const; - - bool GetLinkInterfaceDependentBoolProperty(const std::string &p, - const std::string& config) const; - - const char *GetLinkInterfaceDependentStringProperty(const std::string &p, - const std::string& config) const; - const char *GetLinkInterfaceDependentNumberMinProperty(const std::string &p, - const std::string& config) const; - const char *GetLinkInterfaceDependentNumberMaxProperty(const std::string &p, - const std::string& config) const; std::string GetDebugGeneratorExpressions(const std::string &value, cmTarget::LinkLibraryType llt) const; @@ -610,11 +468,6 @@ public: bool LinkLanguagePropagatesToDependents() const { return this->TargetTypeValue == STATIC_LIBRARY; } - void ReportPropertyOrigin(const std::string &p, - const std::string &result, - const std::string &report, - const std::string &compatibilityType) const; - std::map<std::string, std::string> const& GetMaxLanguageStandards() const { @@ -684,11 +537,6 @@ private: const char* GetSuffixVariableInternal(bool implib) const; const char* GetPrefixVariableInternal(bool implib) const; - std::string GetFullNameInternal(const std::string& config, - bool implib) const; - void GetFullNameInternal(const std::string& config, bool implib, - std::string& outPrefix, std::string& outBase, - std::string& outSuffix) const; // Use a makefile variable to set a default for the given property. // If the variable is not defined use the given default instead. @@ -698,19 +546,12 @@ private: // Returns ARCHIVE, LIBRARY, or RUNTIME based on platform and type. const char* GetOutputTargetType(bool implib) const; - // Get the target base name. - std::string GetOutputName(const std::string& config, bool implib) const; - std::string GetFullNameImported(const std::string& config, bool implib) const; std::string ImportedGetFullPath(const std::string& config, bool implib) const; - /** Append to @a base the mac content directory and return it. */ - std::string BuildMacContentDirectory(const std::string& base, - const std::string& config, - bool contentOnly) const; void GetSourceFiles(std::vector<std::string> &files, const std::string& config) const; @@ -721,7 +562,6 @@ private: std::set<std::string> Utilities; mutable std::set<std::string> LinkImplicitNullProperties; std::map<std::string, cmListFileBacktrace> UtilityBacktraces; - mutable std::map<std::string, bool> DebugCompatiblePropertiesDone; mutable std::map<std::string, std::string> MaxLanguageStandards; cmPolicies::PolicyMap PolicyMap; std::string Name; @@ -768,18 +608,24 @@ private: std::string& out) const; // Cache import information from properties for each configuration. - struct ImportInfo; + struct ImportInfo + { + ImportInfo(): NoSOName(false), Multiplicity(0) {} + bool NoSOName; + int Multiplicity; + std::string Location; + std::string SOName; + std::string ImportLibrary; + std::string Languages; + std::string Libraries; + std::string LibrariesProp; + std::string SharedDeps; + }; + ImportInfo const* GetImportInfo(const std::string& config) const; void ComputeImportInfo(std::string const& desired_config, ImportInfo& info) const; - // Cache target compile paths for each configuration. - struct CompileInfo; - CompileInfo const* GetCompileInfo(const std::string& config) const; - - mutable cmTargetLinkInformationMap LinkInformation; - void CheckPropertyCompatibility(cmComputeLinkInformation *info, - const std::string& config) const; LinkInterface const* GetImportLinkInterface(const std::string& config, cmTarget const* head, @@ -788,7 +634,6 @@ private: LinkImplementationLibraries const* GetLinkImplementationLibrariesInternal(const std::string& config, cmTarget const* head) const; - void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const; void ExpandLinkItems(std::string const& prop, std::string const& value, std::string const& config, cmTarget const* headTarget, diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 71785e9..80b8591 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1627,7 +1627,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( this->GlobalGenerator->GetLanguageFromExtension (sf.GetExtension().c_str()); std::string sourceLang = this->LocalGenerator->GetSourceFileLanguage(sf); - const std::string& linkLanguage = this->Target->GetLinkerLanguage(); + const std::string& linkLanguage = this->GeneratorTarget->GetLinkerLanguage(); bool needForceLang = false; // source file does not match its extension language if(lang != sourceLang) @@ -1774,7 +1774,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions() else { outDir = this->Target->GetDirectory(config->c_str()) + "/"; - targetNameFull = this->Target->GetFullName(config->c_str()); + targetNameFull = this->GeneratorTarget->GetFullName(config->c_str()); } this->ConvertToWindowsSlash(intermediateDir); this->ConvertToWindowsSlash(outDir); @@ -1888,7 +1888,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( std::string flags; const std::string& linkLanguage = - this->Target->GetLinkerLanguage(configName.c_str()); + this->GeneratorTarget->GetLinkerLanguage(configName.c_str()); if(linkLanguage.empty()) { cmSystemTools::Error @@ -2026,7 +2026,8 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( } // Specify the compiler program database file if configured. - std::string pdb = this->Target->GetCompilePDBPath(configName.c_str()); + std::string pdb = + this->GeneratorTarget->GetCompilePDBPath(configName.c_str()); if(!pdb.empty()) { this->ConvertToWindowsSlash(pdb); @@ -2370,7 +2371,7 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) Options& linkOptions = *pOptions; const std::string& linkLanguage = - this->Target->GetLinkerLanguage(config.c_str()); + this->GeneratorTarget->GetLinkerLanguage(config.c_str()); if(linkLanguage.empty()) { cmSystemTools::Error @@ -2438,7 +2439,7 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) cmSystemTools::ExpandListArgument(libs, libVec); cmComputeLinkInformation* pcli = - this->Target->GetLinkInformation(config.c_str()); + this->GeneratorTarget->GetLinkInformation(config.c_str()); if(!pcli) { cmSystemTools::Error @@ -2471,13 +2472,14 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) std::string targetNamePDB; if(this->Target->GetType() == cmTarget::EXECUTABLE) { - this->Target->GetExecutableNames(targetName, targetNameFull, + this->GeneratorTarget->GetExecutableNames(targetName, targetNameFull, targetNameImport, targetNamePDB, config.c_str()); } else { - this->Target->GetLibraryNames(targetName, targetNameSO, targetNameFull, + this->GeneratorTarget->GetLibraryNames(targetName, targetNameSO, + targetNameFull, targetNameImport, targetNamePDB, config.c_str()); } |