summaryrefslogtreecommitdiff
path: root/Source/cmMakefileExecutableTargetGenerator.cxx
diff options
context:
space:
mode:
authorRaul Tambre <raul@tambre.ee>2020-09-05 19:40:02 +0300
committerBrad King <brad.king@kitware.com>2020-09-24 15:19:54 -0400
commitc63fe018353cf6afb30980c4cac7493be7cd0a82 (patch)
tree68d2daf0cd8ab91a9feaa49392607c6cfecd2ac4 /Source/cmMakefileExecutableTargetGenerator.cxx
parentc98ec731f90eb0180c89108b7d2e42263b66d1ed (diff)
downloadcmake-c63fe018353cf6afb30980c4cac7493be7cd0a82.tar.gz
CUDA: Clang separable compilation
For NVCC the compiler takes care of device linking when passed the "-dlink" flag. Clang doesn't support such magic and requires the buildsystem to do the work that NVCC does behind the scenes. The implementation is based on Bazel's device linking documentation: https://github.com/tensorflow/tensorflow/blob/7cabcdf073abad8c46e9dda62bb8fa4682d2061e/third_party/nccl/build_defs.bzl.tpl#L259 Closes: #20726
Diffstat (limited to 'Source/cmMakefileExecutableTargetGenerator.cxx')
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx53
1 files changed, 31 insertions, 22 deletions
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 9b5c6e60a8..871878c0b0 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -91,19 +91,12 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
std::vector<std::string> commands;
- // Get the language to use for linking this library.
- std::string linkLanguage = "CUDA";
+ // Get the name of the device object to generate.
std::string const& objExt =
this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION");
-
- // Build list of dependencies.
- std::vector<std::string> depends;
- this->AppendLinkDepends(depends, linkLanguage);
-
- // Get the name of the device object to generate.
- std::string const targetOutputReal =
+ std::string const targetOutput =
this->GeneratorTarget->ObjectDirectory + "cmake_device_link" + objExt;
- this->DeviceLinkObject = targetOutputReal;
+ this->DeviceLinkObject = targetOutput;
this->NumberOfProgressActions++;
if (!this->NoRuleMessages) {
@@ -111,7 +104,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
this->MakeEchoProgress(progress);
// Add the link message.
std::string buildEcho =
- cmStrCat("Linking ", linkLanguage, " device code ",
+ cmStrCat("Linking CUDA device code ",
this->LocalGenerator->ConvertToOutputFormat(
this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetCurrentBinaryDirectory(),
@@ -121,6 +114,29 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
}
+ if (this->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_ID") == "Clang") {
+ this->WriteDeviceLinkRule(commands, targetOutput);
+ } else {
+ this->WriteNvidiaDeviceExecutableRule(relink, commands, targetOutput);
+ }
+
+ // Write the main driver rule to build everything in this target.
+ this->WriteTargetDriverRule(targetOutput, relink);
+#else
+ static_cast<void>(relink);
+#endif
+}
+
+void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
+ bool relink, std::vector<std::string>& commands,
+ const std::string& targetOutput)
+{
+ const std::string linkLanguage = "CUDA";
+
+ // Build list of dependencies.
+ std::vector<std::string> depends;
+ this->AppendLinkDepends(depends, linkLanguage);
+
// Build a list of compiler flags and linker flags.
std::string langFlags;
std::string linkFlags;
@@ -136,7 +152,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
// may need to be cleaned.
std::vector<std::string> exeCleanFiles;
exeCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal));
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutput));
// Determine whether a link script will be used.
bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
@@ -195,7 +211,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
: cmOutputConverter::SHELL;
std::string target = this->LocalGenerator->ConvertToOutputFormat(
this->LocalGenerator->MaybeConvertToRelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal),
+ this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutput),
output);
std::string targetFullPathCompilePDB =
@@ -226,7 +242,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
this->LocalGenerator->CreateRulePlaceholderExpander());
// Expand placeholders in the commands.
- rulePlaceholderExpander->SetTargetImpLib(targetOutputReal);
+ rulePlaceholderExpander->SetTargetImpLib(targetOutput);
for (std::string& real_link_command : real_link_commands) {
real_link_command = cmStrCat(launcher, real_link_command);
rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
@@ -255,17 +271,10 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
// Write the build rule.
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
- targetOutputReal, depends, commands,
- false);
-
- // Write the main driver rule to build everything in this target.
- this->WriteTargetDriverRule(targetOutputReal, relink);
+ targetOutput, depends, commands, false);
// Clean all the possible executable names and symlinks.
this->CleanFiles.insert(exeCleanFiles.begin(), exeCleanFiles.end());
-#else
- static_cast<void>(relink);
-#endif
}
void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)