$<LINK_LIBRARY>: Add LINK_LIBRARY_OVERRIDE target property

To enable the management of incompatible $<LINK_LIBRARY> declarations,
add LINK_LIBRARY_OVERRIDE and LINK_LIBRARY_OVERRIDE_<LIBRARY> target
properties.
This commit is contained in:
Marc Chevrier
2021-11-19 19:08:30 +01:00
parent 42965799b4
commit 2a6b0415d7
41 changed files with 383 additions and 31 deletions

View File

@@ -1176,12 +1176,20 @@ Output-Related Expressions
target_link_libraries(lib3 PRIVATE lib1 lib2)
# an error will be raised here because lib1 has two different features
To resolve such incompatibilities, the :prop_tgt:`LINK_LIBRARY_OVERRIDE`
and :prop_tgt:`LINK_LIBRARY_OVERRIDE_<LIBRARY>` target properties can be
used.
.. note::
This expression does not guarantee that the list of specified libraries
will be kept grouped. So, constructs like ``start-group`` and
``end-group``, as supported by ``GNU ld``, cannot be used.
``CMake`` pre-defines some features of general interest:
.. include:: ../variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt
.. genex:: $<INSTALL_INTERFACE:...>
Content of ``...`` when the property is exported using :command:`install(EXPORT)`,

View File

@@ -308,6 +308,8 @@ Properties on Targets
/prop_tgt/LINK_INTERFACE_MULTIPLICITY_CONFIG
/prop_tgt/LINK_LIBRARIES
/prop_tgt/LINK_LIBRARIES_ONLY_TARGETS
/prop_tgt/LINK_LIBRARY_OVERRIDE
/prop_tgt/LINK_LIBRARY_OVERRIDE_LIBRARY
/prop_tgt/LINK_OPTIONS
/prop_tgt/LINK_SEARCH_END_STATIC
/prop_tgt/LINK_SEARCH_START_STATIC

View File

@@ -0,0 +1,54 @@
LINK_LIBRARY_OVERRIDE
---------------------
.. versionadded:: 3.24
To resolve incompatible features introduced by :genex:`LINK_LIBRARY` generator
expression, this property offers the possibility to override, per ``link-item``
(``CMake`` target or external library) involved in the link step, any defined
features with a new one.
This property takes a :ref:`;-list <CMake Language Lists>` of override
declarations which have the following format:
::
feature[,link-item]*
For the list of ``link-item`` (``CMake`` target or external library) specified,
the feature ``feature`` will be used in place of any declared feature. For
example:
.. code-block:: cmake
add_library(lib1 ...)
target_link_libraries(lib1 PUBLIC $<LINK_LIBRARY:feature1,external>)
add_library(lib2 ...)
target_link_libraries(lib2 PUBLIC $<LINK_LIBRARY:feature2,lib1>)
add_library(lib3 ...)
target_link_libraries(lib3 PRIVATE lib1 lib2)
# Here, lib1 has two different features which prevents to link lib3
# So, define LINK_LIBRARY_OVERRIDE property to ensure correct link
set_property(TARGET lib3 PROPERTY LINK_LIBRARY_OVERRIDE "feature2,lib1,external")
# The lib1 and external will be used with FEATURE2 to link lib3
It is also possible to override any feature with the pre-defined feature
``DEFAULT`` to get the standard behavior (i.e. no feature):
.. code-block:: cmake
set_property(TARGET lib3 PROPERTY LINK_LIBRARY_OVERRIDE "DEFAULT,lib1"
"feature2,external")
# The lib1 will be used without any feature and external will use feature2 to link lib3
Contents of ``LINK_LIBRARY_OVERRIDE`` may use
:manual:`generator expressions <cmake-generator-expressions(7)>`.
See also :prop_tgt:`LINK_LIBRARY_OVERRIDE_<LIBRARY>` target property for
a per linked target oriented approach to override features.
For more information about features, see
:variable:`CMAKE_<LANG>_LINK_USING_<FEATURE>`
and :variable:`CMAKE_LINK_USING_<FEATURE>` variables.

