/* 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 #include #include "cmComputeLinkInformation.h" #include "cmGeneratorTarget.h" #include "cmOutputConverter.h" #include "cmStateDirectory.h" #include "cmStateTypes.h" cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter, cmStateDirectory const& 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() == cmStateEnums::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 const& libDirs = cli.GetDirectories(); for (std::vector::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 runtimeDirs; cli.GetRPath(runtimeDirs, this->Relink); for (std::vector::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 const& fwDirs = cli.GetFrameworkPaths(); for (std::vector::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(); } std::string cmLinkLineComputer::GetLinkerLanguage(cmGeneratorTarget* target, std::string const& config) { return target->GetLinkerLanguage(config); }