LINK_DIRECTORIES: Add new properties and commands
These new capabilities enable to manage link directories Two new properties: * target properties: LINK_DIRECTORIES and INTERFACE_LINK_DIRECTORIES One new command * target_link_directories(): to populate target properties Fixes: #17215
This commit is contained in:
parent
5ca130e223
commit
a71caab46b
@ -1,19 +1,45 @@
|
||||
link_directories
|
||||
----------------
|
||||
|
||||
Specify directories in which the linker will look for libraries.
|
||||
Add directories in which the linker will look for libraries.
|
||||
|
||||
::
|
||||
|
||||
link_directories(directory1 directory2 ...)
|
||||
link_directories(directory1 [directory2 ...])
|
||||
|
||||
Specify the paths in which the linker should search for libraries.
|
||||
The command will apply only to targets created after it is called.
|
||||
Add the paths in which the linker should search for libraries.
|
||||
Relative paths given to this command are interpreted as relative to
|
||||
the current source directory, see :policy:`CMP0015`.
|
||||
|
||||
Note that this command is rarely necessary. Library locations
|
||||
returned by :command:`find_package` and :command:`find_library` are
|
||||
absolute paths. Pass these absolute library file paths directly to the
|
||||
:command:`target_link_libraries` command. CMake will ensure the linker finds
|
||||
them.
|
||||
The directories are added to the :prop_dir:`LINK_DIRECTORIES` directory
|
||||
property for the current ``CMakeLists.txt`` file, converting relative
|
||||
paths to absolute as needed.
|
||||
The command will apply only to targets created after it is called.
|
||||
|
||||
Arguments to ``link_directories`` may use "generator expressions" with
|
||||
the syntax "$<...>". See the :manual:`cmake-generator-expressions(7)`
|
||||
manual for available expressions. See the :manual:`cmake-buildsystem(7)`
|
||||
manual for more on defining buildsystem properties.
|
||||
|
||||
.. note::
|
||||
|
||||
This command is rarely necessary and should be avoided where there are
|
||||
other choices. Prefer to pass full absolute paths to libraries where
|
||||
possible, since this ensures the correct library will always be linked.
|
||||
The :command:`find_library` command provides the full path, which can
|
||||
generally be used directly in calls to :command:`target_link_libraries`.
|
||||
Situations where a library search path may be needed include:
|
||||
|
||||
- Project generators like Xcode where the user can switch target
|
||||
architecture at build time, but a full path to a library cannot
|
||||
be used because it only provides one architecture (i.e. it is not
|
||||
a universal binary).
|
||||
- Libraries may themselves have other private library dependencies
|
||||
that expect to be found via ``RPATH`` mechanisms, but some linkers
|
||||
are not able to fully decode those paths (e.g. due to the presence
|
||||
of things like ``$ORIGIN``).
|
||||
|
||||
If a library search path must be provided, prefer to localize the effect
|
||||
where possible by using the :command:`target_link_directories` command
|
||||
rather than ``link_directories()``. The target-specific command can also
|
||||
control how the search directories propagate to other dependent targets.
|
||||
|
55
Help/command/target_link_directories.rst
Normal file
55
Help/command/target_link_directories.rst
Normal file
@ -0,0 +1,55 @@
|
||||
target_link_directories
|
||||
-----------------------
|
||||
|
||||
Add link directories to a target.
|
||||
|
||||
::
|
||||
|
||||
target_link_directories(<target> [BEFORE]
|
||||
<INTERFACE|PUBLIC|PRIVATE> [items1...]
|
||||
[<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
|
||||
|
||||
Specify the paths in which the linker should search for libraries when
|
||||
linking a given target. Each item can be an absolute or relative path,
|
||||
with the latter being interpreted as relative to the current source
|
||||
directory. These items will be added to the link command.
|
||||
|
||||
The named ``<target>`` must have been created by a command such as
|
||||
:command:`add_executable` or :command:`add_library` and must not be an
|
||||
:ref:`ALIAS target <Alias Targets>`.
|
||||
|
||||
The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
|
||||
specify the scope of the items that follow them. ``PRIVATE`` and
|
||||
``PUBLIC`` items will populate the :prop_tgt:`LINK_DIRECTORIES` property
|
||||
of ``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
|
||||
:prop_tgt:`INTERFACE_LINK_DIRECTORIES` property of ``<target>``
|
||||
(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items).
|
||||
Each item specifies a link directory and will be converted to an absolute
|
||||
path if necessary before adding it to the relevant property. Repeated
|
||||
calls for the same ``<target>`` append items in the order called.
|
||||
|
||||
If ``BEFORE`` is specified, the content will be prepended to the relevant
|
||||
property instead of being appended.
|
||||
|
||||
Arguments to ``target_link_directories`` may use "generator expressions"
|
||||
with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
|
||||
manual for available expressions. See the :manual:`cmake-buildsystem(7)`
|
||||
manual for more on defining buildsystem properties.
|
||||
|
||||
.. note::
|
||||
|
||||
This command is rarely necessary and should be avoided where there are
|
||||
other choices. Prefer to pass full absolute paths to libraries where
|
||||
possible, since this ensures the correct library will always be linked.
|
||||
The :command:`find_library` command provides the full path, which can
|
||||
generally be used directly in calls to :command:`target_link_libraries`.
|
||||
Situations where a library search path may be needed include:
|
||||
|
||||
- Project generators like Xcode where the user can switch target
|
||||
architecture at build time, but a full path to a library cannot
|
||||
be used because it only provides one architecture (i.e. it is not
|
||||
a universal binary).
|
||||
- Libraries may themselves have other private library dependencies
|
||||
that expect to be found via ``RPATH`` mechanisms, but some linkers
|
||||
are not able to fully decode those paths (e.g. due to the presence
|
||||
of things like ``$ORIGIN``).
|
@ -111,6 +111,7 @@ These commands are available only in CMake projects.
|
||||
/command/target_compile_features
|
||||
/command/target_compile_options
|
||||
/command/target_include_directories
|
||||
/command/target_link_directories
|
||||
/command/target_link_libraries
|
||||
/command/target_link_options
|
||||
/command/target_sources
|
||||
|
@ -228,6 +228,7 @@ Properties on Targets
|
||||
/prop_tgt/INTERFACE_COMPILE_OPTIONS
|
||||
/prop_tgt/INTERFACE_INCLUDE_DIRECTORIES
|
||||
/prop_tgt/INTERFACE_LINK_DEPENDS
|
||||
/prop_tgt/INTERFACE_LINK_DIRECTORIES
|
||||
/prop_tgt/INTERFACE_LINK_LIBRARIES
|
||||
/prop_tgt/INTERFACE_LINK_OPTIONS
|
||||
/prop_tgt/INTERFACE_POSITION_INDEPENDENT_CODE
|
||||
@ -252,6 +253,7 @@ Properties on Targets
|
||||
/prop_tgt/LINK_DEPENDS_NO_SHARED
|
||||
/prop_tgt/LINK_DEPENDS
|
||||
/prop_tgt/LINKER_LANGUAGE
|
||||
/prop_tgt/LINK_DIRECTORIES
|
||||
/prop_tgt/LINK_FLAGS_CONFIG
|
||||
/prop_tgt/LINK_FLAGS
|
||||
/prop_tgt/LINK_INTERFACE_LIBRARIES_CONFIG
|
||||
|
@ -3,6 +3,15 @@ LINK_DIRECTORIES
|
||||
|
||||
List of linker search directories.
|
||||
|
||||
This read-only property specifies the list of directories given so far
|
||||
to the link_directories command. It is intended for debugging
|
||||
purposes.
|
||||
This property holds a :ref:`;-list <CMake Language Lists>` of directories
|
||||
and is typically populated using the :command:`link_directories` command.
|
||||
It gets its initial value from its parent directory, if it has one.
|
||||
|
||||
The directory property is used to initialize the :prop_tgt:`LINK_DIRECTORIES`
|
||||
target property when a target is created. That target property is used
|
||||
by the generators to set the library search directories for the linker.
|
||||
|
||||
Contents of ``LINK_DIRECTORIES`` may use "generator expressions" with
|
||||
the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
|
||||
manual for available expressions. See the :manual:`cmake-buildsystem(7)`
|
||||
manual for more on defining buildsystem properties.
|
||||
|
9
Help/prop_tgt/INTERFACE_LINK_DIRECTORIES.rst
Normal file
9
Help/prop_tgt/INTERFACE_LINK_DIRECTORIES.rst
Normal file
@ -0,0 +1,9 @@
|
||||
INTERFACE_LINK_DIRECTORIES
|
||||
--------------------------
|
||||
|
||||
.. |property_name| replace:: link directories
|
||||
.. |command_name| replace:: :command:`target_link_directories`
|
||||
.. |PROPERTY_INTERFACE_NAME| replace:: ``INTERFACE_LINK_DIRECTORIES``
|
||||
.. |PROPERTY_LINK| replace:: :prop_tgt:`LINK_DIRECTORIES`
|
||||
.. |PROPERTY_GENEX| replace:: ``$<TARGET_PROPERTY:foo,INTERFACE_LINK_DIRECTORIES>``
|
||||
.. include:: INTERFACE_BUILD_PROPERTY.txt
|
18
Help/prop_tgt/LINK_DIRECTORIES.rst
Normal file
18
Help/prop_tgt/LINK_DIRECTORIES.rst
Normal file
@ -0,0 +1,18 @@
|
||||
LINK_DIRECTORIES
|
||||
----------------
|
||||
|
||||
List of directories to use for the link step of shared library, module
|
||||
and executable targets.
|
||||
|
||||
This property holds a :ref:`;-list <CMake Language Lists>` of directories
|
||||
specified so far for its target. Use the :command:`target_link_directories`
|
||||
command to append more search directories.
|
||||
|
||||
This property is initialized by the :prop_dir:`LINK_DIRECTORIES` directory
|
||||
property when a target is created, and is used by the generators to set
|
||||
the search directories for the linker.
|
||||
|
||||
Contents of ``LINK_DIRECTORIES`` may use "generator expressions" with the
|
||||
syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual
|
||||
for available expressions. See the :manual:`cmake-buildsystem(7)` manual
|
||||
for more on defining buildsystem properties.
|
9
Help/release/dev/LINK_DIRECTORIES.rst
Normal file
9
Help/release/dev/LINK_DIRECTORIES.rst
Normal file
@ -0,0 +1,9 @@
|
||||
LINK_DIRECTORIES
|
||||
----------------
|
||||
|
||||
* CMake gained new capabilities to manage link directories:
|
||||
|
||||
* :prop_tgt:`LINK_DIRECTORIES` and :prop_tgt:`INTERFACE_LINK_DIRECTORIES`
|
||||
target properties.
|
||||
* :command:`target_link_directories` command to add link directories to
|
||||
targets.
|
@ -579,6 +579,8 @@ set(SRCS
|
||||
cmTargetIncludeDirectoriesCommand.h
|
||||
cmTargetLinkOptionsCommand.cxx
|
||||
cmTargetLinkOptionsCommand.h
|
||||
cmTargetLinkDirectoriesCommand.cxx
|
||||
cmTargetLinkDirectoriesCommand.h
|
||||
cmTargetLinkLibrariesCommand.cxx
|
||||
cmTargetLinkLibrariesCommand.h
|
||||
cmTargetPropCommandBase.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,
|
||||
|
@ -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);
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) \
|
||||
|
@ -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();
|
||||
@ -3067,6 +3068,102 @@ void cmGeneratorTarget::GetStaticLibraryLinkOptions(
|
||||
cmDeleteAll(entries);
|
||||
}
|
||||
|
||||
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;
|
||||
if (!targetName.empty()) {
|
||||
/* clang-format off */
|
||||
e << "Target \"" << targetName << "\" contains relative "
|
||||
"path in its INTERFACE_LINK_DIRECTORIES:\n"
|
||||
" \"" << entryDirectory << "\"";
|
||||
/* clang-format on */
|
||||
tgt->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, e.str());
|
||||
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,
|
||||
|
@ -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;
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmPolicies.h"
|
||||
#include "cmSystemTools.h"
|
||||
@ -29,7 +30,8 @@ void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir)
|
||||
{
|
||||
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 +43,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 +64,5 @@ void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir)
|
||||
unixPath = tmp;
|
||||
}
|
||||
}
|
||||
this->Makefile->AppendProperty("LINK_DIRECTORIES", unixPath.c_str());
|
||||
this->Makefile->AddLinkDirectory(unixPath);
|
||||
}
|
||||
|
@ -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,11 @@ void cmMakefile::AddLinkOption(std::string const& option)
|
||||
this->AppendProperty("LINK_OPTIONS", option.c_str());
|
||||
}
|
||||
|
||||
void cmMakefile::AddLinkDirectory(std::string const& directory)
|
||||
{
|
||||
this->AppendProperty("LINK_DIRECTORIES", directory.c_str());
|
||||
}
|
||||
|
||||
bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)
|
||||
{
|
||||
// Create a regular expression to match valid definitions.
|
||||
@ -1335,10 +1351,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 +1884,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;
|
||||
|
@ -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);
|
||||
|
||||
/** 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
|
||||
{
|
||||
|
@ -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)) {
|
||||
|
@ -396,6 +396,43 @@ 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::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 +468,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 +500,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 +591,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) {
|
||||
|
@ -65,6 +65,14 @@ public:
|
||||
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,
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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 &&
|
||||
@ -654,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();
|
||||
@ -874,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);
|
||||
@ -900,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);
|
||||
@ -986,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();
|
||||
@ -1097,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();
|
||||
@ -1194,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,
|
||||
@ -1314,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);
|
||||
@ -1330,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);
|
||||
@ -1397,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;
|
||||
|
@ -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;
|
||||
|
61
Source/cmTargetLinkDirectoriesCommand.cxx
Normal file
61
Source/cmTargetLinkDirectoriesCommand.cxx
Normal file
@ -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.
|
||||
}
|
41
Source/cmTargetLinkDirectoriesCommand.h
Normal file
41
Source/cmTargetLinkDirectoriesCommand.h
Normal file
@ -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
|
40
Tests/CMakeCommands/target_link_directories/CMakeLists.txt
Normal file
40
Tests/CMakeCommands/target_link_directories/CMakeLists.txt
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
project(target_link_directories LANGUAGES C)
|
||||
|
||||
add_library(target_link_directories SHARED LinkDirectoriesLib.c)
|
||||
# Test no items
|
||||
target_link_directories(target_link_directories PRIVATE)
|
||||
|
||||
add_library(target_link_directories_2 SHARED EXCLUDE_FROM_ALL LinkDirectoriesLib.c)
|
||||
target_link_directories(target_link_directories_2 PRIVATE /private/dir INTERFACE /interface/dir)
|
||||
get_target_property(result target_link_directories_2 LINK_DIRECTORIES)
|
||||
if (NOT result MATCHES "/private/dir")
|
||||
message(SEND_ERROR "${result} target_link_directories not populated the LINK_DIRECTORIES target property")
|
||||
endif()
|
||||
get_target_property(result target_link_directories_2 INTERFACE_LINK_DIRECTORIES)
|
||||
if (NOT result MATCHES "/interface/dir")
|
||||
message(SEND_ERROR "target_link_directories not populated the INTERFACE_LINK_DIRECTORIES target property of shared library")
|
||||
endif()
|
||||
|
||||
add_library(target_link_directories_3 STATIC EXCLUDE_FROM_ALL LinkDirectoriesLib.c)
|
||||
target_link_directories(target_link_directories_3 INTERFACE /interface/dir)
|
||||
get_target_property(result target_link_directories_3 INTERFACE_LINK_DIRECTORIES)
|
||||
if (NOT result MATCHES "/interface/dir")
|
||||
message(SEND_ERROR "target_link_directories not populated the INTERFACE_LINK_DIRECTORIES target property of static library")
|
||||
endif()
|
||||
|
||||
add_library(target_link_directories_4 SHARED EXCLUDE_FROM_ALL LinkDirectoriesLib.c)
|
||||
target_link_directories(target_link_directories_4 PRIVATE relative/dir)
|
||||
get_target_property(result target_link_directories_4 LINK_DIRECTORIES)
|
||||
if (NOT result MATCHES "${CMAKE_CURRENT_SOURCE_DIR}/relative/dir")
|
||||
message(SEND_ERROR "target_link_directories not populated the LINK_DIRECTORIES with relative path")
|
||||
endif()
|
||||
|
||||
add_subdirectory(subdir)
|
||||
target_link_directories(target_link_directories_5 PRIVATE relative/dir)
|
||||
get_target_property(result target_link_directories_5 LINK_DIRECTORIES)
|
||||
if (NOT result MATCHES "${CMAKE_CURRENT_SOURCE_DIR}/relative/dir")
|
||||
message(SEND_ERROR "target_link_directories not populated the LINK_DIRECTORIES with relative path")
|
||||
endif()
|
@ -0,0 +1,7 @@
|
||||
#if defined(_WIN32)
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int flags_lib(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
|
||||
add_library(target_link_directories_5 SHARED EXCLUDE_FROM_ALL ../LinkDirectoriesLib.c)
|
@ -2823,6 +2823,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
|
||||
ADD_TEST_MACRO(CMakeCommands.add_compile_definitions add_compile_definitions)
|
||||
ADD_TEST_MACRO(CMakeCommands.add_compile_options add_compile_options)
|
||||
ADD_TEST_MACRO(CMakeCommands.target_link_libraries target_link_libraries)
|
||||
ADD_TEST_MACRO(CMakeCommands.target_link_directories)
|
||||
ADD_TEST_MACRO(CMakeCommands.target_include_directories target_include_directories)
|
||||
ADD_TEST_MACRO(CMakeCommands.target_compile_definitions target_compile_definitions)
|
||||
ADD_TEST_MACRO(CMakeCommands.target_compile_options target_compile_options)
|
||||
|
@ -618,6 +618,18 @@ install(TARGETS testLinkOptions
|
||||
export(TARGETS testLinkOptions NAMESPACE bld_ APPEND FILE ExportBuildTree.cmake)
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# test export of INTERFACE_LINK_DIRECTORIES
|
||||
add_library(testLinkDirectories INTERFACE)
|
||||
target_link_directories(testLinkDirectories INTERFACE
|
||||
$<BUILD_INTERFACE:/interface/build>
|
||||
$<INSTALL_INTERFACE:interface/install>)
|
||||
|
||||
install(TARGETS testLinkDirectories
|
||||
EXPORT RequiredExp DESTINATION lib)
|
||||
export(TARGETS testLinkDirectories NAMESPACE bld_ APPEND FILE ExportBuildTree.cmake)
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# test export of INTERFACE_LINK_DEPENDS
|
||||
if(CMAKE_GENERATOR MATCHES "Make|Ninja")
|
||||
|
@ -489,6 +489,11 @@ endif()
|
||||
checkForProperty(bld_testLinkOptions "INTERFACE_LINK_OPTIONS" "INTERFACE_FLAG")
|
||||
checkForProperty(Req::testLinkOptions "INTERFACE_LINK_OPTIONS" "INTERFACE_FLAG")
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# check that imported libraries have the expected INTERFACE_LINK_DIRECTORIES property
|
||||
checkForProperty(bld_testLinkDirectories "INTERFACE_LINK_DIRECTORIES" "/interface/build")
|
||||
checkForProperty(Req::testLinkDirectories "INTERFACE_LINK_DIRECTORIES" "${CMAKE_INSTALL_PREFIX}/interface/install")
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# check that imported libraries have the expected INTERFACE_LINK_DEPENDS property
|
||||
if(CMAKE_GENERATOR MATCHES "Make|Ninja")
|
||||
|
14
Tests/LinkDirectory/External/CMakeLists.txt
vendored
14
Tests/LinkDirectory/External/CMakeLists.txt
vendored
@ -1,6 +1,20 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
project(LinkDirectoryExternal C)
|
||||
|
||||
|
||||
add_executable(myexe2 myexe.c)
|
||||
set_property(TARGET myexe2 PROPERTY OUTPUT_NAME LinkDirectory2)
|
||||
target_link_directories(myexe2 PRIVATE lib "${CMAKE_CURRENT_SOURCE_DIR}/../lib")
|
||||
target_link_libraries(myexe2 PRIVATE mylibA mylibB)
|
||||
|
||||
add_library (mylibs INTERFACE)
|
||||
target_link_directories(mylibs INTERFACE lib "${CMAKE_CURRENT_SOURCE_DIR}/../lib")
|
||||
target_link_libraries(mylibs INTERFACE mylibA mylibB)
|
||||
add_executable(myexe3 myexe.c)
|
||||
set_property(TARGET myexe3 PROPERTY OUTPUT_NAME LinkDirectory3)
|
||||
target_link_libraries(myexe3 PRIVATE mylibs)
|
||||
|
||||
|
||||
# Test CMP0015 OLD behavior: -L../lib
|
||||
cmake_policy(SET CMP0015 OLD)
|
||||
link_directories(../lib)
|
||||
|
2
Tests/RunCMake/set_property/LINK_DIRECTORIES-stdout.txt
Normal file
2
Tests/RunCMake/set_property/LINK_DIRECTORIES-stdout.txt
Normal file
@ -0,0 +1,2 @@
|
||||
-- Target LINK_DIRECTORIES is 'a;b;c;d;;e'
|
||||
-- Directory LINK_DIRECTORIES is 'a;b;c;d;;e'
|
3
Tests/RunCMake/set_property/LINK_DIRECTORIES.cmake
Normal file
3
Tests/RunCMake/set_property/LINK_DIRECTORIES.cmake
Normal file
@ -0,0 +1,3 @@
|
||||
include(Common.cmake)
|
||||
test_target_property(LINK_DIRECTORIES)
|
||||
test_directory_property(LINK_DIRECTORIES)
|
@ -6,6 +6,7 @@ run_cmake(COMPILE_OPTIONS)
|
||||
run_cmake(IMPORTED_GLOBAL)
|
||||
run_cmake(INCLUDE_DIRECTORIES)
|
||||
run_cmake(LINK_OPTIONS)
|
||||
run_cmake(LINK_DIRECTORIES)
|
||||
run_cmake(LINK_LIBRARIES)
|
||||
run_cmake(SOURCES)
|
||||
run_cmake(TYPE)
|
||||
|
Loading…
Reference in New Issue
Block a user