View File

@@ -0,0 +1,45 @@
LINK_LIBRARY_OVERRIDE_<LIBRARY>
-------------------------------
.. versionadded:: 3.24
To resolve incompatible features introduced by :genex:`LINK_LIBRARY` generator
expression, this property offers the possibility to override, for a
``link-item`` (``CMake`` target or external library) involved in the link step,
any defined features with a new one.
This property takes a ``feature`` name which will be applied to the
``link-item`` specified by ``<LIBRARY>`` suffix property. For example:
.. code-block:: cmake
add_library(lib1 ...)
target_link_libraries(lib1 PUBLIC $<LINK_LIBRARY:feature1,external>)
add_library(lib2 ...)
target_link_libraries(lib2 PUBLIC $<LINK_LIBRARY:feature2,lib1>)
add_library(lib3 ...)
target_link_libraries(lib3 PRIVATE lib1 lib2)
# Here, lib1 has two different features which prevents to link lib3
# So, define LINK_LIBRARY_OVERRIDE_lib1 property to ensure correct link
set_property(TARGET lib3 PROPERTY LINK_LIBRARY_OVERRIDE_lib1 feature2)
# The lib1 will be used with feature2 to link lib3
It is also possible to override any feature with the pre-defined feature
``DEFAULT`` to get the standard behavior (i.e. no feature):
.. code-block:: cmake
set_property(TARGET lib3 PROPERTY LINK_LIBRARY_OVERRIDE_lib1 DEFAULT)
# The lib1 will be used without any feature to link lib3
Contents of ``LINK_LIBRARY_OVERRIDE_<LIBRARY>`` may use
:manual:`generator expressions <cmake-generator-expressions(7)>`.
This property takes precedence over :prop_tgt:`LINK_LIBRARY_OVERRIDE`
target property.
For more information about features, see
:variable:`CMAKE_<LANG>_LINK_USING_<FEATURE>`
and :variable:`CMAKE_LINK_USING_<FEATURE>` variables.

View File

@@ -5,4 +5,7 @@ Genex-LINK_LIBRARY
libraries are specified during the link step. The variables
:variable:`CMAKE_<LANG>_LINK_USING_<FEATURE>` and
:variable:`CMAKE_LINK_USING_<FEATURE>` are used to define features usable by
the :genex:`LINK_LIBRARY` generator expression.
the :genex:`LINK_LIBRARY` generator expression. Moreover, the
:prop_tgt:`LINK_LIBRARY_OVERRIDE` and
:prop_tgt:`LINK_LIBRARY_OVERRIDE_<LIBRARY>` target properties are available
to resolve incompatible features.

View File

@@ -17,3 +17,10 @@ See also the associated variable
independent from the link language.
.. include:: CMAKE_LINK_USING_FEATURE.txt
Predefined Features
^^^^^^^^^^^^^^^^^^^
``CMake`` pre-defines some features of general interest:
.. include:: LINK_LIBRARY_PREDEFINED_FEATURES.txt

View File

@@ -21,3 +21,10 @@ for the linker language, the variable
:variable:`CMAKE_<LANG>_LINK_USING_<FEATURE>_SUPPORTED` is false or not set.
.. include:: CMAKE_LINK_USING_FEATURE.txt
Predefined Features
^^^^^^^^^^^^^^^^^^^
``CMake`` pre-defines some features of general interest:
.. include:: LINK_LIBRARY_PREDEFINED_FEATURES.txt

View File

@@ -0,0 +1,5 @@
**Features available in all environments**
* ``DEFAULT``: This feature enables default link expression. This is mainly
useful with :prop_tgt:`LINK_LIBRARY_OVERRIDE` and
:prop_tgt:`LINK_LIBRARY_OVERRIDE_<LIBRARY>` target properties.

View File

