Commit 5b361fdd authored by Stephen Kelly's avatar Stephen Kelly
Browse files

cmLinkLineComputer: Extract from cmLocalGenerator

CMake has several classes which have too many responsibilities.
cmLocalGenerator is one of them.  Start to extract the link line
computation.  Create generator-specific implementations of the interface
to account for generator-specific behavior.

Unfortunately MSVC60 has different behavior to everything else and CMake
still generates makefiles for it.  Isolate it with MSVC60-specific
names.
parent 2e5d1990
......@@ -300,6 +300,8 @@ set(SRCS
cmInstallDirectoryGenerator.cxx
cmLinkedTree.h
cmLinkItem.h
cmLinkLineComputer.cxx
cmLinkLineComputer.h
cmListFileCache.cxx
cmListFileCache.h
cmListFileLexer.c
......@@ -318,6 +320,8 @@ set(SRCS
cmMakefileUtilityTargetGenerator.cxx
cmMessenger.cxx
cmMessenger.h
cmMSVC60LinkLineComputer.cxx
cmMSVC60LinkLineComputer.h
cmOSXBundleGenerator.cxx
cmOSXBundleGenerator.h
cmOutputConverter.cxx
......@@ -545,6 +549,8 @@ set(SRCS ${SRCS}
cmNinjaNormalTargetGenerator.h
cmNinjaUtilityTargetGenerator.cxx
cmNinjaUtilityTargetGenerator.h
cmNinjaLinkLineComputer.cxx
cmNinjaLinkLineComputer.h
)
# Temporary variable for tools targets
......
......@@ -12,6 +12,7 @@
#include "cmComputeLinkInformation.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
#include "cmLinkLineComputer.h"
#include "cmLocalCommonGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
......@@ -59,7 +60,8 @@ void cmCommonTargetGenerator::AddFeatureFlags(std::string& flags,
}
}
void cmCommonTargetGenerator::AddModuleDefinitionFlag(std::string& flags)
void cmCommonTargetGenerator::AddModuleDefinitionFlag(
cmLinkLineComputer* linkLineComputer, std::string& flags)
{
if (!this->ModuleDefinitionFile) {
return;
......@@ -76,7 +78,7 @@ void cmCommonTargetGenerator::AddModuleDefinitionFlag(std::string& flags)
// vs6's "cl -link" pass it to the linker.
std::string flag = defFileFlag;
flag += this->LocalGenerator->ConvertToOutputFormat(
this->LocalGenerator->ConvertToLinkReference(
linkLineComputer->ConvertToLinkReference(
this->ModuleDefinitionFile->GetFullPath()),
cmOutputConverter::SHELL);
this->LocalGenerator->AppendFlags(flags, flag);
......
......@@ -16,6 +16,7 @@ class cmGlobalCommonGenerator;
class cmLocalCommonGenerator;
class cmMakefile;
class cmSourceFile;
class cmLinkLineComputer;
/** \class cmCommonTargetGenerator
* \brief Common infrastructure for Makefile and Ninja per-target generators
......@@ -37,7 +38,8 @@ protected:
bool GetFeatureAsBool(const std::string& feature);
// Helper to add flag for windows .def file.
void AddModuleDefinitionFlag(std::string& flags);
void AddModuleDefinitionFlag(cmLinkLineComputer* linkLineComputer,
std::string& flags);
cmGeneratorTarget* GeneratorTarget;
cmMakefile* Makefile;
......
......@@ -5,6 +5,7 @@
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGhsMultiGenerator.h"
#include "cmLinkLineComputer.h"
#include "cmLocalGhsMultiGenerator.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
......@@ -362,9 +363,13 @@ void cmGhsMultiTargetGenerator::WriteTargetLinkLibraries(
this->GeneratorTarget->GetCreateRuleVariable(language, config);
bool useWatcomQuote =
this->Makefile->IsOn(createRule + "_USE_WATCOM_QUOTE");
CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
this->GetGlobalGenerator()->CreateLinkLineComputer(
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
this->LocalGenerator->GetTargetFlags(
config, linkLibraries, flags, linkFlags, frameworkPath, linkPath,
this->GeneratorTarget, useWatcomQuote);
linkLineComputer.get(), config, linkLibraries, flags, linkFlags,
frameworkPath, linkPath, this->GeneratorTarget, useWatcomQuote);
linkFlags = cmSystemTools::TrimWhitespace(linkFlags);
if (!linkPath.empty()) {
......
......@@ -20,7 +20,9 @@
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmInstallGenerator.h"
#include "cmLinkLineComputer.h"
#include "cmLocalGenerator.h"
#include "cmMSVC60LinkLineComputer.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
......@@ -1412,6 +1414,18 @@ cmGlobalGenerator::CreateQtAutoGeneratorsTargets()
return autogenTargets;
}
cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer(
cmState::Directory stateDir) const
{
return new cmLinkLineComputer(stateDir);
}
cmLinkLineComputer* cmGlobalGenerator::CreateMSVC60LinkLineComputer(
cmState::Directory stateDir) const
{
return new cmMSVC60LinkLineComputer(stateDir);
}
void cmGlobalGenerator::FinalizeTargetCompileInfo()
{
std::vector<std::string> const langs =
......
......@@ -34,6 +34,7 @@ class cmExportBuildFileGenerator;
class cmExternalMakefileProjectGenerator;
class cmGeneratorTarget;
class cmLocalGenerator;
class cmLinkLineComputer;
class cmMakefile;
class cmake;
......@@ -105,6 +106,12 @@ public:
*/
virtual void Generate();
virtual cmLinkLineComputer* CreateLinkLineComputer(
cmState::Directory stateDir) const;
cmLinkLineComputer* CreateMSVC60LinkLineComputer(
cmState::Directory stateDir) const;
/**
* Set/Get and Clear the enabled languages.
*/
......
......@@ -11,6 +11,7 @@
#include "cmLocalGenerator.h"
#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
#include "cmNinjaLinkLineComputer.h"
#include "cmOutputConverter.h"
#include "cmState.h"
#include "cmSystemTools.h"
......@@ -64,6 +65,13 @@ void cmGlobalNinjaGenerator::WriteComment(std::ostream& os,
os << "# " << comment.substr(lpos) << "\n\n";
}
cmLinkLineComputer* cmGlobalNinjaGenerator::CreateLinkLineComputer(
cmState::Directory /* stateDir */) const
{
return new cmNinjaLinkLineComputer(
this->LocalGenerators[0]->GetStateSnapshot().GetDirectory(), this);
}
std::string cmGlobalNinjaGenerator::EncodeRuleName(std::string const& name)
{
// Ninja rule names must match "[a-zA-Z0-9_.-]+". Use ".xx" to encode
......
......@@ -70,6 +70,9 @@ public:
std::string EncodePath(const std::string& path);
static std::string EncodeDepfileSpace(const std::string& path);
cmLinkLineComputer* CreateLinkLineComputer(cmState::Directory stateDir) const
CM_OVERRIDE;
/**
* Write the given @a comment to the output stream @a os. It
* handles new line character properly.
......
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLinkLineComputer.h"
#include "cmOutputConverter.h"
cmLinkLineComputer::cmLinkLineComputer(cmState::Directory stateDir)
: StateDir(stateDir)
{
}
cmLinkLineComputer::~cmLinkLineComputer()
{
}
std::string cmLinkLineComputer::ConvertToLinkReference(
std::string const& lib) const
{
std::string relLib = lib;
if (cmOutputConverter::ContainedInDirectory(
this->StateDir.GetCurrentBinary(), lib, this->StateDir)) {
relLib = cmOutputConverter::ForceToRelativePath(
this->StateDir.GetCurrentBinary(), lib);
}
return relLib;
}
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmLinkLineComputer_h
#define cmLinkLineComputer_h
#include "cmState.h"
class cmLinkLineComputer
{
public:
cmLinkLineComputer(cmState::Directory stateDir);
virtual ~cmLinkLineComputer();
virtual std::string ConvertToLinkReference(std::string const& input) const;
private:
cmState::Directory StateDir;
};
#endif
......@@ -12,6 +12,7 @@
#include "cmInstallGenerator.h"
#include "cmInstallScriptGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmLinkLineComputer.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmSystemTools.h"
......@@ -1148,9 +1149,10 @@ void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags,
}
void cmLocalGenerator::GetTargetFlags(
const std::string& config, std::string& linkLibs, std::string& flags,
std::string& linkFlags, std::string& frameworkPath, std::string& linkPath,
cmGeneratorTarget* target, bool useWatcomQuote)
cmLinkLineComputer* linkLineComputer, const std::string& config,
std::string& linkLibs, std::string& flags, std::string& linkFlags,
std::string& frameworkPath, std::string& linkPath, cmGeneratorTarget* target,
bool useWatcomQuote)
{
const std::string buildType = cmSystemTools::UpperCase(config);
const char* libraryLinkVariable =
......@@ -1203,8 +1205,9 @@ void cmLocalGenerator::GetTargetFlags(
linkFlags += " ";
}
}
this->OutputLinkLibraries(linkLibs, frameworkPath, linkPath, *target,
false, false, useWatcomQuote);
this->OutputLinkLibraries(linkLineComputer, linkLibs, frameworkPath,
linkPath, *target, false, false,
useWatcomQuote);
} break;
case cmState::EXECUTABLE: {
linkFlags += this->Makefile->GetSafeDefinition("CMAKE_EXE_LINKER_FLAGS");
......@@ -1223,8 +1226,9 @@ void cmLocalGenerator::GetTargetFlags(
return;
}
this->AddLanguageFlags(flags, linkLanguage, buildType);
this->OutputLinkLibraries(linkLibs, frameworkPath, linkPath, *target,
false, false, useWatcomQuote);
this->OutputLinkLibraries(linkLineComputer, linkLibs, frameworkPath,
linkPath, *target, false, false,
useWatcomQuote);
if (cmSystemTools::IsOn(
this->Makefile->GetDefinition("BUILD_SHARED_LIBS"))) {
std::string sFlagVar = std::string("CMAKE_SHARED_BUILD_") +
......@@ -1383,51 +1387,15 @@ std::string cmLocalGenerator::GetTargetFortranFlags(
return std::string();
}
std::string cmLocalGenerator::ConvertToLinkReference(std::string const& lib)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
// Work-ardound command line parsing limitations in MSVC 6.0
if (this->Makefile->IsOn("MSVC60")) {
// Search for the last space.
std::string::size_type pos = lib.rfind(' ');
if (pos != lib.npos) {
// Find the slash after the last space, if any.
pos = lib.find('/', pos);
// Convert the portion of the path with a space to a short path.
std::string sp;
if (cmSystemTools::GetShortPath(lib.substr(0, pos).c_str(), sp)) {
// Append the rest of the path with no space.
sp += lib.substr(pos);
return sp;
}
}
}
#endif
// Normal behavior.
std::string relLib = lib;
cmState::Directory stateDir = this->GetStateSnapshot().GetDirectory();
if (cmOutputConverter::ContainedInDirectory(
stateDir.GetCurrentBinary(), lib, stateDir)) {
relLib = cmOutputConverter::ForceToRelativePath(
stateDir.GetCurrentBinary(), lib);
}
return relLib;
}
/**
* Output the linking rules on a command line. For executables,
* targetLibrary should be a NULL pointer. For libraries, it should point
* to the name of the library. This will not link a library against itself.
*/
void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries,
std::string& frameworkPath,
std::string& linkPath,
cmGeneratorTarget& tgt, bool relink,
bool forResponseFile,
bool useWatcomQuote)
void cmLocalGenerator::OutputLinkLibraries(
cmLinkLineComputer* linkLineComputer, std::string& linkLibraries,
std::string& frameworkPath, std::string& linkPath, cmGeneratorTarget& tgt,
bool relink, bool forResponseFile, bool useWatcomQuote)
{
OutputFormat shellFormat =
(forResponseFile) ? RESPONSE : ((useWatcomQuote) ? WATCOMQUOTE : SHELL);
......@@ -1486,7 +1454,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries,
}
if (li->IsPath) {
linkLibs += this->ConvertToOutputFormat(
this->ConvertToLinkReference(li->Value), shellFormat);
linkLineComputer->ConvertToLinkReference(li->Value), shellFormat);
} else {
linkLibs += li->Value;
}
......
......@@ -24,6 +24,7 @@ class cmGeneratorTarget;
class cmGlobalGenerator;
class cmMakefile;
class cmSourceFile;
class cmLinkLineComputer;
/** \class cmLocalGenerator
* \brief Create required build files for a directory.
......@@ -312,7 +313,8 @@ public:
/** Fill out these strings for the given target. Libraries to link,
* flags, and linkflags. */
void GetTargetFlags(const std::string& config, std::string& linkLibs,
void GetTargetFlags(cmLinkLineComputer* linkLineComputer,
const std::string& config, std::string& linkLibs,
std::string& flags, std::string& linkFlags,
std::string& frameworkPath, std::string& linkPath,
cmGeneratorTarget* target, bool useWatcomQuote);
......@@ -345,7 +347,8 @@ public:
protected:
///! put all the libraries for a target on into the given stream
void OutputLinkLibraries(std::string& linkLibraries,
void OutputLinkLibraries(cmLinkLineComputer* linkLineComputer,
std::string& linkLibraries,
std::string& frameworkPath, std::string& linkPath,
cmGeneratorTarget&, bool relink,
bool forResponseFile, bool useWatcomQuote);
......@@ -370,8 +373,6 @@ protected:
std::string& CreateSafeUniqueObjectFileName(const std::string& sin,
std::string const& dir_max);
virtual std::string ConvertToLinkReference(std::string const& lib);
/** Check whether the native build system supports the given
definition. Issues a warning. */
virtual bool CheckDefinition(std::string const& define) const;
......
......@@ -120,12 +120,6 @@ cmGlobalNinjaGenerator* cmLocalNinjaGenerator::GetGlobalNinjaGenerator()
// Virtual protected methods.
std::string cmLocalNinjaGenerator::ConvertToLinkReference(
std::string const& lib)
{
return this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(lib);
}
std::string cmLocalNinjaGenerator::ConvertToIncludeReference(
std::string const& path, cmOutputConverter::OutputFormat format,
bool forceFullPaths)
......
......@@ -76,8 +76,6 @@ public:
void AppendCustomCommandDeps(cmCustomCommandGenerator const& ccg,
cmNinjaDeps& ninjaDeps);
std::string ConvertToLinkReference(std::string const& lib) CM_OVERRIDE;
void ComputeObjectFilenames(
std::map<cmSourceFile const*, std::string>& mapping,
cmGeneratorTarget const* gt = CM_NULLPTR) CM_OVERRIDE;
......
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmMSVC60LinkLineComputer.h"
#include "cmSystemTools.h"
cmMSVC60LinkLineComputer::cmMSVC60LinkLineComputer(cmState::Directory stateDir)
: cmLinkLineComputer(stateDir)
{
}
std::string cmMSVC60LinkLineComputer::ConvertToLinkReference(
std::string const& lib) const
{
#if defined(_WIN32) && !defined(__CYGWIN__)
// Work-ardound command line parsing limitations in MSVC 6.0
// Search for the last space.
std::string::size_type pos = lib.rfind(' ');
if (pos != lib.npos) {
// Find the slash after the last space, if any.
pos = lib.find('/', pos);
// Convert the portion of the path with a space to a short path.
std::string sp;
if (cmSystemTools::GetShortPath(lib.substr(0, pos).c_str(), sp)) {
// Append the rest of the path with no space.
sp += lib.substr(pos);
return sp;
}
}
#endif
return cmLinkLineComputer::ConvertToLinkReference(lib);
}
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmMSVC60LinkLineComputer_h
#define cmMSVC60LinkLineComputer_h
#include "cmLinkLineComputer.h"
class cmMSVC60LinkLineComputer : public cmLinkLineComputer
{
public:
cmMSVC60LinkLineComputer(cmState::Directory stateDir);
std::string ConvertToLinkReference(std::string const& input) const
CM_OVERRIDE;
};
#endif
......@@ -5,6 +5,7 @@
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLinkLineComputer.h"
#include "cmLocalGenerator.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
......@@ -215,7 +216,13 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
this->LocalGenerator->AppendFlags(
linkFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
this->AddModuleDefinitionFlag(linkFlags);
{
CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
this->CreateLinkLineComputer(
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
this->AddModuleDefinitionFlag(linkLineComputer.get(), linkFlags);
}
// Construct a list of files associated with this executable that
// may need to be cleaned.
......
......@@ -5,6 +5,7 @@
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLinkLineComputer.h"
#include "cmLocalGenerator.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
......@@ -159,7 +160,12 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
this->LocalGenerator->AddConfigVariableFlags(
extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->ConfigName);
this->AddModuleDefinitionFlag(extraFlags);
CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
this->CreateLinkLineComputer(
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags);
if (this->GeneratorTarget->GetProperty("LINK_WHAT_YOU_USE")) {
this->LocalGenerator->AppendFlags(extraFlags, " -Wl,--no-as-needed");
......@@ -184,7 +190,12 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
extraFlags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
this->LocalGenerator->AddConfigVariableFlags(
extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->ConfigName);
this->AddModuleDefinitionFlag(extraFlags);
CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
this->CreateLinkLineComputer(
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags);
this->WriteLibraryRules(linkRuleVar, extraFlags, relink);
}
......
......@@ -10,6 +10,7 @@
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLinkLineComputer.h"
#include "cmLocalGenerator.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
......@@ -1588,15 +1589,29 @@ std::string cmMakefileTargetGenerator::CreateResponseFile(
return responseFileName;
}
cmLinkLineComputer* cmMakefileTargetGenerator::CreateLinkLineComputer(
cmState::Directory stateDir)
{
if (this->Makefile->IsOn("MSVC60")) {
return this->GlobalGenerator->CreateMSVC60LinkLineComputer(stateDir);
}
return this->GlobalGenerator->CreateLinkLineComputer(stateDir);
}
void cmMakefileTargetGenerator::CreateLinkLibs(
std::string& linkLibs, bool relink, bool useResponseFile,
std::vector<std::string>& makefile_depends, bool useWatcomQuote)
{
std::string frameworkPath;
std::string linkPath;
this->LocalGenerator->OutputLinkLibraries(linkLibs, frameworkPath, linkPath,
*this->GeneratorTarget, relink,
useResponseFile, useWatcomQuote);
CM_AUTO_PTR<cmLinkLineComputer> linkLineComputer(
this->CreateLinkLineComputer(
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
this->LocalGenerator->OutputLinkLibraries(
linkLineComputer.get(), linkLibs, frameworkPath, linkPath,
*this->GeneratorTarget, relink, useResponseFile, useWatcomQuote);
linkLibs = frameworkPath + linkPath + linkLibs;
if (useResponseFile && linkLibs.find_first_not_of(' ') != linkLibs.npos) {
......
......@@ -139,6 +139,8 @@ protected:
std::vector<std::string>& makefile_commands,
std::vector<std::string>& makefile_depends);
cmLinkLineComputer* CreateLinkLineComputer(cmState::Directory stateDir);
/** 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. */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment