CUDA: Support response files with nvcc

This commit is contained in:
Robert Maynard
2022-06-01 09:20:08 -04:00
parent 87273cc9d3
commit 6377a43814
6 changed files with 83 additions and 49 deletions

View File

@@ -127,15 +127,19 @@ else()
endif()
# FIXME: investigate use of --options-file.
# Tell Makefile generator that nvcc does not support @<rspfile> syntax.
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES 0)
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES 0)
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS 0)
if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "9.0")
set(CMAKE_CUDA_RESPONSE_FILE_DEVICE_LINK_FLAG "--options-file ")
set(CMAKE_CUDA_RESPONSE_FILE_FLAG "--options-file ")
endif()
if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "11.0")
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES 1)
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES 1)
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS 1)
else()
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES 0)
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES 0)
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS 0)
endif()
__compiler_check_default_language_standard(CUDA 6.0 03)

View File

@@ -605,6 +605,15 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
// does not include any system headers anyway.
fprintf(fout,
"set_property(DIRECTORY PROPERTY INCLUDE_DIRECTORIES \"\")\n");
// The link and compile lines for ABI detection step need to not use
// response files so we can extract implicit includes given to
// the underlying host compiler
if (testLangs.find("CUDA") != testLangs.end()) {
fprintf(fout, "set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES OFF)\n");
fprintf(fout, "set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES OFF)\n");
fprintf(fout, "set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS OFF)\n");
}
}
fprintf(fout, "set(CMAKE_VERBOSE_MAKEFILE 1)\n");
for (std::string const& li : testLangs) {

View File

@@ -182,14 +182,16 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
// Collect up flags to link in needed libraries.
std::string linkLibs;
this->CreateLinkLibs(linkLineComputer.get(), linkLibs,
useResponseFileForLibs, depends);
this->CreateLinkLibs(
linkLineComputer.get(), linkLibs, useResponseFileForLibs, depends,
cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink);
// Construct object file lists that may be needed to expand the
// rule.
std::string buildObjs;
this->CreateObjectLists(useLinkScript, false, useResponseFileForObjects,
buildObjs, depends, false);
this->CreateObjectLists(
useLinkScript, false, useResponseFileForObjects, buildObjs, depends,
false, cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink);
cmRulePlaceholderExpander::RuleVariables vars;
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();

View File

@@ -322,15 +322,17 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules(
linkLineComputer->SetForResponse(useResponseFileForLibs);
linkLineComputer->SetRelink(relink);
this->CreateLinkLibs(linkLineComputer.get(), linkLibs,
useResponseFileForLibs, depends);
this->CreateLinkLibs(
linkLineComputer.get(), linkLibs, useResponseFileForLibs, depends,
cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink);
// Construct object file lists that may be needed to expand the
// rule.
std::string buildObjs;
this->CreateObjectLists(useLinkScript, false, // useArchiveRules
useResponseFileForObjects, buildObjs, depends,
false);
this->CreateObjectLists(
useLinkScript, false, // useArchiveRules
useResponseFileForObjects, buildObjs, depends, false,
cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink);
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
objectDir = this->LocalGenerator->ConvertToOutputFormat(

View File

@@ -107,7 +107,7 @@ std::unique_ptr<cmMakefileTargetGenerator> cmMakefileTargetGenerator::New(
return result;
}
std::string cmMakefileTargetGenerator::GetConfigName()
std::string cmMakefileTargetGenerator::GetConfigName() const
{
auto const& configNames = this->LocalGenerator->GetConfigNames();
assert(configNames.size() == 1);
@@ -2080,7 +2080,7 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForLibraries(
}
std::string cmMakefileTargetGenerator::CreateResponseFile(
const char* name, std::string const& options,
const std::string& name, std::string const& options,
std::vector<std::string>& makefile_depends)
{
// FIXME: Find a better way to determine the response file encoding,
@@ -2126,7 +2126,8 @@ cmMakefileTargetGenerator::CreateLinkLineComputer(
void cmMakefileTargetGenerator::CreateLinkLibs(
cmLinkLineComputer* linkLineComputer, std::string& linkLibs,
bool useResponseFile, std::vector<std::string>& makefile_depends)
bool useResponseFile, std::vector<std::string>& makefile_depends,
ResponseFlagFor responseMode)
{
std::string frameworkPath;
std::string linkPath;
@@ -2139,20 +2140,13 @@ void cmMakefileTargetGenerator::CreateLinkLibs(
if (useResponseFile &&
linkLibs.find_first_not_of(' ') != std::string::npos) {
// Lookup the response file reference flag.
std::string responseFlagVar =
cmStrCat("CMAKE_",
this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()),
"_RESPONSE_FILE_LINK_FLAG");
std::string responseFlag;
if (cmValue p = this->Makefile->GetDefinition(responseFlagVar)) {
responseFlag = *p;
} else {
responseFlag = "@";
}
std::string responseFlag = this->GetResponseFlag(responseMode);
// Create this response file.
std::string responseFileName =
(responseMode == Link) ? "linkLibs.rsp" : "deviceLinkLibs.rsp";
std::string link_rsp =
this->CreateResponseFile("linklibs.rsp", linkLibs, makefile_depends);
this->CreateResponseFile(responseFileName, linkLibs, makefile_depends);
// Reference the response file.
linkLibs = cmStrCat(responseFlag,
@@ -2164,7 +2158,7 @@ void cmMakefileTargetGenerator::CreateLinkLibs(
void cmMakefileTargetGenerator::CreateObjectLists(
bool useLinkScript, bool useArchiveRules, bool useResponseFile,
std::string& buildObjs, std::vector<std::string>& makefile_depends,
bool useWatcomQuote)
bool useWatcomQuote, ResponseFlagFor responseMode)
{
std::string variableName;
std::string variableNameExternal;
@@ -2179,27 +2173,19 @@ void cmMakefileTargetGenerator::CreateObjectLists(
this->WriteObjectsStrings(object_strings, responseFileLimit);
// Lookup the response file reference flag.
std::string responseFlagVar =
cmStrCat("CMAKE_",
this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()),
"_RESPONSE_FILE_LINK_FLAG");
std::string responseFlag;
if (cmValue p = this->Makefile->GetDefinition(responseFlagVar)) {
responseFlag = *p;
} else {
responseFlag = "@";
}
std::string responseFlag = this->GetResponseFlag(responseMode);
// Write a response file for each string.
const char* sep = "";
for (unsigned int i = 0; i < object_strings.size(); ++i) {
// Number the response files.
char rsp[32];
snprintf(rsp, sizeof(rsp), "objects%u.rsp", i + 1);
std::string responseFileName =
(responseMode == Link) ? "objects" : "deviceObjects";
responseFileName += std::to_string(i + 1);
// Create this response file.
std::string objects_rsp =
this->CreateResponseFile(rsp, object_strings[i], makefile_depends);
std::string objects_rsp = this->CreateResponseFile(
responseFileName, object_strings[i], makefile_depends);
// Separate from previous response file references.
buildObjs += sep;
@@ -2251,7 +2237,7 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
}
std::string name = cmStrCat("includes_", lang, ".rsp");
std::string arg = std::move(responseFlag) +
this->CreateResponseFile(name.c_str(), includeFlags,
this->CreateResponseFile(name, includeFlags,
this->FlagFileDepends[lang]);
this->LocalGenerator->AppendFlags(flags, arg);
} else {
@@ -2304,3 +2290,22 @@ void cmMakefileTargetGenerator::GenDefFile(
fout << src->GetFullPath() << "\n";
}
}
std::string cmMakefileTargetGenerator::GetResponseFlag(
ResponseFlagFor mode) const
{
std::string responseFlag = "@";
std::string responseFlagVar;
auto lang = this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName());
if (mode == cmMakefileTargetGenerator::ResponseFlagFor::Link) {
responseFlagVar = cmStrCat("CMAKE_", lang, "_RESPONSE_FILE_LINK_FLAG");
} else if (mode == cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink) {
responseFlagVar = "CMAKE_CUDA_RESPONSE_FILE_DEVICE_LINK_FLAG";
}
if (cmValue p = this->Makefile->GetDefinition(responseFlagVar)) {
responseFlag = *p;
}
return responseFlag;
}

View File

@@ -56,7 +56,7 @@ public:
cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; }
std::string GetConfigName();
std::string GetConfigName() const;
protected:
void GetDeviceLinkFlags(std::string& linkFlags,
@@ -157,22 +157,31 @@ protected:
/** Create a response file with the given set of options. Returns
the relative path from the target build working directory to the
response file name. */
std::string CreateResponseFile(const char* name, std::string const& options,
std::string CreateResponseFile(const std::string& name,
std::string const& options,
std::vector<std::string>& makefile_depends);
bool CheckUseResponseFileForObjects(std::string const& l) const;
bool CheckUseResponseFileForLibraries(std::string const& l) const;
enum ResponseFlagFor
{
Link,
DeviceLink
};
/** Create list of flags for link libraries. */
void CreateLinkLibs(cmLinkLineComputer* linkLineComputer,
std::string& linkLibs, bool useResponseFile,
std::vector<std::string>& makefile_depends);
std::vector<std::string>& makefile_depends,
ResponseFlagFor responseMode = ResponseFlagFor::Link);
/** Create lists of object files for linking and cleaning. */
void CreateObjectLists(bool useLinkScript, bool useArchiveRules,
bool useResponseFile, std::string& buildObjs,
std::vector<std::string>& makefile_depends,
bool useWatcomQuote);
bool useWatcomQuote,
ResponseFlagFor responseMode = ResponseFlagFor::Link);
/** Add commands for generate def files */
void GenDefFile(std::vector<std::string>& real_link_commands);
@@ -180,6 +189,9 @@ protected:
void AddIncludeFlags(std::string& flags, const std::string& lang,
const std::string& config) override;
/** Return the response flag for the given configuration */
std::string GetResponseFlag(ResponseFlagFor mode) const;
virtual void CloseFileStreams();
cmLocalUnixMakefileGenerator3* LocalGenerator;
cmGlobalUnixMakefileGenerator3* GlobalGenerator;