@@ -24,6 +24,12 @@ set(CMAKE_DL_LIBS "dl")
set(CMAKE_FIND_LIBRARY_PREFIXES "lib")
set(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a")
# Define feature "DEFAULT" as supported. This special feature generates the
# default option to link a library
# This feature is intended to be used in LINK_LIBRARY_OVERRIDE and
# LINK_LIBRARY_OVERRIDE_<LIBRARY> target properties
set(CMAKE_LINK_USING_DEFAULT_SUPPORTED TRUE)
set(CMAKE_AUTOGEN_ORIGIN_DEPENDS ON)
set(CMAKE_AUTOMOC_COMPILER_PREDEFINES ON)
if(NOT DEFINED CMAKE_AUTOMOC_PATH_PREFIX)

View File

@@ -11,9 +11,12 @@
#include <utility>
#include <cm/memory>
#include <cm/string_view>
#include <cmext/string_view>
#include "cmComputeComponentGraph.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
@@ -200,6 +203,8 @@ bool IsFeatureSupported(cmMakefile* makefile, std::string const& linkLanguage,
}
}
const std::string cmComputeLinkDepends::LinkEntry::DEFAULT = "DEFAULT";
cmComputeLinkDepends::cmComputeLinkDepends(const cmGeneratorTarget* target,
const std::string& config,
const std::string& linkLanguage)
@@ -212,6 +217,49 @@ cmComputeLinkDepends::cmComputeLinkDepends(const cmGeneratorTarget* target,
this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance();
this->LinkLanguage = linkLanguage;
// target oriented feature override property takes precedence over
// global override property
cm::string_view lloPrefix = "LINK_LIBRARY_OVERRIDE_"_s;
auto const& keys = this->Target->GetPropertyKeys();
std::for_each(
keys.cbegin(), keys.cend(),
[this, &lloPrefix, &config, &linkLanguage](std::string const& key) {
if (cmHasPrefix(key, lloPrefix)) {
if (cmValue feature = this->Target->GetProperty(key)) {
if (!feature->empty() && key.length() > lloPrefix.length()) {
auto item = key.substr(lloPrefix.length());
cmGeneratorExpressionDAGChecker dag{ this->Target->GetBacktrace(),
this->Target,
"LINK_LIBRARY_OVERRIDE",
nullptr, nullptr };
auto overrideFeature = cmGeneratorExpression::Evaluate(
feature, this->Target->GetLocalGenerator(), config, this->Target,
&dag, this->Target, linkLanguage);
this->LinkLibraryOverride.emplace(item, overrideFeature);
}
}
}
});
// global override property
if (cmValue linkLibraryOverride =
this->Target->GetProperty("LINK_LIBRARY_OVERRIDE")) {
cmGeneratorExpressionDAGChecker dag{ target->GetBacktrace(), target,
"LINK_LIBRARY_OVERRIDE", nullptr,
nullptr };
auto overrideValue = cmGeneratorExpression::Evaluate(
linkLibraryOverride, target->GetLocalGenerator(), config, target, &dag,
target, linkLanguage);
auto overrideList = cmTokenize(overrideValue, ","_s);
if (overrideList.size() >= 2) {
auto const& feature = overrideList.front();
for_each(overrideList.cbegin() + 1, overrideList.cend(),
[this, &feature](std::string const& item) {
this->LinkLibraryOverride.emplace(item, feature);
});
}
}
// The configuration being linked.
this->HasConfig = !config.empty();
this->Config = (this->HasConfig) ? config : std::string();
@@ -309,6 +357,13 @@ cmComputeLinkDepends::Compute()
return this->FinalLinkEntries;
}
std::string const& cmComputeLinkDepends::GetCurrentFeature(
std::string const& item, std::string const& defaultFeature) const
{
auto it = this->LinkLibraryOverride.find(item);
return it == this->LinkLibraryOverride.end() ? defaultFeature : it->second;
}
std::pair<std::map<cmLinkItem, int>::iterator, bool>
cmComputeLinkDepends::AllocateLinkEntry(cmLinkItem const& item)
{
@@ -568,7 +623,7 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index,
{
// Track inferred dependency sets implied by this list.
std::map<int, DependSet> dependSets;
std::string feature;
std::string feature = LinkEntry::DEFAULT;
// Loop over the libraries linked directly by the depender.
for (T const& l : libs) {
@@ -604,7 +659,7 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index,
continue;
}
if (cmHasPrefix(item.AsStr(), LL_END) && cmHasSuffix(item.AsStr(), '>')) {
feature.clear();
feature = LinkEntry::DEFAULT;
continue;
}
@@ -612,7 +667,9 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index,
auto ale = this->AddLinkEntry(item);
int dependee_index = ale.first;
LinkEntry& entry = this->EntryList[dependee_index];
if (!feature.empty()) {
auto const& itemFeature =
this->GetCurrentFeature(entry.Item.Value, feature);
if (itemFeature != LinkEntry::DEFAULT) {
if (ale.second) {
// current item not yet defined
if (entry.Target != nullptr &&
@@ -633,7 +690,7 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index,
" library '", entry.Item.Value, "'."),
this->Target->GetBacktrace());
} else {
entry.Feature = feature;
entry.Feature = itemFeature;
}
}
}
@@ -642,20 +699,21 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index,
(entry.Target->GetType() != cmStateEnums::TargetType::OBJECT_LIBRARY &&
entry.Target->GetType() != cmStateEnums::TargetType::INTERFACE_LIBRARY);
if (supportedItem && entry.Feature != feature) {
if (supportedItem && entry.Feature != itemFeature) {
// incompatibles features occurred
this->CMakeInstance->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat(
"Impossible to link target '", this->Target->GetName(),
"' because the link item '", entry.Item.Value, "', specified ",
(feature.empty() ? "without any feature"
: cmStrCat("with the feature '", feature, '\'')),
", has already occurred ",
(entry.Feature.empty()
? "without any feature"
: cmStrCat("with the feature '", entry.Feature, '\'')),
", which is not allowed."),
cmStrCat("Impossible to link target '", this->Target->GetName(),
"' because the link item '", entry.Item.Value,
"', specified ",
(itemFeature == LinkEntry::DEFAULT
? "without any feature or 'DEFAULT' feature"
: cmStrCat("with the feature '", itemFeature, '\'')),
", has already occurred ",
(entry.Feature == LinkEntry::DEFAULT
? "without any feature or 'DEFAULT' feature"
: cmStrCat("with the feature '", entry.Feature, '\'')),
", which is not allowed."),
this->Target->GetBacktrace());
}
@@ -978,7 +1036,7 @@ void cmComputeLinkDepends::DisplayFinalEntries()
} else {
fprintf(stderr, " item [%s]", lei.Item.Value.c_str());
}
if (!lei.Feature.empty()) {
if (lei.Feature != LinkEntry::DEFAULT) {
fprintf(stderr, ", feature [%s]", lei.Feature.c_str());
}
fprintf(stderr, "\n");

View File

@@ -47,6 +47,8 @@ public:
{
}
static const std::string DEFAULT;
BT<std::string> Item;
cmGeneratorTarget const* Target = nullptr;
bool IsSharedDep = false;
@@ -54,7 +56,7 @@ public:
bool IsObject = false;
// The following member is for the management of items specified
// through genex $<LINK_LIBRARY:...>
std::string Feature;
std::string Feature = std::string(DEFAULT);
};
using EntryVector = std::vector<LinkEntry>;
@@ -75,6 +77,10 @@ private:
std::string LinkLanguage;
std::string Config;
EntryVector FinalLinkEntries;
std::map<std::string, std::string> LinkLibraryOverride;
std::string const& GetCurrentFeature(
std::string const& item, std::string const& defaultFeature) const;
std::pair<std::map<cmLinkItem, int>::iterator, bool> AllocateLinkEntry(
cmLinkItem const& item);

