diff options
author | Robert Maynard <robert.maynard@kitware.com> | 2016-10-21 18:17:42 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2016-11-14 21:40:49 (GMT) |
commit | d038559e49b0d0dd65124370f48a92ba3de9006c (patch) | |
tree | 690627ae383a74ab82be197a83068a51ab7dc8cf /Source/cmMakefileLibraryTargetGenerator.cxx | |
parent | 43ce4414c479af6b04e93decaf7f69938c92a323 (diff) | |
download | CMake-d038559e49b0d0dd65124370f48a92ba3de9006c.zip CMake-d038559e49b0d0dd65124370f48a92ba3de9006c.tar.gz CMake-d038559e49b0d0dd65124370f48a92ba3de9006c.tar.bz2 |
CUDA: Add separable compilation support to the makefile generator.
Diffstat (limited to 'Source/cmMakefileLibraryTargetGenerator.cxx')
-rw-r--r-- | Source/cmMakefileLibraryTargetGenerator.cxx | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index c591bb3..2b0e1b1 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -11,6 +11,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalUnixMakefileGenerator3.h" #include "cmLinkLineComputer.h" +#include "cmLinkLineDeviceComputer.h" #include "cmLocalGenerator.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" @@ -151,6 +152,24 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) this->WriteFrameworkRules(relink); return; } + + if (!relink) { + const std::string cuda_lang("CUDA"); + cmGeneratorTarget::LinkClosure const* closure = + this->GeneratorTarget->GetLinkClosure(this->ConfigName); + + const bool hasCUDA = + (std::find(closure->Languages.begin(), closure->Languages.end(), + cuda_lang) != closure->Languages.end()); + if (hasCUDA) { + std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; + std::string extraFlags; + this->LocalGenerator->AppendFlags( + extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS")); + this->WriteDeviceLibraryRules(linkRuleVar, extraFlags, relink); + } + } + std::string linkLanguage = this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); std::string linkRuleVar = "CMAKE_"; @@ -183,6 +202,24 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) { + + if (!relink) { + const std::string cuda_lang("CUDA"); + cmGeneratorTarget::LinkClosure const* closure = + this->GeneratorTarget->GetLinkClosure(this->ConfigName); + + const bool hasCUDA = + (std::find(closure->Languages.begin(), closure->Languages.end(), + cuda_lang) != closure->Languages.end()); + if (hasCUDA) { + std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_LIBRARY"; + std::string extraFlags; + this->LocalGenerator->AppendFlags( + extraFlags, this->GeneratorTarget->GetProperty("LINK_FLAGS")); + this->WriteDeviceLibraryRules(linkRuleVar, extraFlags, relink); + } + } + std::string linkLanguage = this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); std::string linkRuleVar = "CMAKE_"; @@ -230,6 +267,180 @@ void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink) this->WriteLibraryRules(linkRuleVar, extraFlags, relink); } +void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( + const std::string& linkRuleVar, const std::string& extraFlags, bool relink) +{ +#ifdef CMAKE_BUILD_WITH_CMAKE + // TODO: Merge the methods that call this method to avoid + // code duplication. + std::vector<std::string> commands; + + // Build list of dependencies. + std::vector<std::string> depends; + this->AppendLinkDepends(depends); + + // Get the language to use for linking this library. + std::string linkLanguage = "CUDA"; + + // Create set of linking flags. + std::string linkFlags; + this->LocalGenerator->AppendFlags(linkFlags, extraFlags); + + // Get the name of the device object to generate. + std::string const targetOutputReal = + this->GeneratorTarget->ObjectDirectory + "cmake_device_link.o"; + this->DeviceLinkObject = targetOutputReal; + + this->NumberOfProgressActions++; + if (!this->NoRuleMessages) { + cmLocalUnixMakefileGenerator3::EchoProgress progress; + this->MakeEchoProgress(progress); + // Add the link message. + std::string buildEcho = "Linking " + linkLanguage + " device code"; + buildEcho += targetOutputReal; + this->LocalGenerator->AppendEcho( + commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress); + } + // Clean files associated with this library. + std::vector<std::string> libCleanFiles; + libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal)); + + // Determine whether a link script will be used. + bool useLinkScript = this->GlobalGenerator->GetUseLinkScript(); + + bool useResponseFileForObjects = + this->CheckUseResponseFileForObjects(linkLanguage); + bool const useResponseFileForLibs = + this->CheckUseResponseFileForLibraries(linkLanguage); + + cmRulePlaceholderExpander::RuleVariables vars; + vars.Language = linkLanguage.c_str(); + + // Expand the rule variables. + std::vector<std::string> real_link_commands; + { + bool useWatcomQuote = + this->Makefile->IsOn(linkRuleVar + "_USE_WATCOM_QUOTE"); + + // Set path conversion for link script shells. + this->LocalGenerator->SetLinkScriptShell(useLinkScript); + + // Collect up flags to link in needed libraries. + std::string linkLibs; + if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY) { + + CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer( + new cmLinkLineDeviceComputer( + this->LocalGenerator, + this->LocalGenerator->GetStateSnapshot().GetDirectory())); + linkLineComputer->SetForResponse(useResponseFileForLibs); + linkLineComputer->SetUseWatcomQuote(useWatcomQuote); + linkLineComputer->SetRelink(relink); + + this->CreateLinkLibs(linkLineComputer.get(), linkLibs, + useResponseFileForLibs, depends); + } + + // Construct object file lists that may be needed to expand the + // rule. + std::string buildObjs; + this->CreateObjectLists(useLinkScript, false, // useArchiveRules + useResponseFileForObjects, buildObjs, depends, + useWatcomQuote); + + cmOutputConverter::OutputFormat output = (useWatcomQuote) + ? cmOutputConverter::WATCOMQUOTE + : cmOutputConverter::SHELL; + + std::string objectDir = this->GeneratorTarget->GetSupportDirectory(); + objectDir = this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetCurrentBinaryDirectory(), objectDir), + cmOutputConverter::SHELL); + + std::string target = this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetCurrentBinaryDirectory(), targetOutputReal), + output); + + vars.Objects = buildObjs.c_str(); + vars.ObjectDir = objectDir.c_str(); + vars.Target = target.c_str(); + vars.LinkLibraries = linkLibs.c_str(); + vars.ObjectsQuoted = buildObjs.c_str(); + vars.LinkFlags = linkFlags.c_str(); + + // Add language feature flags. + std::string langFlags; + this->AddFeatureFlags(langFlags, linkLanguage); + + vars.LanguageCompileFlags = langFlags.c_str(); + + std::string launcher; + const char* val = this->LocalGenerator->GetRuleLauncher( + this->GeneratorTarget, "RULE_LAUNCH_LINK"); + if (val && *val) { + launcher = val; + launcher += " "; + } + + CM_AUTO_PTR<cmRulePlaceholderExpander> rulePlaceholderExpander( + this->LocalGenerator->CreateRulePlaceholderExpander()); + + // Construct the main link rule and expand placeholders. + rulePlaceholderExpander->SetTargetImpLib(targetOutputReal); + std::string linkRule = this->GetLinkRule(linkRuleVar); + cmSystemTools::ExpandListArgument(linkRule, real_link_commands); + + // Expand placeholders. + for (std::vector<std::string>::iterator i = real_link_commands.begin(); + i != real_link_commands.end(); ++i) { + *i = launcher + *i; + rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, *i, + vars); + } + // Restore path conversion to normal shells. + this->LocalGenerator->SetLinkScriptShell(false); + + // Clean all the possible library names and symlinks. + this->CleanFiles.insert(this->CleanFiles.end(), libCleanFiles.begin(), + libCleanFiles.end()); + } + + std::vector<std::string> commands1; + // Optionally convert the build rule to use a script to avoid long + // command lines in the make shell. + if (useLinkScript) { + // Use a link script. + const char* name = (relink ? "drelink.txt" : "dlink.txt"); + this->CreateLinkScript(name, real_link_commands, commands1, depends); + } else { + // No link script. Just use the link rule directly. + commands1 = real_link_commands; + } + this->LocalGenerator->CreateCDCommand( + commands1, this->Makefile->GetCurrentBinaryDirectory(), + this->LocalGenerator->GetBinaryDirectory()); + commands.insert(commands.end(), commands1.begin(), commands1.end()); + commands1.clear(); + + // Compute the list of outputs. + std::vector<std::string> outputs(1, targetOutputReal); + + // Write the build rule. + this->WriteMakeRule(*this->BuildFileStream, CM_NULLPTR, outputs, depends, + commands, false); + + // Write the main driver rule to build everything in this target. + this->WriteTargetDriverRule(targetOutputReal, relink); +#else + static_cast<void>(linkRuleVar); + static_cast<void>(extraFlags); + static_cast<void>(relink); +#endif +} + void cmMakefileLibraryTargetGenerator::WriteLibraryRules( const std::string& linkRuleVar, const std::string& extraFlags, bool relink) { @@ -240,6 +451,9 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Build list of dependencies. std::vector<std::string> depends; this->AppendLinkDepends(depends); + if (!this->DeviceLinkObject.empty()) { + depends.push_back(this->DeviceLinkObject); + } // Get the language to use for linking this library. std::string linkLanguage = @@ -518,6 +732,14 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( this->CreateObjectLists(useLinkScript, useArchiveRules, useResponseFileForObjects, buildObjs, depends, useWatcomQuote); + if (!this->DeviceLinkObject.empty()) { + buildObjs += " " + + this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetCurrentBinaryDirectory(), + this->DeviceLinkObject), + cmOutputConverter::SHELL); + } // maybe create .def file from list of objects if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY && |