ENH: Handle large object file lists on some platforms
- Use a response file when enabled by CMAKE_<LANG>_USE_RESPONSE_FILE_FOR_OBJECTS - Enable for C and CXX with cl (MSVC) - Enable for Fortran with ifort (Intel Fortran)
This commit is contained in:
parent
4c137bad6b
commit
dfe2ea6406
@ -9,8 +9,10 @@ ENDIF(CMAKE_VERBOSE_MAKEFILE)
|
|||||||
|
|
||||||
SET(CMAKE_Fortran_MODDIR_FLAG "-module:")
|
SET(CMAKE_Fortran_MODDIR_FLAG "-module:")
|
||||||
|
|
||||||
|
SET(CMAKE_Fortran_USE_RESPONSE_FILE_FOR_OBJECTS 1)
|
||||||
|
|
||||||
SET(CMAKE_Fortran_CREATE_SHARED_LIBRARY
|
SET(CMAKE_Fortran_CREATE_SHARED_LIBRARY
|
||||||
"link ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /out:<TARGET> /dll <LINK_FLAGS> <OBJECTS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}")
|
"link ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /dll <LINK_FLAGS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}")
|
||||||
|
|
||||||
SET(CMAKE_Fortran_CREATE_SHARED_MODULE ${CMAKE_Fortran_CREATE_SHARED_LIBRARY})
|
SET(CMAKE_Fortran_CREATE_SHARED_MODULE ${CMAKE_Fortran_CREATE_SHARED_LIBRARY})
|
||||||
|
|
||||||
@ -24,7 +26,7 @@ SET(CMAKE_Fortran_COMPILE_OBJECT
|
|||||||
SET(CMAKE_COMPILE_RESOURCE "rc <FLAGS> /fo<OBJECT> <SOURCE>")
|
SET(CMAKE_COMPILE_RESOURCE "rc <FLAGS> /fo<OBJECT> <SOURCE>")
|
||||||
|
|
||||||
SET(CMAKE_Fortran_LINK_EXECUTABLE
|
SET(CMAKE_Fortran_LINK_EXECUTABLE
|
||||||
"<CMAKE_Fortran_COMPILER> ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} <FLAGS> <OBJECTS> /Fe<TARGET> -link <CMAKE_Fortran_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}")
|
"<CMAKE_Fortran_COMPILER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} <FLAGS> /Fe<TARGET> -link <CMAKE_Fortran_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}")
|
||||||
|
|
||||||
SET(CMAKE_CREATE_WIN32_EXE /subsystem:windows)
|
SET(CMAKE_CREATE_WIN32_EXE /subsystem:windows)
|
||||||
SET(CMAKE_CREATE_CONSOLE_EXE /subsystem:console)
|
SET(CMAKE_CREATE_CONSOLE_EXE /subsystem:console)
|
||||||
|
@ -17,7 +17,7 @@ ELSE(CMAKE_VERBOSE_MAKEFILE)
|
|||||||
ENDIF(CMAKE_VERBOSE_MAKEFILE)
|
ENDIF(CMAKE_VERBOSE_MAKEFILE)
|
||||||
# create a shared C++ library
|
# create a shared C++ library
|
||||||
SET(CMAKE_CXX_CREATE_SHARED_LIBRARY
|
SET(CMAKE_CXX_CREATE_SHARED_LIBRARY
|
||||||
"<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /dll /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <LINK_FLAGS> <OBJECTS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}")
|
"<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /dll /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <LINK_FLAGS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}")
|
||||||
SET(CMAKE_CXX_CREATE_SHARED_MODULE ${CMAKE_CXX_CREATE_SHARED_LIBRARY})
|
SET(CMAKE_CXX_CREATE_SHARED_MODULE ${CMAKE_CXX_CREATE_SHARED_LIBRARY})
|
||||||
|
|
||||||
# create a C shared library
|
# create a C shared library
|
||||||
@ -40,12 +40,13 @@ SET(CMAKE_CXX_COMPILE_OBJECT
|
|||||||
SET(CMAKE_C_COMPILE_OBJECT
|
SET(CMAKE_C_COMPILE_OBJECT
|
||||||
"<CMAKE_C_COMPILER> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} <FLAGS> <DEFINES> /Fo<OBJECT> /Fd<TARGET_PDB> -c <SOURCE>${CMAKE_END_TEMP_FILE}")
|
"<CMAKE_C_COMPILER> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} <FLAGS> <DEFINES> /Fo<OBJECT> /Fd<TARGET_PDB> -c <SOURCE>${CMAKE_END_TEMP_FILE}")
|
||||||
|
|
||||||
|
SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1)
|
||||||
SET(CMAKE_C_LINK_EXECUTABLE
|
SET(CMAKE_C_LINK_EXECUTABLE
|
||||||
"<CMAKE_C_COMPILER> ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} <FLAGS> <OBJECTS> /Fe<TARGET> /Fd<TARGET_PDB> -link /implib:<TARGET_IMPLIB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}")
|
"<CMAKE_C_COMPILER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} <FLAGS> /Fe<TARGET> /Fd<TARGET_PDB> -link /implib:<TARGET_IMPLIB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}")
|
||||||
|
|
||||||
|
SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1)
|
||||||
SET(CMAKE_CXX_LINK_EXECUTABLE
|
SET(CMAKE_CXX_LINK_EXECUTABLE
|
||||||
"<CMAKE_CXX_COMPILER> ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} <FLAGS> <OBJECTS> /Fe<TARGET> /Fd<TARGET_PDB> -link /implib:<TARGET_IMPLIB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}")
|
"<CMAKE_CXX_COMPILER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} <FLAGS> /Fe<TARGET> /Fd<TARGET_PDB> -link /implib:<TARGET_IMPLIB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}")
|
||||||
|
|
||||||
SET(CMAKE_C_CREATE_PREPROCESSED_SOURCE
|
SET(CMAKE_C_CREATE_PREPROCESSED_SOURCE
|
||||||
"<CMAKE_C_COMPILER> > <PREPROCESSED_SOURCE> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} <FLAGS> <DEFINES> -E <SOURCE>${CMAKE_END_TEMP_FILE}")
|
"<CMAKE_C_COMPILER> > <PREPROCESSED_SOURCE> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} <FLAGS> <DEFINES> -E <SOURCE>${CMAKE_END_TEMP_FILE}")
|
||||||
|
@ -1059,6 +1059,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
|
|||||||
cmProperty::VARIABLE,0,0);
|
cmProperty::VARIABLE,0,0);
|
||||||
cm->DefineProperty("CMAKE_<LANG>_STANDARD_LIBRARIES_INIT",
|
cm->DefineProperty("CMAKE_<LANG>_STANDARD_LIBRARIES_INIT",
|
||||||
cmProperty::VARIABLE,0,0);
|
cmProperty::VARIABLE,0,0);
|
||||||
|
cm->DefineProperty("CMAKE_<LANG>_USE_RESPONSE_FILE_FOR_OBJECTS",
|
||||||
|
cmProperty::VARIABLE,0,0);
|
||||||
cm->DefineProperty("CMAKE_EXECUTABLE_SUFFIX_<LANG>",
|
cm->DefineProperty("CMAKE_EXECUTABLE_SUFFIX_<LANG>",
|
||||||
cmProperty::VARIABLE,0,0);
|
cmProperty::VARIABLE,0,0);
|
||||||
cm->DefineProperty("CMAKE_EXE_LINK_DYNAMIC_<LANG>_FLAGS",
|
cm->DefineProperty("CMAKE_EXE_LINK_DYNAMIC_<LANG>_FLAGS",
|
||||||
|
@ -328,6 +328,18 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Select whether to use a response file for objects.
|
||||||
|
bool useResponseFile = false;
|
||||||
|
{
|
||||||
|
std::string responseVar = "CMAKE_";
|
||||||
|
responseVar += linkLanguage;
|
||||||
|
responseVar += "_USE_RESPONSE_FILE_FOR_OBJECTS";
|
||||||
|
if(this->Makefile->IsOn(responseVar.c_str()))
|
||||||
|
{
|
||||||
|
useResponseFile = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Expand the rule variables.
|
// Expand the rule variables.
|
||||||
{
|
{
|
||||||
// Set path conversion for link script shells.
|
// Set path conversion for link script shells.
|
||||||
@ -343,7 +355,18 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
|
|||||||
std::string variableNameExternal;
|
std::string variableNameExternal;
|
||||||
this->WriteObjectsVariable(variableName, variableNameExternal);
|
this->WriteObjectsVariable(variableName, variableNameExternal);
|
||||||
std::string buildObjs;
|
std::string buildObjs;
|
||||||
if(useLinkScript)
|
if(useResponseFile)
|
||||||
|
{
|
||||||
|
std::string objects;
|
||||||
|
this->WriteObjectsString(objects);
|
||||||
|
std::string objects_rsp =
|
||||||
|
this->CreateResponseFile("objects.rsp", objects, depends);
|
||||||
|
buildObjs = "@";
|
||||||
|
buildObjs += this->Convert(objects_rsp.c_str(),
|
||||||
|
cmLocalGenerator::NONE,
|
||||||
|
cmLocalGenerator::SHELL);
|
||||||
|
}
|
||||||
|
else if(useLinkScript)
|
||||||
{
|
{
|
||||||
this->WriteObjectsString(buildObjs);
|
this->WriteObjectsString(buildObjs);
|
||||||
}
|
}
|
||||||
|
@ -567,6 +567,18 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
|
|||||||
// Determine whether a link script will be used.
|
// Determine whether a link script will be used.
|
||||||
bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
|
bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
|
||||||
|
|
||||||
|
// Select whether to use a response file for objects.
|
||||||
|
bool useResponseFile = false;
|
||||||
|
{
|
||||||
|
std::string responseVar = "CMAKE_";
|
||||||
|
responseVar += linkLanguage;
|
||||||
|
responseVar += "_USE_RESPONSE_FILE_FOR_OBJECTS";
|
||||||
|
if(this->Makefile->IsOn(responseVar.c_str()))
|
||||||
|
{
|
||||||
|
useResponseFile = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// For static libraries there might be archiving rules.
|
// For static libraries there might be archiving rules.
|
||||||
std::vector<std::string> archiveCreateCommands;
|
std::vector<std::string> archiveCreateCommands;
|
||||||
std::vector<std::string> archiveAppendCommands;
|
std::vector<std::string> archiveAppendCommands;
|
||||||
@ -605,6 +617,9 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
|
|||||||
// Archiving rules are always run with a link script.
|
// Archiving rules are always run with a link script.
|
||||||
useLinkScript = true;
|
useLinkScript = true;
|
||||||
|
|
||||||
|
// Archiving rules never use a response file.
|
||||||
|
useResponseFile = false;
|
||||||
|
|
||||||
// Limit the length of individual object lists to less than the
|
// Limit the length of individual object lists to less than the
|
||||||
// 32K command line length limit on Windows. We could make this a
|
// 32K command line length limit on Windows. We could make this a
|
||||||
// platform file variable but this should work everywhere.
|
// platform file variable but this should work everywhere.
|
||||||
@ -631,7 +646,18 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
|
|||||||
std::string variableNameExternal;
|
std::string variableNameExternal;
|
||||||
this->WriteObjectsVariable(variableName, variableNameExternal);
|
this->WriteObjectsVariable(variableName, variableNameExternal);
|
||||||
std::string buildObjs;
|
std::string buildObjs;
|
||||||
if(useLinkScript)
|
if(useResponseFile)
|
||||||
|
{
|
||||||
|
std::string objects;
|
||||||
|
this->WriteObjectsString(objects);
|
||||||
|
std::string objects_rsp =
|
||||||
|
this->CreateResponseFile("objects.rsp", objects, depends);
|
||||||
|
buildObjs = "@";
|
||||||
|
buildObjs += this->Convert(objects_rsp.c_str(),
|
||||||
|
cmLocalGenerator::NONE,
|
||||||
|
cmLocalGenerator::SHELL);
|
||||||
|
}
|
||||||
|
else if(useLinkScript)
|
||||||
{
|
{
|
||||||
if(!useArchiveRules)
|
if(!useArchiveRules)
|
||||||
{
|
{
|
||||||
|
@ -1583,6 +1583,30 @@ cmMakefileTargetGenerator
|
|||||||
makefile_depends.push_back(linkScriptName);
|
makefile_depends.push_back(linkScriptName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
std::string
|
||||||
|
cmMakefileTargetGenerator
|
||||||
|
::CreateResponseFile(const char* name, std::string const& options,
|
||||||
|
std::vector<std::string>& makefile_depends)
|
||||||
|
{
|
||||||
|
// Create the response file.
|
||||||
|
std::string responseFileNameFull = this->TargetBuildDirectoryFull;
|
||||||
|
responseFileNameFull += "/";
|
||||||
|
responseFileNameFull += name;
|
||||||
|
cmGeneratedFileStream responseStream(responseFileNameFull.c_str());
|
||||||
|
responseStream << options << "\n";
|
||||||
|
|
||||||
|
// Add a dependency so the target will rebuild when the set of
|
||||||
|
// objects changes.
|
||||||
|
makefile_depends.push_back(responseFileNameFull);
|
||||||
|
|
||||||
|
// Construct the name to be used on the command line.
|
||||||
|
std::string responseFileName = this->TargetBuildDirectory;
|
||||||
|
responseFileName += "/";
|
||||||
|
responseFileName += name;
|
||||||
|
return responseFileName;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
const char* cmMakefileTargetGenerator::GetFortranModuleDirectory()
|
const char* cmMakefileTargetGenerator::GetFortranModuleDirectory()
|
||||||
{
|
{
|
||||||
|
@ -137,6 +137,13 @@ protected:
|
|||||||
std::vector<std::string>& makefile_commands,
|
std::vector<std::string>& makefile_commands,
|
||||||
std::vector<std::string>& makefile_depends);
|
std::vector<std::string>& makefile_depends);
|
||||||
|
|
||||||
|
/** 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::vector<std::string>& makefile_depends);
|
||||||
|
|
||||||
virtual void CloseFileStreams();
|
virtual void CloseFileStreams();
|
||||||
void RemoveForbiddenFlags(const char* flagVar, const char* linkLang,
|
void RemoveForbiddenFlags(const char* flagVar, const char* linkLang,
|
||||||
std::string& linkFlags);
|
std::string& linkFlags);
|
||||||
|
Loading…
Reference in New Issue
Block a user