View File

@@ -431,6 +431,10 @@ cmComputeLinkInformation::cmComputeLinkInformation(
cmComputeLinkInformation::~cmComputeLinkInformation() = default;
namespace {
const std::string& DEFAULT = cmComputeLinkDepends::LinkEntry::DEFAULT;
}
void cmComputeLinkInformation::AppendValues(
std::string& result, std::vector<BT<std::string>>& values)
{
@@ -551,7 +555,7 @@ bool cmComputeLinkInformation::Compute()
currentFeature = nullptr;
}
if (!linkEntry.Feature.empty() &&
if (linkEntry.Feature != DEFAULT &&
(currentFeature == nullptr ||
linkEntry.Feature != currentFeature->Name)) {
if (!this->AddLibraryFeature(linkEntry.Feature)) {
@@ -988,8 +992,9 @@ void cmComputeLinkInformation::AddItem(LinkEntry const& entry)
std::string exe = tgt->GetFullPath(config, artifact, true);
this->Items.emplace_back(
BT<std::string>(exe, item.Backtrace), ItemIsPath::Yes, tgt,
this->FindLibraryFeature(
entry.Feature.empty() ? "__CMAKE_LINK_EXECUTABLE" : entry.Feature));
this->FindLibraryFeature(entry.Feature == DEFAULT
? "__CMAKE_LINK_EXECUTABLE"
: entry.Feature));
this->Depends.push_back(std::move(exe));
} else if (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
// Add the interface library as an item so it can be considered as part
@@ -1421,7 +1426,7 @@ void cmComputeLinkInformation::AddTargetItem(LinkEntry const& entry)
// Now add the full path to the library.
this->Items.emplace_back(item, ItemIsPath::Yes, target,
this->FindLibraryFeature(entry.Feature.empty()
this->FindLibraryFeature(entry.Feature == DEFAULT
? "__CMAKE_LINK_LIBRARY"
: entry.Feature));
}
@@ -1482,7 +1487,7 @@ void cmComputeLinkInformation::AddFullItem(LinkEntry const& entry)
this->Items.emplace_back(
item, ItemIsPath::Yes, nullptr,
this->FindLibraryFeature(
entry.Feature.empty()
entry.Feature == DEFAULT
? (entry.IsObject ? "__CMAKE_LINK_OBJECT" : "__CMAKE_LINK_LIBRARY")
: entry.Feature));
}
@@ -1650,7 +1655,7 @@ void cmComputeLinkInformation::AddUserItem(LinkEntry const& entry,
// Create an option to ask the linker to search for the library.
auto out = cmStrCat(this->LibLinkFlag, lib, this->LibLinkSuffix);
if (!entry.Feature.empty()) {
if (entry.Feature != DEFAULT) {
auto const& feature = this->GetLibraryFeature(entry.Feature);
this->Items.emplace_back(
BT<std::string>(

View File

@@ -167,7 +167,7 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkExpression() const
cm::string_view property(this->Top()->Property);
return property == "LINK_DIRECTORIES"_s || property == "LINK_OPTIONS"_s ||
property == "LINK_DEPENDS"_s;
property == "LINK_DEPENDS"_s || property == "LINK_LIBRARY_OVERRIDE"_s;
}
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkOptionsExpression() const

View File

@@ -19,7 +19,16 @@ run_cmake(bad-feature7)
run_cmake(feature-not-supported)
run_cmake(library-ignored)
run_cmake(compatible-features)
run_cmake(incompatible-features)
run_cmake(incompatible-features1)
run_cmake(incompatible-features2)
run_cmake(incompatible-features3)
run_cmake(nested-compatible-features)
run_cmake(nested-incompatible-features)
run_cmake(only-targets)
# testing target propertes LINK_LIBRARY_OVERRIDE and LINK_LIBRARY_OVERRIDE_<LIBRARY>
run_cmake(override-features1)
run_cmake(override-features2)
run_cmake(override-features3)
run_cmake(override-features4)
run_cmake(override-features5)

View File

@@ -11,5 +11,11 @@ add_library(dep1 SHARED empty.c)
add_library(dep2 SHARED empty.c)
target_link_libraries(dep2 PRIVATE "$<LINK_LIBRARY:feat1,dep1>")
add_library(lib SHARED empty.c)
target_link_libraries(lib PRIVATE "$<LINK_LIBRARY:feat2,dep1,dep2>")
add_library(dep3 SHARED empty.c)
target_link_libraries(dep3 PUBLIC dep2)
add_library(lib1 SHARED empty.c)
target_link_libraries(lib1 PRIVATE $<LINK_LIBRARY:feat2,dep1,dep2>)
add_library(lib2 SHARED empty.c)
target_link_libraries(lib2 PRIVATE $<LINK_LIBRARY:DEFAULT,dep2,dep3>)

View File

@@ -1,4 +1,4 @@
CMake Error at incompatible-features.cmake:[0-9]+ \(add_library\):
CMake Error at incompatible-features1.cmake:[0-9]+ \(add_library\):
Impossible to link target 'lib' because the link item 'dep1', specified
with the feature 'feat1', has already occurred with the feature 'feat2',
which is not allowed.

View File

@@ -0,0 +1,6 @@
CMake Error at incompatible-features2.cmake:[0-9]+ \(add_library\):
Impossible to link target 'lib' because the link item 'dep1', specified
without any feature or 'DEFAULT' feature, has already occurred with the
feature 'feat2', which is not allowed.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)

View File

@@ -0,0 +1,15 @@
enable_language(C)
set(CMAKE_C_LINK_USING_feat1_SUPPORTED TRUE)
set(CMAKE_C_LINK_USING_feat1 "<LIBRARY>")
set(CMAKE_C_LINK_USING_feat2_SUPPORTED TRUE)
set(CMAKE_C_LINK_USING_feat2 "<LIBRARY>")
add_library(dep1 SHARED empty.c)
add_library(dep2 SHARED empty.c)
target_link_libraries(dep2 PUBLIC dep1)
add_library(lib SHARED empty.c)
target_link_libraries(lib PRIVATE $<LINK_LIBRARY:feat2,dep1,dep2>)

View File

@@ -0,0 +1,6 @@
CMake Error at incompatible-features3.cmake:[0-9]+ \(add_library\):
Impossible to link target 'lib' because the link item 'dep1', specified
with the feature 'feat1', has already occurred without any feature or
'DEFAULT' feature, which is not allowed.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)

View File

@@ -0,0 +1,15 @@
enable_language(C)
set(CMAKE_C_LINK_USING_feat1_SUPPORTED TRUE)
set(CMAKE_C_LINK_USING_feat1 "<LIBRARY>")
set(CMAKE_C_LINK_USING_feat2_SUPPORTED TRUE)
set(CMAKE_C_LINK_USING_feat2 "<LIBRARY>")
add_library(dep1 SHARED empty.c)
add_library(dep2 SHARED empty.c)
target_link_libraries(dep2 PUBLIC $<LINK_LIBRARY:feat1,dep1>)
add_library(lib SHARED empty.c)
target_link_libraries(lib PRIVATE dep1 dep2)

View File

@@ -0,0 +1,4 @@
include(incompatible-features1.cmake)
set_property(TARGET lib PROPERTY LINK_LIBRARY_OVERRIDE "feat1,dep1")

View File

@@ -0,0 +1,4 @@
include(incompatible-features1.cmake)
set_property(TARGET lib PROPERTY LINK_LIBRARY_OVERRIDE "feat2,dep1")

View File

@@ -0,0 +1,7 @@
include(incompatible-features1.cmake)
set(CMAKE_C_LINK_USING_feat3_SUPPORTED TRUE)
set(CMAKE_C_LINK_USING_feat3 "<LIBRARY>")
set_property(TARGET lib PROPERTY LINK_LIBRARY_OVERRIDE "feat3,dep1")

View File

@@ -0,0 +1,9 @@
include(incompatible-features1.cmake)
set(CMAKE_C_LINK_USING_feat3_SUPPORTED TRUE)
set(CMAKE_C_LINK_USING_feat3 "<LIBRARY>")
set_property(TARGET lib PROPERTY LINK_LIBRARY_OVERRIDE "feat3,dep1")
set_property(TARGET lib PROPERTY LINK_LIBRARY_OVERRIDE_dep1 feat1)

View File

@@ -0,0 +1,7 @@
include(incompatible-features1.cmake)
set_property(TARGET lib PROPERTY LINK_LIBRARY_OVERRIDE "feat1,dep1")
# next property will be ignored because no feature is specified
set_property(TARGET lib PROPERTY LINK_LIBRARY_OVERRIDE_dep1)

View File

@@ -0,0 +1,4 @@
if (NOT actual_stdout MATCHES "(/|-)-LIBFLAG.*${LINK_SHARED_LIBRARY_PREFIX}base3${LINK_SHARED_LIBRARY_SUFFIX}\"? +\"?(/|-)-LIBFLAG.*${LINK_SHARED_LIBRARY_PREFIX}base1${LINK_SHARED_LIBRARY_SUFFIX}\"? +\"?${CMAKE_LINK_LIBRARY_FLAG}other1")
set (RunCMake_TEST_FAILED "Not found expected '--LIBFLAG<base3> --LIBFLAG<base1> <other1>'.")
endif()

View File

@@ -0,0 +1,4 @@
if (NOT actual_stdout MATCHES "(/|-)-LIBFLAG.*${LINK_SHARED_LIBRARY_PREFIX}base3${LINK_SHARED_LIBRARY_SUFFIX}\"? +\"?(/|-)-PREFIXGROUP\"? +\"?(/|-)-LIBGROUP.*${LINK_SHARED_LIBRARY_PREFIX}base1${LINK_SHARED_LIBRARY_SUFFIX}\"? +\"?(/|-)-LIBGROUPother1${LINK_EXTERN_LIBRARY_SUFFIX}\"? +\"?(/|-)-SUFFIXGROUP")
set (RunCMake_TEST_FAILED "Not found expected '--LIBFLAG<base3> --PREFIXGROUP --LIBGROUP<base1> --LIBGROUP<other1> --SUFFIXGROUP'.")
endif()

View File

@@ -0,0 +1,4 @@
if (NOT actual_stdout MATCHES "(/|-)-LIBFLAG.*${LINK_SHARED_LIBRARY_PREFIX}base3${LINK_SHARED_LIBRARY_SUFFIX}\"? +\"?(/|-)-LIBFLAG.*${LINK_SHARED_LIBRARY_PREFIX}base1${LINK_SHARED_LIBRARY_SUFFIX}\"? +\"?${CMAKE_LINK_LIBRARY_FLAG}other1")
set (RunCMake_TEST_FAILED "Not found expected '--LIBFLAG<base3> --LIBFLAG<base1> <other1>'.")
endif()

View File

@@ -0,0 +1,4 @@
if (NOT actual_stdout MATCHES "(/|-)-LIBFLAG.*${LINK_SHARED_LIBRARY_PREFIX}base3${LINK_SHARED_LIBRARY_SUFFIX}\"? +\"?(/|-)-PREFIXGROUP\"? +\"?(/|-)-LIBGROUP.*${LINK_SHARED_LIBRARY_PREFIX}base1${LINK_SHARED_LIBRARY_SUFFIX}\"? +\"?(/|-)-LIBGROUPother1${LINK_EXTERN_LIBRARY_SUFFIX}\"? +\"?(/|-)-SUFFIXGROUP")
set (RunCMake_TEST_FAILED "Not found expected '--LIBFLAG<base3> --PREFIXGROUP --LIBGROUP<base1> --LIBGROUP<other1> --SUFFIXGROUP'.")
endif()

View File

@@ -0,0 +1,4 @@
if (NOT actual_stdout MATCHES "(/|-)-LIBFLAG.*${LINK_SHARED_LIBRARY_PREFIX}base3${LINK_SHARED_LIBRARY_SUFFIX}\"? +\"?.*${LINK_SHARED_LIBRARY_PREFIX}base1${LINK_SHARED_LIBRARY_SUFFIX}\"? +\"?${CMAKE_LINK_LIBRARY_FLAG}other1${LINK_EXTERN_LIBRARY_SUFFIX}\"?")
set (RunCMake_TEST_FAILED "Not found expected '--LIBFLAG<base3> <base1> <other1>'.")
endif()

View File

@@ -1,4 +1,3 @@
enable_language(C)
# ensure command line is always displayed and do not use any response file
@@ -78,4 +77,28 @@ target_link_libraries(LinkLibrary_mix_features2 PRIVATE "$<LINK_LIBRARY:feat2,ba
target_link_libraries(base3 INTERFACE other1)
add_library(LinkLibrary_mix_features3 SHARED lib.c)
target_link_libraries(LinkLibrary_mix_features3 PRIVATE base2 "$<LINK_LIBRARY:feat2,base1,base3>" other2)
target_link_libraries(LinkLibrary_mix_features3 PRIVATE base2 $<LINK_LIBRARY:feat2,base1,base3> other2)
# testing LINK_LIBRARY_OVERRIDE property
add_library(LinkLibrary_override_features1 SHARED lib.c)
target_link_libraries(LinkLibrary_override_features1 PRIVATE $<LINK_LIBRARY:feat1,base1,base3>)
set_property(TARGET LinkLibrary_override_features1 PROPERTY LINK_LIBRARY_OVERRIDE "feat1,base1")
add_library(LinkLibrary_override_features2 SHARED lib.c)
target_link_libraries(LinkLibrary_override_features2 PRIVATE $<LINK_LIBRARY:feat1,base1,base3>)
set_property(TARGET LinkLibrary_override_features2 PROPERTY LINK_LIBRARY_OVERRIDE "feat2,base1,other1")
add_library(LinkLibrary_override_with_default SHARED lib.c)
target_link_libraries(LinkLibrary_override_with_default PRIVATE $<LINK_LIBRARY:feat1,base1,base3>)
set_property(TARGET LinkLibrary_override_with_default PROPERTY LINK_LIBRARY_OVERRIDE "$<$<LINK_LANGUAGE:C>:DEFAULT,base1,other1>")
# testing LINK_LIBRARY_OVERRIDE_<LIBRARY> property
add_library(LinkLibrary_override_features3 SHARED lib.c)
target_link_libraries(LinkLibrary_override_features3 PRIVATE $<LINK_LIBRARY:feat1,base1,base3>)
set_property(TARGET LinkLibrary_override_features3 PROPERTY LINK_LIBRARY_OVERRIDE_base1 feat1)
add_library(LinkLibrary_override_features4 SHARED lib.c)
target_link_libraries(LinkLibrary_override_features4 PRIVATE $<LINK_LIBRARY:feat1,base1,base3>)
set_property(TARGET LinkLibrary_override_features4 PROPERTY LINK_LIBRARY_OVERRIDE "feat3,base1,other1")
set_property(TARGET LinkLibrary_override_features4 PROPERTY LINK_LIBRARY_OVERRIDE_base1 feat2)
set_property(TARGET LinkLibrary_override_features4 PROPERTY LINK_LIBRARY_OVERRIDE_other1 feat2)

View File

@@ -53,6 +53,14 @@ if ((RunCMake_GENERATOR MATCHES "Makefiles|Ninja|Xcode"
run_cmake_target(LINK_LIBRARY mix-features2 LinkLibrary_mix_features2)
run_cmake_target(LINK_LIBRARY mix-features3 LinkLibrary_mix_features3)
# testing target property LINK_LIBRARY_OVERRIDE
run_cmake_target(LINK_LIBRARY override-features1 LinkLibrary_override_features1)
run_cmake_target(LINK_LIBRARY override-features2 LinkLibrary_override_features2)
run_cmake_target(LINK_LIBRARY override-with-DEFAULT LinkLibrary_override_with_default)
# testing target property LINK_LIBRARY_OVERRIDE_<LIBRARY>
run_cmake_target(LINK_LIBRARY override-features3 LinkLibrary_override_features3)
run_cmake_target(LINK_LIBRARY override-features4 LinkLibrary_override_features4)
run_cmake(imported-target)
# tests using features as described in the documentation