diff options
author | Brad King <brad.king@kitware.com> | 2016-11-03 20:44:32 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2016-11-09 14:45:14 (GMT) |
commit | 09cda9d5e7bb31f05177bdaf11d24aeaf85a8dd3 (patch) | |
tree | a755fd6424b16a66b008c998e108e7c1b43b64df /Source | |
parent | 1d1f1eeb6a52d464d476eb0a46eb75c452e3dfbc (diff) | |
download | CMake-09cda9d5e7bb31f05177bdaf11d24aeaf85a8dd3.zip CMake-09cda9d5e7bb31f05177bdaf11d24aeaf85a8dd3.tar.gz CMake-09cda9d5e7bb31f05177bdaf11d24aeaf85a8dd3.tar.bz2 |
Allow imported INTERFACE libraries to specify a link library name
Add an `IMPORTED_LIBNAME[_<CONFIG>]` target property to specify a library
name to be placed on the link line in place of an interface library
since it has no library file of its own. Restrict use of the property
to imported `INTERFACE` libraries.
This will be particularly useful for find modules that need to provide
imported libraries from system SDKs where the full path to the library
file is not known. Now such find modules will be able to provide an
imported interface library and set `IMPORTED_LIBNAME` to refer to the
SDK library by name.
Issue: #15267
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmComputeLinkInformation.cxx | 6 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 13 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.h | 4 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 55 | ||||
-rw-r--r-- | Source/cmTarget.h | 3 | ||||
-rw-r--r-- | Source/cmTargetPropertyComputer.cxx | 4 |
6 files changed, 72 insertions, 13 deletions
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 28aa533..80e7e7d 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -606,6 +606,12 @@ void cmComputeLinkInformation::AddItem(std::string const& item, // of COMPATIBLE_INTERFACE_ enforcement. The generators will ignore // this for the actual link line. this->Items.push_back(Item(std::string(), false, tgt)); + + // Also add the item the interface specifies to be used in its place. + std::string const& libName = tgt->GetImportedLibName(config); + if (!libName.empty()) { + this->AddItem(libName, CM_NULLPTR); + } } else { // Decide whether to use an import library. bool implib = diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index ca056c0..a18a9ef 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -2796,6 +2796,16 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const } } +std::string cmGeneratorTarget::GetImportedLibName( + std::string const& config) const +{ + if (cmGeneratorTarget::ImportInfo const* info = + this->GetImportInfo(config)) { + return info->LibName; + } + return std::string(); +} + std::string cmGeneratorTarget::GetFullPath(const std::string& config, bool implib, bool realname) const { @@ -4711,6 +4721,9 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, } } if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + if (loc) { + info.LibName = loc; + } return; } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 3805bfc..4c3c14b 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -147,6 +147,9 @@ public: const cmGeneratorTarget* head, bool usage_requirements_only) const; + /** Get the library name for an imported interface library. */ + std::string GetImportedLibName(std::string const& 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, @@ -643,6 +646,7 @@ private: std::string Location; std::string SOName; std::string ImportLibrary; + std::string LibName; std::string Languages; std::string Libraries; std::string LibrariesProp; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index e37a9f8..434edf5 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -912,6 +912,9 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->SourceEntries.push_back(value); this->Internal->SourceBacktraces.push_back(lfbt); } + } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") && + !this->CheckImportedLibName(prop, value ? value : "")) { + /* error was reported by check method */ } else { this->Properties.SetProperty(prop, value); } @@ -979,6 +982,9 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); this->Internal->SourceEntries.push_back(value); this->Internal->SourceBacktraces.push_back(lfbt); + } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME")) { + this->Makefile->IssueMessage(cmake::FATAL_ERROR, + prop + " property may not be APPENDed."); } else { this->Properties.AppendProperty(prop, value, asString); } @@ -1374,20 +1380,41 @@ void cmTarget::SetPropertyDefault(const std::string& property, } } +bool cmTarget::CheckImportedLibName(std::string const& prop, + std::string const& value) const +{ + if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY || + !this->IsImported()) { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, prop + + " property may be set only on imported INTERFACE library targets."); + return false; + } + if (!value.empty()) { + if (value[0] == '-') { + this->Makefile->IssueMessage(cmake::FATAL_ERROR, prop + + " property value\n " + value + + "\nmay not start with '-'."); + return false; + } + std::string::size_type bad = value.find_first_of(":/\\;"); + if (bad != value.npos) { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, prop + " property value\n " + value + + "\nmay not contain '" + value.substr(bad, 1) + "'."); + return false; + } + } + return true; +} + bool cmTarget::GetMappedConfig(std::string const& desired_config, const char** loc, const char** imp, std::string& suffix) const { - if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) { - // This method attempts to find a config-specific LOCATION for the - // IMPORTED library. In the case of cmStateEnums::INTERFACE_LIBRARY, there - // is no - // LOCATION at all, so leaving *loc and *imp unchanged is the appropriate - // and valid response. - return true; - } - - std::string const locPropBase = "IMPORTED_LOCATION"; + std::string const locPropBase = + this->GetType() == cmStateEnums::INTERFACE_LIBRARY ? "IMPORTED_LIBNAME" + : "IMPORTED_LOCATION"; // Track the configuration-specific property suffix. suffix = "_"; @@ -1445,7 +1472,9 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, // then the target location is not found. The project does not want // any other configuration. if (!mappedConfigs.empty() && !*loc && !*imp) { - return false; + // Interface libraries are always available because their + // library name is optional so it is okay to leave *loc empty. + return this->GetType() == cmStateEnums::INTERFACE_LIBRARY; } // If we have not yet found it then there are no mapped @@ -1499,7 +1528,9 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, } // If we have not yet found it then the target location is not available. if (!*loc && !*imp) { - return false; + // Interface libraries are always available because their + // library name is optional so it is okay to leave *loc empty. + return this->GetType() == cmStateEnums::INTERFACE_LIBRARY; } return true; diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 1f035a1..2f6aa12 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -277,6 +277,9 @@ private: void SetPropertyDefault(const std::string& property, const char* default_value); + bool CheckImportedLibName(std::string const& prop, + std::string const& value) const; + private: cmPropertyMap Properties; std::set<std::string> SystemIncludeDirectories; diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx index 7cf1fd8..5ad1694 100644 --- a/Source/cmTargetPropertyComputer.cxx +++ b/Source/cmTargetPropertyComputer.cxx @@ -66,7 +66,9 @@ bool cmTargetPropertyComputer::WhiteListedInterfaceProperty( return true; } - if (cmHasLiteralPrefix(prop, "MAP_IMPORTED_CONFIG_")) { + if (prop == "IMPORTED_CONFIGURATIONS" || prop == "IMPORTED_LIBNAME" || + cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME_") || + cmHasLiteralPrefix(prop, "MAP_IMPORTED_CONFIG_")) { return true; } |