summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorCraig Scott <craig.scott@crascit.com>2018-09-26 12:11:28 (GMT)
committerKitware Robot <kwrobot@kitware.com>2018-09-26 12:11:40 (GMT)
commit3181f8405bc949affb8ea321ec7746b44717fd99 (patch)
tree7111151e7ef38815fea1dae046f1cc46dd2df04a /Source
parentb16b25484545e8186eb8d52760386b6ab531b9c2 (diff)
parentf9717725f9d4c7f4a1da52b0184365cd757bc076 (diff)
downloadCMake-3181f8405bc949affb8ea321ec7746b44717fd99.zip
CMake-3181f8405bc949affb8ea321ec7746b44717fd99.tar.gz
CMake-3181f8405bc949affb8ea321ec7746b44717fd99.tar.bz2
Merge topic 'link-directories'
f9717725f9 link_directories(): enhance capabilities b5915744eb LINK_DIRECTORIES target property: add policy for absolute paths check. a71caab46b LINK_DIRECTORIES: Add new properties and commands 5ca130e223 Refactoring: introduce function to check if a string is a generator expression Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !2403
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/cmCPluginAPI.cxx2
-rw-r--r--Source/cmCommands.cxx3
-rw-r--r--Source/cmComputeLinkInformation.cxx11
-rw-r--r--Source/cmExportBuildFileGenerator.cxx3
-rw-r--r--Source/cmExportFileGenerator.cxx31
-rw-r--r--Source/cmExportFileGenerator.h4
-rw-r--r--Source/cmExportInstallFileGenerator.cxx2
-rw-r--r--Source/cmGeneratorExpression.cxx6
-rw-r--r--Source/cmGeneratorExpression.h9
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.h1
-rw-r--r--Source/cmGeneratorTarget.cxx131
-rw-r--r--Source/cmGeneratorTarget.h8
-rw-r--r--Source/cmIncludeDirectoryCommand.cxx8
-rw-r--r--Source/cmLinkDirectoriesCommand.cxx30
-rw-r--r--Source/cmLinkDirectoriesCommand.h3
-rw-r--r--Source/cmMakefile.cxx38
-rw-r--r--Source/cmMakefile.h3
-rw-r--r--Source/cmPolicies.h8
-rw-r--r--Source/cmState.cxx5
-rw-r--r--Source/cmStateDirectory.cxx80
-rw-r--r--Source/cmStateDirectory.h10
-rw-r--r--Source/cmStatePrivate.h4
-rw-r--r--Source/cmStateSnapshot.cxx7
-rw-r--r--Source/cmTarget.cxx83
-rw-r--r--Source/cmTarget.h11
-rw-r--r--Source/cmTargetLinkDirectoriesCommand.cxx61
-rw-r--r--Source/cmTargetLinkDirectoriesCommand.h41
28 files changed, 537 insertions, 68 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index bfddbc6..3cf6c8f 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -579,6 +579,8 @@ set(SRCS
cmTargetIncludeDirectoriesCommand.h
cmTargetLinkOptionsCommand.cxx
cmTargetLinkOptionsCommand.h
+ cmTargetLinkDirectoriesCommand.cxx
+ cmTargetLinkDirectoriesCommand.h
cmTargetLinkLibrariesCommand.cxx
cmTargetLinkLibrariesCommand.h
cmTargetPropCommandBase.cxx
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index 3aa59d6..22ae340 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -171,7 +171,7 @@ void CCONV cmAddLinkDirectoryForTarget(void* arg, const char* tgt,
" for directory ", d);
return;
}
- t->AddLinkDirectory(d);
+ t->InsertLinkDirectory(d, mf->GetBacktrace());
}
void CCONV cmAddExecutable(void* arg, const char* exename, int numSrcs,
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index 15fbd40..873372f 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -101,6 +101,7 @@
# include "cmRemoveDefinitionsCommand.h"
# include "cmSourceGroupCommand.h"
# include "cmSubdirDependsCommand.h"
+# include "cmTargetLinkDirectoriesCommand.h"
# include "cmTargetLinkOptionsCommand.h"
# include "cmUseMangledMesaCommand.h"
# include "cmUtilitySourceCommand.h"
@@ -278,6 +279,8 @@ void GetProjectCommands(cmState* state)
state->AddBuiltinCommand("link_libraries", new cmLinkLibrariesCommand);
state->AddBuiltinCommand("target_link_options",
new cmTargetLinkOptionsCommand);
+ state->AddBuiltinCommand("target_link_directories",
+ new cmTargetLinkDirectoriesCommand);
state->AddBuiltinCommand("load_cache", new cmLoadCacheCommand);
state->AddBuiltinCommand("qt_wrap_cpp", new cmQTWrapCPPCommand);
state->AddBuiltinCommand("qt_wrap_ui", new cmQTWrapUICommand);
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index a3e135f..0e48ca8 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -357,10 +357,10 @@ cmComputeLinkInformation::cmComputeLinkInformation(
}
// Add the search path entries requested by the user to path ordering.
- this->OrderLinkerSearchPath->AddUserDirectories(
- this->Target->GetLinkDirectories());
- this->OrderRuntimeSearchPath->AddUserDirectories(
- this->Target->GetLinkDirectories());
+ std::vector<std::string> directories;
+ this->Target->GetLinkDirectories(directories, config, this->LinkLanguage);
+ this->OrderLinkerSearchPath->AddUserDirectories(directories);
+ this->OrderRuntimeSearchPath->AddUserDirectories(directories);
// Set up the implicit link directories.
this->LoadImplicitLinkInfo();
@@ -387,8 +387,7 @@ cmComputeLinkInformation::cmComputeLinkInformation(
if (this->OldLinkDirMode) {
// Construct a mask to not bother with this behavior for link
// directories already specified by the user.
- std::vector<std::string> const& dirs = this->Target->GetLinkDirectories();
- this->OldLinkDirMask.insert(dirs.begin(), dirs.end());
+ this->OldLinkDirMask.insert(directories.begin(), directories.end());
}
this->CMP0060Warn = this->Makefile->PolicyOptionalWarningEnabled(
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index 7f42035..024e641 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -98,6 +98,9 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gte,
cmGeneratorExpression::BuildInterface,
properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_LINK_DIRECTORIES", gte,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_LINK_DEPENDS", gte,
cmGeneratorExpression::BuildInterface,
properties, missingTargets);
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index d6573b8..4cf9dd7 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -451,6 +451,37 @@ void cmExportFileGenerator::PopulateLinkDependsInterface(
}
}
+void cmExportFileGenerator::PopulateLinkDirectoriesInterface(
+ cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
+{
+ cmGeneratorTarget* gt = tei->Target;
+ assert(preprocessRule == cmGeneratorExpression::InstallInterface);
+
+ const char* propName = "INTERFACE_LINK_DIRECTORIES";
+ const char* input = gt->GetProperty(propName);
+
+ if (!input) {
+ return;
+ }
+
+ if (!*input) {
+ properties[propName].clear();
+ return;
+ }
+
+ std::string prepro =
+ cmGeneratorExpression::Preprocess(input, preprocessRule, true);
+ if (!prepro.empty()) {
+ this->ResolveTargetsInGeneratorExpressions(prepro, gt, missingTargets);
+
+ if (!checkInterfaceDirs(prepro, gt, propName)) {
+ return;
+ }
+ properties[propName] = prepro;
+ }
+}
+
void cmExportFileGenerator::PopulateInterfaceProperty(
const std::string& propName, cmGeneratorTarget* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 6ca2e07..41c6538 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -147,6 +147,10 @@ protected:
cmTargetExport* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
+ void PopulateLinkDirectoriesInterface(
+ cmTargetExport* target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap& properties, std::vector<std::string>& missingTargets);
void PopulateLinkDependsInterface(
cmTargetExport* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index bfb7a05..e444087 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -106,6 +106,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", gt,
cmGeneratorExpression::InstallInterface,
properties, missingTargets);
+ this->PopulateLinkDirectoriesInterface(
+ te, cmGeneratorExpression::InstallInterface, properties, missingTargets);
this->PopulateLinkDependsInterface(
te, cmGeneratorExpression::InstallInterface, properties, missingTargets);
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 658e9a7..2727d9a 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -168,7 +168,7 @@ static std::string stripAllGeneratorExpressions(const std::string& input)
const char* c = input.c_str() + pos;
const char* const cStart = c;
for (; *c; ++c) {
- if (c[0] == '$' && c[1] == '<') {
+ if (cmGeneratorExpression::StartsWithGeneratorExpression(c)) {
++nestingLevel;
++c;
continue;
@@ -243,7 +243,7 @@ static std::string stripExportInterface(
const char* c = input.c_str() + pos;
const char* const cStart = c;
for (; *c; ++c) {
- if (c[0] == '$' && c[1] == '<') {
+ if (cmGeneratorExpression::StartsWithGeneratorExpression(c)) {
++nestingLevel;
++c;
continue;
@@ -310,7 +310,7 @@ void cmGeneratorExpression::Split(const std::string& input,
const char* c = input.c_str() + pos;
const char* const cStart = c;
for (; *c; ++c) {
- if (c[0] == '$' && c[1] == '<') {
+ if (cmGeneratorExpression::StartsWithGeneratorExpression(c)) {
++nestingLevel;
++c;
continue;
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index 8176d5c..9c05f60 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -63,6 +63,15 @@ public:
static std::string StripEmptyListElements(const std::string& input);
+ static inline bool StartsWithGeneratorExpression(const std::string& input)
+ {
+ return input.length() >= 2 && input[0] == '$' && input[1] == '<';
+ }
+ static inline bool StartsWithGeneratorExpression(const char* input)
+ {
+ return input != nullptr && input[0] == '$' && input[1] == '<';
+ }
+
private:
cmListFileBacktrace Backtrace;
};
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index 8b1697b..a5134c3 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -28,6 +28,7 @@ class cmGeneratorTarget;
SELECT(F, EvaluatingSources, SOURCES) \
SELECT(F, EvaluatingCompileFeatures, COMPILE_FEATURES) \
SELECT(F, EvaluatingLinkOptions, LINK_OPTIONS) \
+ SELECT(F, EvaluatingLinkDirectories, LINK_DIRECTORIES) \
SELECT(F, EvaluatingLinkDepends, LINK_DEPENDS)
#define CM_FOR_EACH_TRANSITIVE_PROPERTY(F) \
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index a58d3cb..29c6058 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -103,6 +103,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
, DebugCompileFeaturesDone(false)
, DebugCompileDefinitionsDone(false)
, DebugLinkOptionsDone(false)
+ , DebugLinkDirectoriesDone(false)
, DebugSourcesDone(false)
, LinkImplementationLanguageIsContextDependent(true)
, UtilityItemsDone(false)
@@ -133,6 +134,10 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
t->GetLinkOptionsBacktraces(),
this->LinkOptionsEntries);
+ CreatePropertyGeneratorExpressions(t->GetLinkDirectoriesEntries(),
+ t->GetLinkDirectoriesBacktraces(),
+ this->LinkDirectoriesEntries);
+
CreatePropertyGeneratorExpressions(t->GetSourceEntries(),
t->GetSourceBacktraces(),
this->SourceEntries, true);
@@ -150,6 +155,7 @@ cmGeneratorTarget::~cmGeneratorTarget()
cmDeleteAll(this->CompileFeaturesEntries);
cmDeleteAll(this->CompileDefinitionsEntries);
cmDeleteAll(this->LinkOptionsEntries);
+ cmDeleteAll(this->LinkDirectoriesEntries);
cmDeleteAll(this->SourceEntries);
cmDeleteAll(this->LinkInformation);
}
@@ -1704,11 +1710,6 @@ cmListFileBacktrace cmGeneratorTarget::GetBacktrace() const
return this->Target->GetBacktrace();
}
-const std::vector<std::string>& cmGeneratorTarget::GetLinkDirectories() const
-{
- return this->Target->GetLinkDirectories();
-}
-
const std::set<std::string>& cmGeneratorTarget::GetUtilities() const
{
return this->Target->GetUtilities();
@@ -3068,6 +3069,126 @@ void cmGeneratorTarget::GetStaticLibraryLinkOptions(
}
namespace {
+void processLinkDirectories(
+ cmGeneratorTarget const* tgt,
+ const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
+ std::vector<std::string>& directories,
+ std::unordered_set<std::string>& uniqueDirectories,
+ cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
+ bool debugDirectories, std::string const& language)
+{
+ for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) {
+ cmLinkImplItem const& item = entry->LinkImplItem;
+ std::string const& targetName = item.AsStr();
+
+ std::vector<std::string> entryDirectories;
+ cmSystemTools::ExpandListArgument(
+ entry->ge->Evaluate(tgt->GetLocalGenerator(), config, false, tgt,
+ dagChecker, language),
+ entryDirectories);
+
+ std::string usedDirectories;
+ for (std::string& entryDirectory : entryDirectories) {
+ if (!cmSystemTools::FileIsFullPath(entryDirectory)) {
+ std::ostringstream e;
+ bool noMessage = false;
+ cmake::MessageType messageType = cmake::FATAL_ERROR;
+ if (!targetName.empty()) {
+ /* clang-format off */
+ e << "Target \"" << targetName << "\" contains relative "
+ "path in its INTERFACE_LINK_DIRECTORIES:\n"
+ " \"" << entryDirectory << "\"";
+ /* clang-format on */
+ } else {
+ switch (tgt->GetPolicyStatusCMP0081()) {
+ case cmPolicies::WARN: {
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0081) << "\n";
+ messageType = cmake::AUTHOR_WARNING;
+ } break;
+ case cmPolicies::OLD:
+ noMessage = true;
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Issue the fatal message.
+ break;
+ }
+ e << "Found relative path while evaluating link directories of "
+ "\""
+ << tgt->GetName() << "\":\n \"" << entryDirectory << "\"\n";
+ }
+ if (!noMessage) {
+ tgt->GetLocalGenerator()->IssueMessage(messageType, e.str());
+ if (messageType == cmake::FATAL_ERROR) {
+ return;
+ }
+ }
+ }
+
+ // Sanitize the path the same way the link_directories command does
+ // in case projects set the LINK_DIRECTORIES property directly.
+ cmSystemTools::ConvertToUnixSlashes(entryDirectory);
+ if (uniqueDirectories.insert(entryDirectory).second) {
+ directories.push_back(entryDirectory);
+ if (debugDirectories) {
+ usedDirectories += " * " + entryDirectory + "\n";
+ }
+ }
+ }
+ if (!usedDirectories.empty()) {
+ tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
+ cmake::LOG,
+ std::string("Used link directories for target ") + tgt->GetName() +
+ ":\n" + usedDirectories,
+ entry->ge->GetBacktrace());
+ }
+ }
+}
+}
+
+void cmGeneratorTarget::GetLinkDirectories(std::vector<std::string>& result,
+ const std::string& config,
+ const std::string& language) const
+{
+ std::unordered_set<std::string> uniqueDirectories;
+
+ cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DIRECTORIES", nullptr,
+ nullptr);
+
+ std::vector<std::string> debugProperties;
+ const char* debugProp =
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+ if (debugProp) {
+ cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+ }
+
+ bool debugDirectories = !this->DebugLinkDirectoriesDone &&
+ std::find(debugProperties.begin(), debugProperties.end(),
+ "LINK_DIRECTORIES") != debugProperties.end();
+
+ if (this->GlobalGenerator->GetConfigureDoneCMP0026()) {
+ this->DebugLinkDirectoriesDone = true;
+ }
+
+ processLinkDirectories(this, this->LinkDirectoriesEntries, result,
+ uniqueDirectories, &dagChecker, config,
+ debugDirectories, language);
+
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*>
+ linkInterfaceLinkDirectoriesEntries;
+
+ AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES",
+ linkInterfaceLinkDirectoriesEntries);
+
+ processLinkDirectories(this, linkInterfaceLinkDirectoriesEntries, result,
+ uniqueDirectories, &dagChecker, config,
+ debugDirectories, language);
+
+ cmDeleteAll(linkInterfaceLinkDirectoriesEntries);
+}
+
+namespace {
void processLinkDepends(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 9d8c9f5..bfd95ac 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -273,8 +273,6 @@ public:
cmListFileBacktrace GetBacktrace() const;
- const std::vector<std::string>& GetLinkDirectories() const;
-
std::set<std::string> const& GetUtilities() const;
cmListFileBacktrace const* GetUtilityBacktrace(const std::string& u) const;
@@ -435,6 +433,10 @@ public:
const std::string& config,
const std::string& language) const;
+ void GetLinkDirectories(std::vector<std::string>& result,
+ const std::string& config,
+ const std::string& language) const;
+
void GetLinkDepends(std::vector<std::string>& result,
const std::string& config,
const std::string& language) const;
@@ -825,6 +827,7 @@ private:
std::vector<TargetPropertyEntry*> CompileFeaturesEntries;
std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
std::vector<TargetPropertyEntry*> LinkOptionsEntries;
+ std::vector<TargetPropertyEntry*> LinkDirectoriesEntries;
std::vector<TargetPropertyEntry*> SourceEntries;
mutable std::set<std::string> LinkImplicitNullProperties;
@@ -874,6 +877,7 @@ private:
mutable bool DebugCompileFeaturesDone;
mutable bool DebugCompileDefinitionsDone;
mutable bool DebugLinkOptionsDone;
+ mutable bool DebugLinkDirectoriesDone;
mutable bool DebugSourcesDone;
mutable bool LinkImplementationLanguageIsContextDependent;
mutable bool UtilityItemsDone;
diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx
index eaaf64d..caec67d 100644
--- a/Source/cmIncludeDirectoryCommand.cxx
+++ b/Source/cmIncludeDirectoryCommand.cxx
@@ -5,6 +5,7 @@
#include <algorithm>
#include <set>
+#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
@@ -69,11 +70,6 @@ bool cmIncludeDirectoryCommand::InitialPass(
return true;
}
-static bool StartsWithGeneratorExpression(const std::string& input)
-{
- return input[0] == '$' && input[1] == '<';
-}
-
// do a lot of cleanup on the arguments because this is one place where folks
// sometimes take the output of a program and pass it directly into this
// command not thinking that a single argument could be filled with spaces
@@ -124,7 +120,7 @@ void cmIncludeDirectoryCommand::NormalizeInclude(std::string& inc)
cmSystemTools::ConvertToUnixSlashes(inc);
if (!cmSystemTools::FileIsFullPath(inc)) {
- if (!StartsWithGeneratorExpression(inc)) {
+ if (!cmGeneratorExpression::StartsWithGeneratorExpression(inc)) {
std::string tmp = this->Makefile->GetCurrentSourceDirectory();
tmp += "/";
tmp += inc;
diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx
index 1371c53..10425fd 100644
--- a/Source/cmLinkDirectoriesCommand.cxx
+++ b/Source/cmLinkDirectoriesCommand.cxx
@@ -4,6 +4,8 @@
#include <sstream>
+#include "cmAlgorithms.h"
+#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
#include "cmSystemTools.h"
@@ -19,17 +21,34 @@ bool cmLinkDirectoriesCommand::InitialPass(
return true;
}
- for (std::string const& i : args) {
- this->AddLinkDir(i);
+ bool before = this->Makefile->IsOn("CMAKE_LINK_DIRECTORIES_BEFORE");
+
+ auto i = args.cbegin();
+ if ((*i) == "BEFORE") {
+ before = true;
+ ++i;
+ } else if ((*i) == "AFTER") {
+ before = false;
+ ++i;
+ }
+
+ std::vector<std::string> directories;
+ for (; i != args.cend(); ++i) {
+ this->AddLinkDir(*i, directories);
}
+
+ this->Makefile->AddLinkDirectory(cmJoin(directories, ";"), before);
+
return true;
}
-void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir)
+void cmLinkDirectoriesCommand::AddLinkDir(
+ std::string const& dir, std::vector<std::string>& directories)
{
std::string unixPath = dir;
cmSystemTools::ConvertToUnixSlashes(unixPath);
- if (!cmSystemTools::FileIsFullPath(unixPath)) {
+ if (!cmSystemTools::FileIsFullPath(unixPath) &&
+ !cmGeneratorExpression::StartsWithGeneratorExpression(unixPath)) {
bool convertToAbsolute = false;
std::ostringstream e;
/* clang-format off */
@@ -41,6 +60,7 @@ void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir)
case cmPolicies::WARN:
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0015);
this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ break;
case cmPolicies::OLD:
// OLD behavior does not convert
break;
@@ -61,5 +81,5 @@ void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir)
unixPath = tmp;
}
}
- this->Makefile->AppendProperty("LINK_DIRECTORIES", unixPath.c_str());
+ directories.push_back(unixPath);
}
diff --git a/Source/cmLinkDirectoriesCommand.h b/Source/cmLinkDirectoriesCommand.h
index 3fd4e50..ae4fb7f 100644
--- a/Source/cmLinkDirectoriesCommand.h
+++ b/Source/cmLinkDirectoriesCommand.h
@@ -36,7 +36,8 @@ public:
cmExecutionStatus& status) override;
private:
- void AddLinkDir(std::string const& dir);
+ void AddLinkDir(std::string const& dir,
+ std::vector<std::string>& directories);
};
#endif
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 354da4e..8d163b7 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -243,6 +243,17 @@ cmBacktraceRange cmMakefile::GetLinkOptionsBacktraces() const
return this->StateSnapshot.GetDirectory().GetLinkOptionsEntryBacktraces();
}
+cmStringRange cmMakefile::GetLinkDirectoriesEntries() const
+{
+ return this->StateSnapshot.GetDirectory().GetLinkDirectoriesEntries();
+}
+
+cmBacktraceRange cmMakefile::GetLinkDirectoriesBacktraces() const
+{
+ return this->StateSnapshot.GetDirectory()
+ .GetLinkDirectoriesEntryBacktraces();
+}
+
cmListFileBacktrace cmMakefile::GetBacktrace() const
{
return this->Backtrace;
@@ -1237,6 +1248,18 @@ void cmMakefile::AddLinkOption(std::string const& option)
this->AppendProperty("LINK_OPTIONS", option.c_str());
}
+void cmMakefile::AddLinkDirectory(std::string const& directory, bool before)
+{
+ cmListFileBacktrace lfbt = this->GetBacktrace();
+ if (before) {
+ this->StateSnapshot.GetDirectory().PrependLinkDirectoriesEntry(directory,
+ lfbt);
+ } else {
+ this->StateSnapshot.GetDirectory().AppendLinkDirectoriesEntry(directory,
+ lfbt);
+ }
+}
+
bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)
{
// Create a regular expression to match valid definitions.
@@ -1335,10 +1358,6 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent)
// link libraries
this->SetProperty("LINK_LIBRARIES", parent->GetProperty("LINK_LIBRARIES"));
- // link directories
- this->SetProperty("LINK_DIRECTORIES",
- parent->GetProperty("LINK_DIRECTORIES"));
-
// the initial project name
this->StateSnapshot.SetProjectName(parent->StateSnapshot.GetProjectName());
@@ -1872,17 +1891,6 @@ void cmMakefile::AddGlobalLinkInformation(cmTarget& target)
return;
default:;
}
- if (const char* linkDirsProp = this->GetProperty("LINK_DIRECTORIES")) {
- std::vector<std::string> linkDirs;
- cmSystemTools::ExpandListArgument(linkDirsProp, linkDirs);
-
- for (std::string& linkDir : linkDirs) {
- // Sanitize the path the same way the link_directories command does
- // in case projects set the LINK_DIRECTORIES property directly.
- cmSystemTools::ConvertToUnixSlashes(linkDir);
- target.AddLinkDirectory(linkDir);
- }
- }
if (const char* linkLibsProp = this->GetProperty("LINK_LIBRARIES")) {
std::vector<std::string> linkLibs;
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index bb01c0b..b30f281 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -182,6 +182,7 @@ public:
void AddCompileDefinition(std::string const& definition);
void AddCompileOption(std::string const& option);
void AddLinkOption(std::string const& option);
+ void AddLinkDirectory(std::string const& directory, bool before = false);
/** Create a new imported target with the name and type given. */
cmTarget* AddImportedTarget(const std::string& name,
@@ -802,6 +803,8 @@ public:
cmBacktraceRange GetCompileDefinitionsBacktraces() const;
cmStringRange GetLinkOptionsEntries() const;
cmBacktraceRange GetLinkOptionsBacktraces() const;
+ cmStringRange GetLinkDirectoriesEntries() const;
+ cmBacktraceRange GetLinkDirectoriesBacktraces() const;
std::set<std::string> const& GetSystemIncludeDirectories() const
{
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index f99cc0f..a367e47 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -237,7 +237,10 @@ class cmMakefile;
13, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0080, \
"BundleUtilities cannot be included at configure time", 3, 13, 0, \
- cmPolicies::WARN)
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0081, \
+ "Relative paths not allowed in LINK_DIRECTORIES target property.", \
+ 3, 13, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
@@ -263,7 +266,8 @@ class cmMakefile;
F(CMP0068) \
F(CMP0069) \
F(CMP0073) \
- F(CMP0076)
+ F(CMP0076) \
+ F(CMP0081)
/** \class cmPolicies
* \brief Handles changes in CMake behavior and policies
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index c6667f6..4b65cf1 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -284,6 +284,8 @@ cmStateSnapshot cmState::Reset()
it->CompileOptionsBacktraces.clear();
it->LinkOptions.clear();
it->LinkOptionsBacktraces.clear();
+ it->LinkDirectories.clear();
+ it->LinkDirectoriesBacktraces.clear();
it->DirectoryEnd = pos;
it->NormalTargetNames.clear();
it->Properties.clear();
@@ -660,6 +662,7 @@ cmStateSnapshot cmState::CreateBaseSnapshot()
pos->CompileDefinitionsPosition = 0;
pos->CompileOptionsPosition = 0;
pos->LinkOptionsPosition = 0;
+ pos->LinkDirectoriesPosition = 0;
pos->BuildSystemDirectory->DirectoryEnd = pos;
pos->Policies = this->PolicyStack.Root();
pos->PolicyRoot = this->PolicyStack.Root();
@@ -813,6 +816,8 @@ cmStateSnapshot cmState::Pop(cmStateSnapshot const& originSnapshot)
prevPos->BuildSystemDirectory->CompileOptions.size();
prevPos->LinkOptionsPosition =
prevPos->BuildSystemDirectory->LinkOptions.size();
+ prevPos->LinkDirectoriesPosition =
+ prevPos->BuildSystemDirectory->LinkDirectories.size();
prevPos->BuildSystemDirectory->DirectoryEnd = prevPos;
if (!pos->Keep && this->SnapshotData.IsLast(pos)) {
diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx
index 925b161..f94e714 100644
--- a/Source/cmStateDirectory.cxx
+++ b/Source/cmStateDirectory.cxx
@@ -396,6 +396,70 @@ void cmStateDirectory::ClearLinkOptions()
this->Snapshot_.Position->LinkOptionsPosition);
}
+cmStringRange cmStateDirectory::GetLinkDirectoriesEntries() const
+{
+ return GetPropertyContent(this->DirectoryState->LinkDirectories,
+ this->Snapshot_.Position->LinkDirectoriesPosition);
+}
+
+cmBacktraceRange cmStateDirectory::GetLinkDirectoriesEntryBacktraces() const
+{
+ return GetPropertyBacktraces(
+ this->DirectoryState->LinkDirectories,
+ this->DirectoryState->LinkDirectoriesBacktraces,
+ this->Snapshot_.Position->LinkDirectoriesPosition);
+}
+
+void cmStateDirectory::AppendLinkDirectoriesEntry(
+ const std::string& vec, const cmListFileBacktrace& lfbt)
+{
+ AppendEntry(this->DirectoryState->LinkDirectories,
+ this->DirectoryState->LinkDirectoriesBacktraces,
+ this->Snapshot_.Position->LinkDirectoriesPosition, vec, lfbt);
+}
+void cmStateDirectory::PrependLinkDirectoriesEntry(
+ const std::string& vec, const cmListFileBacktrace& lfbt)
+{
+ std::vector<std::string>::iterator entryEnd =
+ this->DirectoryState->LinkDirectories.begin() +
+ this->Snapshot_.Position->LinkDirectoriesPosition;
+
+ std::vector<std::string>::reverse_iterator rend =
+ this->DirectoryState->LinkDirectories.rend();
+ std::vector<std::string>::reverse_iterator rbegin =
+ cmMakeReverseIterator(entryEnd);
+ rbegin = std::find(rbegin, rend, cmPropertySentinal);
+
+ std::vector<std::string>::iterator entryIt = rbegin.base();
+ std::vector<std::string>::iterator entryBegin =
+ this->DirectoryState->LinkDirectories.begin();
+
+ std::vector<cmListFileBacktrace>::iterator btIt =
+ this->DirectoryState->LinkDirectoriesBacktraces.begin() +
+ std::distance(entryBegin, entryIt);
+
+ this->DirectoryState->LinkDirectories.insert(entryIt, vec);
+ this->DirectoryState->LinkDirectoriesBacktraces.insert(btIt, lfbt);
+
+ this->Snapshot_.Position->LinkDirectoriesPosition =
+ this->DirectoryState->LinkDirectories.size();
+}
+
+void cmStateDirectory::SetLinkDirectories(const std::string& vec,
+ const cmListFileBacktrace& lfbt)
+{
+ SetContent(this->DirectoryState->LinkDirectories,
+ this->DirectoryState->LinkDirectoriesBacktraces,
+ this->Snapshot_.Position->LinkDirectoriesPosition, vec, lfbt);
+}
+
+void cmStateDirectory::ClearLinkDirectories()
+{
+ ClearContent(this->DirectoryState->LinkDirectories,
+ this->DirectoryState->LinkDirectoriesBacktraces,
+ this->Snapshot_.Position->LinkDirectoriesPosition);
+}
+
void cmStateDirectory::SetProperty(const std::string& prop, const char* value,
cmListFileBacktrace const& lfbt)
{
@@ -431,6 +495,14 @@ void cmStateDirectory::SetProperty(const std::string& prop, const char* value,
this->SetLinkOptions(value, lfbt);
return;
}
+ if (prop == "LINK_DIRECTORIES") {
+ if (!value) {
+ this->ClearLinkDirectories();
+ return;
+ }
+ this->SetLinkDirectories(value, lfbt);
+ return;
+ }
this->DirectoryState->Properties.SetProperty(prop, value);
}
@@ -455,6 +527,10 @@ void cmStateDirectory::AppendProperty(const std::string& prop,
this->AppendLinkOptionsEntry(value, lfbt);
return;
}
+ if (prop == "LINK_DIRECTORIES") {
+ this->AppendLinkDirectoriesEntry(value, lfbt);
+ return;
+ }
this->DirectoryState->Properties.AppendProperty(prop, value, asString);
}
@@ -542,6 +618,10 @@ const char* cmStateDirectory::GetProperty(const std::string& prop,
output = cmJoin(this->GetLinkOptionsEntries(), ";");
return output.c_str();
}
+ if (prop == "LINK_DIRECTORIES") {
+ output = cmJoin(this->GetLinkDirectoriesEntries(), ";");
+ return output.c_str();
+ }
const char* retVal = this->DirectoryState->Properties.GetPropertyValue(prop);
if (!retVal && chain) {
diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h
index 412664f..e5f4d05 100644
--- a/Source/cmStateDirectory.h
+++ b/Source/cmStateDirectory.h
@@ -62,9 +62,19 @@ public:
cmBacktraceRange GetLinkOptionsEntryBacktraces() const;
void AppendLinkOptionsEntry(std::string const& vec,
cmListFileBacktrace const& lfbt);
+ void PrependLinkDirectoriesEntry(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
void SetLinkOptions(std::string const& vec, cmListFileBacktrace const& lfbt);
void ClearLinkOptions();
+ cmStringRange GetLinkDirectoriesEntries() const;
+ cmBacktraceRange GetLinkDirectoriesEntryBacktraces() const;
+ void AppendLinkDirectoriesEntry(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
+ void SetLinkDirectories(std::string const& vec,
+ cmListFileBacktrace const& lfbt);
+ void ClearLinkDirectories();
+
void SetProperty(const std::string& prop, const char* value,
cmListFileBacktrace const& lfbt);
void AppendProperty(const std::string& prop, const char* value,
diff --git a/Source/cmStatePrivate.h b/Source/cmStatePrivate.h
index 7177221..e76f2af 100644
--- a/Source/cmStatePrivate.h
+++ b/Source/cmStatePrivate.h
@@ -43,6 +43,7 @@ struct cmStateDetail::SnapshotDataType
std::vector<std::string>::size_type CompileDefinitionsPosition;
std::vector<std::string>::size_type CompileOptionsPosition;
std::vector<std::string>::size_type LinkOptionsPosition;
+ std::vector<std::string>::size_type LinkDirectoriesPosition;
};
struct cmStateDetail::PolicyStackEntry : public cmPolicies::PolicyMap
@@ -88,6 +89,9 @@ struct cmStateDetail::BuildsystemDirectoryStateType
std::vector<std::string> LinkOptions;
std::vector<cmListFileBacktrace> LinkOptionsBacktraces;
+ std::vector<std::string> LinkDirectories;
+ std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces;
+
std::vector<std::string> NormalTargetNames;
std::string ProjectName;
diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx
index 0379e7e..c2510f3 100644
--- a/Source/cmStateSnapshot.cxx
+++ b/Source/cmStateSnapshot.cxx
@@ -398,6 +398,13 @@ void cmStateSnapshot::InitializeFromParent()
this->Position->BuildSystemDirectory->LinkOptionsBacktraces,
this->Position->LinkOptionsPosition);
+ InitializeContentFromParent(
+ parent->BuildSystemDirectory->LinkDirectories,
+ this->Position->BuildSystemDirectory->LinkDirectories,
+ parent->BuildSystemDirectory->LinkDirectoriesBacktraces,
+ this->Position->BuildSystemDirectory->LinkDirectoriesBacktraces,
+ this->Position->LinkDirectoriesPosition);
+
const char* include_regex =
parent->BuildSystemDirectory->Properties.GetPropertyValue(
"INCLUDE_REGULAR_EXPRESSION");
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 4e353c7..c5295f2 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -168,6 +168,8 @@ public:
std::vector<cmListFileBacktrace> SourceBacktraces;
std::vector<std::string> LinkOptionsEntries;
std::vector<cmListFileBacktrace> LinkOptionsBacktraces;
+ std::vector<std::string> LinkDirectoriesEntries;
+ std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces;
std::vector<std::string> LinkImplementationPropertyEntries;
std::vector<cmListFileBacktrace> LinkImplementationPropertyBacktraces;
};
@@ -391,6 +393,18 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
this->Internal->LinkOptionsBacktraces.insert(
this->Internal->LinkOptionsBacktraces.end(),
parentLinkOptionsBts.begin(), parentLinkOptionsBts.end());
+
+ const cmStringRange parentLinkDirectories =
+ this->Makefile->GetLinkDirectoriesEntries();
+ const cmBacktraceRange parentLinkDirectoriesBts =
+ this->Makefile->GetLinkDirectoriesBacktraces();
+
+ this->Internal->LinkDirectoriesEntries.insert(
+ this->Internal->LinkDirectoriesEntries.end(),
+ parentLinkDirectories.begin(), parentLinkDirectories.end());
+ this->Internal->LinkDirectoriesBacktraces.insert(
+ this->Internal->LinkDirectoriesBacktraces.end(),
+ parentLinkDirectoriesBts.begin(), parentLinkDirectoriesBts.end());
}
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
@@ -514,9 +528,7 @@ void cmTarget::AddSources(std::vector<std::string> const& srcs)
std::string srcFiles;
const char* sep = "";
for (auto filename : srcs) {
- const char* src = filename.c_str();
-
- if (!(src[0] == '$' && src[1] == '<')) {
+ if (!cmGeneratorExpression::StartsWithGeneratorExpression(filename)) {
if (!filename.empty()) {
filename = this->ProcessSourceItemCMP0049(filename);
if (filename.empty()) {
@@ -656,19 +668,6 @@ cmSourceFile* cmTarget::AddSource(const std::string& src)
cmSourceFileLocationKind::Known);
}
-void cmTarget::AddLinkDirectory(const std::string& d)
-{
- // Make sure we don't add unnecessary search directories.
- if (this->LinkDirectoriesEmmitted.insert(d).second) {
- this->LinkDirectories.push_back(d);
- }
-}
-
-const std::vector<std::string>& cmTarget::GetLinkDirectories() const
-{
- return this->LinkDirectories;
-}
-
void cmTarget::ClearDependencyInformation(cmMakefile& mf)
{
std::string depname = this->GetName();
@@ -876,6 +875,16 @@ cmBacktraceRange cmTarget::GetLinkOptionsBacktraces() const
return cmMakeRange(this->Internal->LinkOptionsBacktraces);
}
+cmStringRange cmTarget::GetLinkDirectoriesEntries() const
+{
+ return cmMakeRange(this->Internal->LinkDirectoriesEntries);
+}
+
+cmBacktraceRange cmTarget::GetLinkDirectoriesBacktraces() const
+{
+ return cmMakeRange(this->Internal->LinkDirectoriesBacktraces);
+}
+
cmStringRange cmTarget::GetLinkImplementationEntries() const
{
return cmMakeRange(this->Internal->LinkImplementationPropertyEntries);
@@ -902,6 +911,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
MAKE_STATIC_PROP(IMPORTED_GLOBAL);
MAKE_STATIC_PROP(INCLUDE_DIRECTORIES);
MAKE_STATIC_PROP(LINK_OPTIONS);
+ MAKE_STATIC_PROP(LINK_DIRECTORIES);
MAKE_STATIC_PROP(LINK_LIBRARIES);
MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES);
MAKE_STATIC_PROP(NAME);
@@ -988,6 +998,14 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
this->Internal->LinkOptionsBacktraces.push_back(lfbt);
}
+ } else if (prop == propLINK_DIRECTORIES) {
+ this->Internal->LinkDirectoriesEntries.clear();
+ this->Internal->LinkDirectoriesBacktraces.clear();
+ if (value) {
+ this->Internal->LinkDirectoriesEntries.push_back(value);
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ this->Internal->LinkDirectoriesBacktraces.push_back(lfbt);
+ }
} else if (prop == propLINK_LIBRARIES) {
this->Internal->LinkImplementationPropertyEntries.clear();
this->Internal->LinkImplementationPropertyBacktraces.clear();
@@ -1099,6 +1117,12 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value,
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
this->Internal->LinkOptionsBacktraces.push_back(lfbt);
}
+ } else if (prop == "LINK_DIRECTORIES") {
+ if (value && *value) {
+ this->Internal->LinkDirectoriesEntries.push_back(value);
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+ this->Internal->LinkDirectoriesBacktraces.push_back(lfbt);
+ }
} else if (prop == "LINK_LIBRARIES") {
if (value && *value) {
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
@@ -1196,6 +1220,21 @@ void cmTarget::InsertLinkOption(std::string const& entry,
this->Internal->LinkOptionsBacktraces.insert(btPosition, bt);
}
+void cmTarget::InsertLinkDirectory(std::string const& entry,
+ cmListFileBacktrace const& bt, bool before)
+{
+ std::vector<std::string>::iterator position = before
+ ? this->Internal->LinkDirectoriesEntries.begin()
+ : this->Internal->LinkDirectoriesEntries.end();
+
+ std::vector<cmListFileBacktrace>::iterator btPosition = before
+ ? this->Internal->LinkDirectoriesBacktraces.begin()
+ : this->Internal->LinkDirectoriesBacktraces.end();
+
+ this->Internal->LinkDirectoriesEntries.insert(position, entry);
+ this->Internal->LinkDirectoriesBacktraces.insert(btPosition, bt);
+}
+
static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop,
const char* value,
cmMakefile* context,
@@ -1316,6 +1355,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const
MAKE_STATIC_PROP(COMPILE_OPTIONS);
MAKE_STATIC_PROP(COMPILE_DEFINITIONS);
MAKE_STATIC_PROP(LINK_OPTIONS);
+ MAKE_STATIC_PROP(LINK_DIRECTORIES);
MAKE_STATIC_PROP(IMPORTED);
MAKE_STATIC_PROP(IMPORTED_GLOBAL);
MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES);
@@ -1332,6 +1372,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const
specialProps.insert(propCOMPILE_OPTIONS);
specialProps.insert(propCOMPILE_DEFINITIONS);
specialProps.insert(propLINK_OPTIONS);
+ specialProps.insert(propLINK_DIRECTORIES);
specialProps.insert(propIMPORTED);
specialProps.insert(propIMPORTED_GLOBAL);
specialProps.insert(propMANUALLY_ADDED_DEPENDENCIES);
@@ -1399,6 +1440,16 @@ const char* cmTarget::GetProperty(const std::string& prop) const
output = cmJoin(this->Internal->LinkOptionsEntries, ";");
return output.c_str();
}
+ if (prop == propLINK_DIRECTORIES) {
+ if (this->Internal->LinkDirectoriesEntries.empty()) {
+ return nullptr;
+ }
+
+ static std::string output;
+ output = cmJoin(this->Internal->LinkDirectoriesEntries, ";");
+
+ return output.c_str();
+ }
if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
if (this->Utilities.empty()) {
return nullptr;
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 1f380df..694de1c 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -154,10 +154,6 @@ public:
cmListFileContext const& lfc);
void GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const;
- const std::vector<std::string>& GetLinkDirectories() const;
-
- void AddLinkDirectory(const std::string& d);
-
/**
* Set the path where this target should be installed. This is relative to
* INSTALL_PREFIX
@@ -247,6 +243,8 @@ public:
cmListFileBacktrace const& bt);
void InsertLinkOption(std::string const& entry,
cmListFileBacktrace const& bt, bool before = false);
+ void InsertLinkDirectory(std::string const& entry,
+ cmListFileBacktrace const& bt, bool before = false);
void AppendBuildInterfaceIncludes();
@@ -277,6 +275,9 @@ public:
cmStringRange GetLinkOptionsEntries() const;
cmBacktraceRange GetLinkOptionsBacktraces() const;
+ cmStringRange GetLinkDirectoriesEntries() const;
+ cmBacktraceRange GetLinkDirectoriesBacktraces() const;
+
cmStringRange GetLinkImplementationEntries() const;
cmBacktraceRange GetLinkImplementationBacktraces() const;
@@ -306,14 +307,12 @@ private:
bool IsGeneratorProvided;
cmPropertyMap Properties;
std::set<std::string> SystemIncludeDirectories;
- std::set<std::string> LinkDirectoriesEmmitted;
std::set<std::string> Utilities;
std::map<std::string, cmListFileBacktrace> UtilityBacktraces;
cmPolicies::PolicyMap PolicyMap;
std::string Name;
std::string InstallPath;
std::string RuntimeInstallPath;
- std::vector<std::string> LinkDirectories;
std::vector<cmCustomCommand> PreBuildCommands;
std::vector<cmCustomCommand> PreLinkCommands;
std::vector<cmCustomCommand> PostBuildCommands;
diff --git a/Source/cmTargetLinkDirectoriesCommand.cxx b/Source/cmTargetLinkDirectoriesCommand.cxx
new file mode 100644
index 0000000..bca3e45
--- /dev/null
+++ b/Source/cmTargetLinkDirectoriesCommand.cxx
@@ -0,0 +1,61 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmTargetLinkDirectoriesCommand.h"
+
+#include <sstream>
+
+#include "cmAlgorithms.h"
+#include "cmGeneratorExpression.h"
+#include "cmListFileCache.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmake.h"
+
+class cmExecutionStatus;
+
+bool cmTargetLinkDirectoriesCommand::InitialPass(
+ std::vector<std::string> const& args, cmExecutionStatus&)
+{
+ return this->HandleArguments(args, "LINK_DIRECTORIES", PROCESS_BEFORE);
+}
+
+void cmTargetLinkDirectoriesCommand::HandleMissingTarget(
+ const std::string& name)
+{
+ std::ostringstream e;
+ e << "Cannot specify link directories for target \"" << name
+ << "\" which is not built by this project.";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+std::string cmTargetLinkDirectoriesCommand::Join(
+ const std::vector<std::string>& content)
+{
+ std::vector<std::string> directories;
+
+ for (const auto& dir : content) {
+ auto unixPath = dir;
+ cmSystemTools::ConvertToUnixSlashes(unixPath);
+ if (!cmSystemTools::FileIsFullPath(unixPath) &&
+ !cmGeneratorExpression::StartsWithGeneratorExpression(unixPath)) {
+ auto tmp = this->Makefile->GetCurrentSourceDirectory();
+ tmp += "/";
+ tmp += unixPath;
+ unixPath = tmp;
+ }
+ directories.push_back(unixPath);
+ }
+
+ return cmJoin(directories, ";");
+}
+
+bool cmTargetLinkDirectoriesCommand::HandleDirectContent(
+ cmTarget* tgt, const std::vector<std::string>& content, bool prepend, bool)
+{
+ cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
+
+ tgt->InsertLinkDirectory(this->Join(content), lfbt, prepend);
+
+ return true; // Successfully handled.
+}
diff --git a/Source/cmTargetLinkDirectoriesCommand.h b/Source/cmTargetLinkDirectoriesCommand.h
new file mode 100644
index 0000000..52c75a0
--- /dev/null
+++ b/Source/cmTargetLinkDirectoriesCommand.h
@@ -0,0 +1,41 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmTargetLinkDirectoriesCommand_h
+#define cmTargetLinkDirectoriesCommand_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <string>
+#include <vector>
+
+#include "cmTargetPropCommandBase.h"
+
+class cmCommand;
+class cmExecutionStatus;
+class cmTarget;
+
+class cmTargetLinkDirectoriesCommand : public cmTargetPropCommandBase
+{
+public:
+ /**
+ * This is a virtual constructor for the command.
+ */
+ cmCommand* Clone() override { return new cmTargetLinkDirectoriesCommand; }
+
+ /**
+ * This is called when the command is first encountered in
+ * the CMakeLists.txt file.
+ */
+ bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus& status) override;
+
+private:
+ void HandleMissingTarget(const std::string& name) override;
+
+ std::string Join(const std::vector<std::string>& content) override;
+ bool HandleDirectContent(cmTarget* tgt,
+ const std::vector<std::string>& content,
+ bool prepend, bool system) override;
+};
+
+#endif