diff options
author | Marc Chevrier <marc.chevrier@gmail.com> | 2023-09-27 13:22:55 (GMT) |
---|---|---|
committer | Marc Chevrier <marc.chevrier@gmail.com> | 2023-10-13 09:52:35 (GMT) |
commit | 96a953b1ed7e41260aa0869bad0ff14c788cf57e (patch) | |
tree | d9bedd8494b073f3795e4ed80f01b22a2b5a9093 /Source/cmGeneratorTarget.cxx | |
parent | ee5f31ba727e392e1ebc9f5be54c74ac1868d029 (diff) | |
download | CMake-96a953b1ed7e41260aa0869bad0ff14c788cf57e.zip CMake-96a953b1ed7e41260aa0869bad0ff14c788cf57e.tar.gz CMake-96a953b1ed7e41260aa0869bad0ff14c788cf57e.tar.bz2 |
Add options to specify linker tool
Offer the capability, through variable `CMAKE_LINKER_TYPE`, as well as
the target property `LINKER_TYPE` to specify which linker must be used.
The implementation of this capability is specified by variables specific
to the language and linker type: `CMAKE_<LANG>_USING_LINKER_<TYPE>`.
Some definitions are provided as part of `CMake`.
For example, to select the `LLVM` linker rather than the standard one,
the type `LLD` should be specified through the variable `CMAKE_LINKER_TYPE`.
And, on `Apple`, `Linux` and some environments on `Windows`, the variable
`CMAKE_<LANG>_USING_LINKER_LLD` has value `-fuse-ld=lld`. And for `Windows`
environments based on `MSVC`, where the linker is used directly, the tool
`lld-link.exe` will be used rather than `link.exe`.
Fixes: #19174, #24254, #24990
Diffstat (limited to 'Source/cmGeneratorTarget.cxx')
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 2ea18bd..f7a6a4e 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -868,6 +868,31 @@ cmValue cmGeneratorTarget::GetFeature(const std::string& feature, return this->LocalGenerator->GetFeature(feature, config); } +std::string cmGeneratorTarget::GetLinkerTypeProperty( + std::string const& lang, std::string const& config) const +{ + std::string propName{ "LINKER_TYPE" }; + auto linkerType = this->GetProperty(propName); + if (!linkerType.IsEmpty()) { + cmGeneratorExpressionDAGChecker dagChecker(this, propName, nullptr, + nullptr); + auto ltype = + cmGeneratorExpression::Evaluate(*linkerType, this->GetLocalGenerator(), + config, this, &dagChecker, this, lang); + if (this->IsDeviceLink()) { + cmList list{ ltype }; + const auto DL_BEGIN = "<DEVICE_LINK>"_s; + const auto DL_END = "</DEVICE_LINK>"_s; + cm::erase_if(list, [&](const std::string& item) { + return item == DL_BEGIN || item == DL_END; + }); + return list.to_string(); + } + return ltype; + } + return std::string{}; +} + const char* cmGeneratorTarget::GetLinkPIEProperty( const std::string& config) const { @@ -5515,6 +5540,50 @@ std::string cmGeneratorTarget::GetLinkerLanguage( return this->GetLinkClosure(config)->LinkerLanguage; } +std::string cmGeneratorTarget::GetLinkerTool(const std::string& config) const +{ + return this->GetLinkerTool(this->GetLinkerLanguage(config), config); +} + +std::string cmGeneratorTarget::GetLinkerTool(const std::string& lang, + const std::string& config) const +{ + auto usingLinker = + cmStrCat("CMAKE_", lang, "_USING_", this->IsDeviceLink() ? "DEVICE_" : "", + "LINKER_"); + auto format = this->Makefile->GetDefinition(cmStrCat(usingLinker, "MODE")); + if (!format || format != "TOOL"_s) { + return this->Makefile->GetDefinition("CMAKE_LINKER"); + } + + auto linkerType = this->GetLinkerTypeProperty(lang, config); + if (linkerType.empty()) { + linkerType = "DEFAULT"; + } + usingLinker = cmStrCat(usingLinker, linkerType); + auto linkerTool = this->Makefile->GetDefinition(usingLinker); + + if (!linkerTool) { + if (this->GetGlobalGenerator()->IsVisualStudio() && + linkerType == "DEFAULT"_s) { + return std::string{}; + } + + // fall-back to generic definition + linkerTool = this->Makefile->GetDefinition("CMAKE_LINKER"); + + if (linkerType != "DEFAULT"_s) { + this->LocalGenerator->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("LINKER_TYPE '", linkerType, + "' is unknown. Did you forgot to define '", usingLinker, + "' variable?")); + } + } + + return linkerTool; +} + std::string cmGeneratorTarget::GetPDBOutputName( const std::string& config) const { |