summaryrefslogtreecommitdiffstats
path: root/Source/cmGeneratorTarget.cxx
diff options
context:
space:
mode:
authorMarc Chevrier <marc.chevrier@gmail.com>2023-09-27 13:22:55 (GMT)
committerMarc Chevrier <marc.chevrier@gmail.com>2023-10-13 09:52:35 (GMT)
commit96a953b1ed7e41260aa0869bad0ff14c788cf57e (patch)
treed9bedd8494b073f3795e4ed80f01b22a2b5a9093 /Source/cmGeneratorTarget.cxx
parentee5f31ba727e392e1ebc9f5be54c74ac1868d029 (diff)
downloadCMake-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.cxx69
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
{