diff options
-rw-r--r-- | Source/cmComputeTargetDepends.cxx | 40 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 103 | ||||
-rw-r--r-- | Source/cmTarget.h | 6 | ||||
-rw-r--r-- | Tests/CMakeCommands/target_link_libraries/CMakeLists.txt | 7 | ||||
-rw-r--r-- | Tests/CMakeCommands/target_link_libraries/depB.cpp | 6 | ||||
-rw-r--r-- | Tests/CMakeCommands/target_link_libraries/libgenex.cpp | 7 | ||||
-rw-r--r-- | Tests/CMakeCommands/target_link_libraries/libgenex.h | 12 |
7 files changed, 164 insertions, 17 deletions
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index c3a75e4..8fd95b9 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -200,25 +200,51 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) // Get the depender. cmTarget* depender = this->Targets[depender_index]; - // Loop over all targets linked directly. + // Loop over all targets linked directly in all configs. + // We need to make targets depend on the union of all config-specific + // dependencies in all targets, because the generated build-systems can't + // deal with config-specific dependencies. { - cmTarget::LinkLibraryVectorType const& tlibs = - depender->GetOriginalLinkLibraries(); std::set<cmStdString> emitted; + { + std::vector<std::string> tlibs; + depender->GetDirectLinkLibraries(0, tlibs, depender); // A target should not depend on itself. emitted.insert(depender->GetName()); - for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin(); + for(std::vector<std::string>::const_iterator lib = tlibs.begin(); lib != tlibs.end(); ++lib) { // Don't emit the same library twice for this target. - if(emitted.insert(lib->first).second) + if(emitted.insert(*lib).second) { - this->AddTargetDepend(depender_index, lib->first.c_str(), true); - this->AddInterfaceDepends(depender_index, lib->first.c_str(), + this->AddTargetDepend(depender_index, lib->c_str(), true); + this->AddInterfaceDepends(depender_index, lib->c_str(), true, emitted); } } } + std::vector<std::string> configs; + depender->GetMakefile()->GetConfigurations(configs); + for (std::vector<std::string>::const_iterator it = configs.begin(); + it != configs.end(); ++it) + { + std::vector<std::string> tlibs; + depender->GetDirectLinkLibraries(it->c_str(), tlibs, depender); + // A target should not depend on itself. + emitted.insert(depender->GetName()); + for(std::vector<std::string>::const_iterator lib = tlibs.begin(); + lib != tlibs.end(); ++lib) + { + // Don't emit the same library twice for this target. + if(emitted.insert(*lib).second) + { + this->AddTargetDepend(depender_index, lib->c_str(), true); + this->AddInterfaceDepends(depender_index, lib->c_str(), + true, emitted); + } + } + } + } // Loop over all utility dependencies. { diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 1338ec4..25054c5 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -520,6 +520,22 @@ void cmTarget::DefineProperties(cmake *cm) "undefined behavior."); cm->DefineProperty + ("LINK_LIBRARIES", cmProperty::TARGET, + "List of direct link dependencies.", + "This property specifies the list of libraries or targets which will be " + "used for linking. " + "In addition to accepting values from the target_link_libraries " + "command, values may be set directly on any target using the " + "set_property command. " + "\n" + "The target property values are used by the generators to set " + "the link libraries for the compiler. " + "See also the target_link_libraries command.\n" + "Contents of LINK_LIBRARIES may use \"generator expressions\" with " + "the syntax \"$<...>\". " + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS); + + cm->DefineProperty ("INCLUDE_DIRECTORIES", cmProperty::TARGET, "List of preprocessor include file search directories.", "This property specifies the list of directories given " @@ -2140,6 +2156,66 @@ bool cmTarget::NameResolvesToFramework(const std::string& libname) } //---------------------------------------------------------------------------- +void cmTarget::GetDirectLinkLibraries(const char *config, + std::vector<std::string> &libs, cmTarget *head) +{ + const char *prop = this->GetProperty("LINK_LIBRARIES"); + if (prop) + { + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + "LINK_LIBRARIES", 0, 0); + cmSystemTools::ExpandListArgument(ge.Parse(prop)->Evaluate(this->Makefile, + config, + false, + head, + &dagChecker), + libs); + } +} + +//---------------------------------------------------------------------------- +std::string cmTarget::GetDebugGeneratorExpressions(const std::string &value, + cmTarget::LinkLibraryType llt) +{ + if (llt == GENERAL) + { + return value; + } + + // Get the list of configurations considered to be DEBUG. + std::vector<std::string> const& debugConfigs = + this->Makefile->GetCMakeInstance()->GetDebugConfigs(); + + std::string configString = "$<CONFIG:" + debugConfigs[0] + ">"; + + if (debugConfigs.size() > 1) + { + for(std::vector<std::string>::const_iterator + li = debugConfigs.begin() + 1; li != debugConfigs.end(); ++li) + { + configString += ",$<CONFIG:" + *li + ">"; + } + configString = "$<OR:" + configString + ">"; + } + + if (llt == OPTIMIZED) + { + configString = "$<NOT:" + configString + ">"; + } + return "$<" + configString + ":" + value + ">"; +} + +//---------------------------------------------------------------------------- +static std::string targetNameGenex(const char *lib) +{ + return std::string("$<TARGET_NAME:") + lib + ">"; +} + +//---------------------------------------------------------------------------- void cmTarget::AddLinkLibrary(cmMakefile& mf, const char *target, const char* lib, LinkLibraryType llt) @@ -2149,6 +2225,18 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, { return; } + + { + cmTarget *tgt = this->Makefile->FindTargetToUse(lib); + const bool isNonImportedTarget = tgt && !tgt->IsImported(); + + std::string libName = isNonImportedTarget ? targetNameGenex(lib) + : std::string(lib); + this->AppendProperty("LINK_LIBRARIES", + this->GetDebugGeneratorExpressions(libName, + llt).c_str()); + } + cmTarget::LibraryID tmp; tmp.first = lib; tmp.second = llt; @@ -4884,26 +4972,23 @@ void cmTarget::ComputeLinkImplementation(const char* config, LinkImplementation& impl, cmTarget *head) { - (void)head; // Compute which library configuration to link. cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config); // Collect libraries directly linked in this configuration. - LinkLibraryVectorType const& llibs = this->GetOriginalLinkLibraries(); - for(cmTarget::LinkLibraryVectorType::const_iterator li = llibs.begin(); + std::vector<std::string> llibs; + this->GetDirectLinkLibraries(config, llibs, head); + for(std::vector<std::string>::const_iterator li = llibs.begin(); li != llibs.end(); ++li) { // Skip entries that resolve to the target itself or are empty. - std::string item = this->CheckCMP0004(li->first); + std::string item = this->CheckCMP0004(*li); if(item == this->GetName() || item.empty()) { continue; } - if(li->second == cmTarget::GENERAL || li->second == linkType) - { - // The entry is meant for this configuration. - impl.Libraries.push_back(item); - } + // The entry is meant for this configuration. + impl.Libraries.push_back(item); } LinkLibraryVectorType const& oldllibs = this->GetOriginalLinkLibraries(); diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 29c73b6..d4069fa 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -168,6 +168,9 @@ public: return this->LinkLibraries;} const LinkLibraryVectorType &GetOriginalLinkLibraries() const {return this->OriginalLinkLibraries;} + void GetDirectLinkLibraries(const char *config, + std::vector<std::string> &, + cmTarget *head); /** Compute the link type to use for the given configuration. */ LinkLibraryType ComputeLinkType(const char* config); @@ -622,6 +625,9 @@ private: void ProcessSourceExpression(std::string const& expr); + std::string GetDebugGeneratorExpressions(const std::string &value, + cmTarget::LinkLibraryType llt); + // The cmMakefile instance that owns this target. This should // always be set. cmMakefile* Makefile; diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt index 60b36fc..63ae675 100644 --- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt +++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt @@ -34,6 +34,13 @@ generate_export_header(depB) target_link_libraries(depB LINK_PRIVATE depA) +add_library(libgenex SHARED libgenex.cpp) +generate_export_header(libgenex) + +set_property(TARGET depB APPEND PROPERTY + LINK_LIBRARIES $<1:libgenex> +) + add_library(depC SHARED depC.cpp) generate_export_header(depC) diff --git a/Tests/CMakeCommands/target_link_libraries/depB.cpp b/Tests/CMakeCommands/target_link_libraries/depB.cpp index 1bbe38b..4f46552 100644 --- a/Tests/CMakeCommands/target_link_libraries/depB.cpp +++ b/Tests/CMakeCommands/target_link_libraries/depB.cpp @@ -3,9 +3,13 @@ #include "depA.h" +#include "libgenex.h" + int DepB::foo() { DepA a; - return a.foo(); + LibGenex lg; + + return a.foo() + lg.foo(); } diff --git a/Tests/CMakeCommands/target_link_libraries/libgenex.cpp b/Tests/CMakeCommands/target_link_libraries/libgenex.cpp new file mode 100644 index 0000000..c925c08 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/libgenex.cpp @@ -0,0 +1,7 @@ + +#include "libgenex.h" + +int LibGenex::foo() +{ + return 0; +} diff --git a/Tests/CMakeCommands/target_link_libraries/libgenex.h b/Tests/CMakeCommands/target_link_libraries/libgenex.h new file mode 100644 index 0000000..733f9b6 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/libgenex.h @@ -0,0 +1,12 @@ + +#include "libgenex_export.h" + +#ifndef LIBGENEX_H +#define LIBGENEX_H + +struct LIBGENEX_EXPORT LibGenex +{ + int foo(); +}; + +#endif |