Commit 656ebaca authored by Brad King's avatar Brad King Committed by Kitware Robot
Browse files

Merge topic 'extract-cmLinkLineComputer'

41340304 cmLinkLineComputer: Extract link libraries computation from cmLocalGenerator
f03d446e cmLinkLineComputer: Move FrameworkPath computation from cmLocalGenerator
3444105f cmLocalGenerator: Inline last use of local variable
77c4202e cmLinkLineComputer: Move RPath computation from cmLocalGenerator
09b6cc66 cmLinkLineComputer: Move LinkPath computation from cmLocalGenerator
0c978063 cmLinkLineComputer: Move ComputeLinkLibs from cmLocalGenerator
0152a01f cmLocalGenerator: Move variable to where it is used
011e6870 cmLocalGenerator: Use a std::string instead of char*
cbca80f3 cmLocalGenerator: Move stringstream to where it is used
d48f69d0 cmLocalGenerator: Move flag determination up in the function
ff8e321c cmLocalGenerator: Separate stdlib content from library stream
80f57e67 cmLocalGenerator: Separate rpath content from library stream
7ef83468 cmLocalGenerator: Pass link library info to OutputLinkLibraries
69295812 Makefiles: Port CreateLinkLibs to cmLinkLineComputer
5b361fdd cmLinkLineComputer: Extract from cmLocalGenerator
2e5d1990 Ninja: Constify
...
parents 06b71ff9 41340304
Pipeline #30075 failed with stage
in 0 seconds
......@@ -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,15 @@ 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,
this->LocalGenerator->GetStateSnapshot().GetDirectory()));
linkLineComputer->SetUseWatcomQuote(useWatcomQuote);
this->LocalGenerator->GetTargetFlags(
config, linkLibraries, flags, linkFlags, frameworkPath, linkPath,
this->GeneratorTarget, useWatcomQuote);
linkLineComputer.get(), config, linkLibraries, flags, linkFlags,
frameworkPath, linkPath, this->GeneratorTarget);
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(
cmOutputConverter* outputConverter, cmState::Directory stateDir) const
{
return new cmLinkLineComputer(outputConverter, stateDir);
}
cmLinkLineComputer* cmGlobalGenerator::CreateMSVC60LinkLineComputer(
cmOutputConverter* outputConverter, cmState::Directory stateDir) const
{
return new cmMSVC60LinkLineComputer(outputConverter, stateDir);
}
void cmGlobalGenerator::FinalizeTargetCompileInfo()
{
std::vector<std::string> const langs =
......
......@@ -34,7 +34,9 @@ class cmExportBuildFileGenerator;
class cmExternalMakefileProjectGenerator;
class cmGeneratorTarget;
class cmLocalGenerator;
class cmLinkLineComputer;
class cmMakefile;
class cmOutputConverter;
class cmake;
/** \class cmGlobalGenerator
......@@ -105,6 +107,12 @@ public:
*/
virtual void Generate();
virtual cmLinkLineComputer* CreateLinkLineComputer(
cmOutputConverter* outputConverter, cmState::Directory stateDir) const;
cmLinkLineComputer* CreateMSVC60LinkLineComputer(
cmOutputConverter* outputConverter, 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,14 @@ void cmGlobalNinjaGenerator::WriteComment(std::ostream& os,
os << "# " << comment.substr(lpos) << "\n\n";
}
cmLinkLineComputer* cmGlobalNinjaGenerator::CreateLinkLineComputer(
cmOutputConverter* outputConverter, cmState::Directory /* stateDir */) const
{
return new cmNinjaLinkLineComputer(
outputConverter,
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
......@@ -830,7 +839,8 @@ static void EnsureTrailingSlash(std::string& path)
#endif
}
std::string cmGlobalNinjaGenerator::ConvertToNinjaPath(const std::string& path)
std::string cmGlobalNinjaGenerator::ConvertToNinjaPath(
const std::string& path) const
{
cmLocalNinjaGenerator* ng =
static_cast<cmLocalNinjaGenerator*>(this->LocalGenerators[0]);
......@@ -1421,7 +1431,8 @@ void cmGlobalNinjaGenerator::InitOutputPathPrefix()
EnsureTrailingSlash(this->OutputPathPrefix);
}
std::string cmGlobalNinjaGenerator::NinjaOutputPath(std::string const& path)
std::string cmGlobalNinjaGenerator::NinjaOutputPath(
std::string const& path) const
{
if (!this->HasOutputPathPrefix() || cmSystemTools::FileIsFullPath(path)) {
return path;
......
......@@ -70,6 +70,10 @@ public:
std::string EncodePath(const std::string& path);
static std::string EncodeDepfileSpace(const std::string& path);
cmLinkLineComputer* CreateLinkLineComputer(
cmOutputConverter* outputConverter,
cmState::Directory stateDir) const CM_OVERRIDE;
/**
* Write the given @a comment to the output stream @a os. It
* handles new line character properly.
......@@ -233,7 +237,7 @@ public:
return this->RulesFileStream;
}
std::string ConvertToNinjaPath(const std::string& path);
std::string ConvertToNinjaPath(const std::string& path) const;
std::string ConvertToNinjaFolderRule(const std::string& path);
struct MapToNinjaPathImpl
......@@ -333,7 +337,7 @@ public:
bool SupportsConsolePool() const;
bool SupportsImplicitOuts() const;
std::string NinjaOutputPath(std::string const& path);
std::string NinjaOutputPath(std::string const& path) const;
bool HasOutputPathPrefix() const { return !this->OutputPathPrefix.empty(); }
void StripNinjaOutputPathPrefixAsSuffix(std::string& path);
......
/* 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 "cmComputeLinkInformation.h"
#include "cmGeneratorTarget.h"
#include "cmOutputConverter.h"
cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter,
cmState::Directory stateDir)
: StateDir(stateDir)
, OutputConverter(outputConverter)
, ForResponse(false)
, UseWatcomQuote(false)
, Relink(false)
{
}
cmLinkLineComputer::~cmLinkLineComputer()
{
}
void cmLinkLineComputer::SetUseWatcomQuote(bool useWatcomQuote)
{
this->UseWatcomQuote = useWatcomQuote;
}
void cmLinkLineComputer::SetForResponse(bool forResponse)
{
this->ForResponse = forResponse;
}
void cmLinkLineComputer::SetRelink(bool relink)
{
this->Relink = relink;
}
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;
}
std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli)
{
std::string linkLibs;
typedef cmComputeLinkInformation::ItemVector ItemVector;
ItemVector const& items = cli.GetItems();
for (ItemVector::const_iterator li = items.begin(); li != items.end();
++li) {
if (li->Target && li->Target->GetType() == cmState::INTERFACE_LIBRARY) {
continue;
}
if (li->IsPath) {
linkLibs +=
this->ConvertToOutputFormat(this->ConvertToLinkReference(li->Value));
} else {
linkLibs += li->Value;
}
linkLibs += " ";
}
return linkLibs;
}
std::string cmLinkLineComputer::ConvertToOutputFormat(std::string const& input)
{
cmOutputConverter::OutputFormat shellFormat = (this->ForResponse)
? cmOutputConverter::RESPONSE
: ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE
: cmOutputConverter::SHELL);
return this->OutputConverter->ConvertToOutputFormat(input, shellFormat);
}
std::string cmLinkLineComputer::ConvertToOutputForExisting(
std::string const& input)
{
cmOutputConverter::OutputFormat shellFormat = (this->ForResponse)
? cmOutputConverter::RESPONSE
: ((this->UseWatcomQuote) ? cmOutputConverter::WATCOMQUOTE
: cmOutputConverter::SHELL);
return this->OutputConverter->ConvertToOutputForExisting(input, shellFormat);
}
std::string cmLinkLineComputer::ComputeLinkPath(
cmComputeLinkInformation& cli, std::string const& libPathFlag,
std::string const& libPathTerminator)
{
std::string linkPath;
std::vector<std::string> const& libDirs = cli.GetDirectories();
for (std::vector<std::string>::const_iterator libDir = libDirs.begin();
libDir != libDirs.end(); ++libDir) {
std::string libpath = this->ConvertToOutputForExisting(*libDir);
linkPath += " " + libPathFlag;
linkPath += libpath;
linkPath += libPathTerminator;
linkPath += " ";
}
return linkPath;
}
std::string cmLinkLineComputer::ComputeRPath(cmComputeLinkInformation& cli)
{
std::string rpath;
// Check what kind of rpath flags to use.
if (cli.GetRuntimeSep().empty()) {
// Each rpath entry gets its own option ("-R a -R b -R c")
std::vector<std::string> runtimeDirs;
cli.GetRPath(runtimeDirs, this->Relink);
for (std::vector<std::string>::iterator ri = runtimeDirs.begin();
ri != runtimeDirs.end(); ++ri) {
rpath += cli.GetRuntimeFlag();
rpath += this->ConvertToOutputFormat(*ri);
rpath += " ";
}
} else {
// All rpath entries are combined ("-Wl,-rpath,a:b:c").
std::string rpathString = cli.GetRPathString(this->Relink);
// Store the rpath option in the stream.
if (!rpathString.empty()) {
rpath += cli.GetRuntimeFlag();
rpath +=
this->OutputConverter->EscapeForShell(rpathString, !this->ForResponse);
rpath += " ";
}
}
return rpath;
}
std::string cmLinkLineComputer::ComputeFrameworkPath(
cmComputeLinkInformation& cli, std::string const& fwSearchFlag)
{
std::string frameworkPath;
if (!fwSearchFlag.empty()) {
std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
for (std::vector<std::string>::const_iterator fdi = fwDirs.begin();
fdi != fwDirs.end(); ++fdi) {
frameworkPath += fwSearchFlag;
frameworkPath += this->ConvertToOutputFormat(*fdi);
frameworkPath += " ";
}
}
return frameworkPath;
}
std::string cmLinkLineComputer::ComputeLinkLibraries(
cmComputeLinkInformation& cli, std::string const& stdLibString)
{
std::ostringstream fout;
fout << this->ComputeRPath(cli);
// Write the library flags to the build rule.
fout << this->ComputeLinkLibs(cli);
// Add the linker runtime search path if any.
std::string rpath_link = cli.GetRPathLinkString();
if (!cli.GetRPathLinkFlag().empty() && !rpath_link.empty()) {
fout << cli.GetRPathLinkFlag();
fout << this->OutputConverter->EscapeForShell(rpath_link,
!this->ForResponse);
fout << " ";
}
if (!stdLibString.empty()) {
fout << stdLibString << " ";
}
return fout.str();
}
/* 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 cmComputeLinkInformation;
class cmOutputConverter;
class cmLinkLineComputer
{
public:
cmLinkLineComputer(cmOutputConverter* outputConverter,
cmState::Directory stateDir);
virtual ~cmLinkLineComputer();
void SetUseWatcomQuote(bool useWatcomQuote);
void SetForResponse(bool forResponse);
void SetRelink(bool relink);
virtual std::string ConvertToLinkReference(std::string const& input) const;
std::string ComputeLinkPath(cmComputeLinkInformation& cli,
std::string const& libPathFlag,
std::string const& libPathTerminator);
std::string ComputeFrameworkPath(cmComputeLinkInformation& cli,
std::string const& fwSearchFlag);
std::string ComputeLinkLibraries(cmComputeLinkInformation& cli,
std::string const& stdLibString);
private:
std::string ComputeLinkLibs(cmComputeLinkInformation& cli);
std::string ComputeRPath(cmComputeLinkInformation& cli);
std::string ConvertToOutputFormat(std::string const& input);
std::string ConvertToOutputForExisting(std::string const& input);
cmState::Directory StateDir;
cmOutputConverter* OutputConverter;
bool ForResponse;
bool UseWatcomQuote;
bool Relink;
};
#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,11 +1149,12 @@ 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)
{
const std::string buildType = cmSystemTools::UpperCase(config);
cmComputeLinkInformation* pcli = target->GetLinkInformation(config);
const char* libraryLinkVariable =
"CMAKE_SHARED_LINKER_FLAGS"; // default to shared library
......@@ -1203,8 +1205,10 @@ void cmLocalGenerator::GetTargetFlags(
linkFlags += " ";
}
}
this->OutputLinkLibraries(linkLibs, frameworkPath, linkPath, *target,
false, false, useWatcomQuote);
if (pcli) {
this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
frameworkPath, linkPath);
}
} break;
case cmState::EXECUTABLE: {
linkFlags += this->Makefile->GetSafeDefinition("CMAKE_EXE_LINKER_FLAGS");
......@@ -1223,8 +1227,10 @@ void cmLocalGenerator::GetTargetFlags(
return;
}
this->AddLanguageFlags(flags, linkLanguage, buildType);
this->OutputLinkLibraries(linkLibs, frameworkPath, linkPath, *target,
false, false, useWatcomQuote);
if (pcli) {
this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs,
frameworkPath, linkPath);
}
if (cmSystemTools::IsOn(
this->Makefile->GetDefinition("BUILD_SHARED_LIBS"))) {
std::string sFlagVar = std::string("CMAKE_SHARED_BUILD_") +
......@@ -1383,155 +1389,46 @@ 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.
return this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), lib);
}
/**
* 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)
{
OutputFormat shellFormat =
(forResponseFile) ? RESPONSE : ((useWatcomQuote) ? WATCOMQUOTE : SHELL);
bool escapeAllowMakeVars = !forResponseFile;
std::ostringstream fout;
std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
cmComputeLinkInformation* pcli = tgt.GetLinkInformation(config);
if (!pcli) {
return;
}
void cmLocalGenerator::OutputLinkLibraries(
cmComputeLinkInformation* pcli, cmLinkLineComputer* linkLineComputer,
std::string& linkLibraries, std::string& frameworkPath,
std::string& linkPath)
{
cmComputeLinkInformation& cli = *pcli;
std::string linkLanguage = cli.GetLinkLanguage();
std::string linkLibs;
std::string libPathFlag =
this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG");
std::string libPathTerminator =
this->Makefile->GetSafeDefinition("CMAKE_LIBRARY_PATH_TERMINATOR");
// Append the framework search path flags.
std::string fwSearchFlagVar = "CMAKE_";
fwSearchFlagVar += linkLanguage;
fwSearchFlagVar += "_FRAMEWORK_SEARCH_FLAG";
const char* fwSearchFlag = this->Makefile->GetDefinition(fwSearchFlagVar);
if (fwSearchFlag && *fwSearchFlag) {
std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
for (std::vector<std::string>::const_iterator fdi = fwDirs.begin();
fdi != fwDirs.end(); ++fdi) {
frameworkPath += fwSearchFlag;
frameworkPath += this->ConvertToOutputFormat(*fdi, shellFormat);
frameworkPath += " ";
}
}
// Append the library search path flags.
std::vector<std::string> const& libDirs = cli.GetDirectories();
for (std::vector<std::string>::const_iterator libDir = libDirs.begin();
libDir != libDirs.end(); ++libDir) {
std::string libpath =
this->ConvertToOutputForExisting(*libDir, shellFormat);
linkPath += " " + libPathFlag;
linkPath += libpath;
linkPath += libPathTerminator;
linkPath += " ";
}
// Append the link items.
typedef cmComputeLinkInformation::ItemVector ItemVector;
ItemVector const& items = cli.GetItems();
for (ItemVector::const_iterator li = items.begin(); li != items.end();
++li) {
if (li->Target && li->Target->GetType() == cmState::INTERFACE_LIBRARY) {
continue;