Merge topic 'revert-link-interface-direct-for-3.23' into release-3.23

687a91967f Revert INTERFACE_LINK_LIBRARIES_DIRECT feature for 3.23 branch

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !7098
This commit is contained in:
Brad King
2022-03-22 15:56:32 +00:00
committed by Kitware Robot
78 changed files with 27 additions and 1320 deletions

View File

@@ -266,8 +266,6 @@ Properties on Targets
/prop_tgt/INTERFACE_LINK_DEPENDS
/prop_tgt/INTERFACE_LINK_DIRECTORIES
/prop_tgt/INTERFACE_LINK_LIBRARIES
/prop_tgt/INTERFACE_LINK_LIBRARIES_DIRECT
/prop_tgt/INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
/prop_tgt/INTERFACE_LINK_OPTIONS
/prop_tgt/INTERFACE_POSITION_INDEPENDENT_CODE
/prop_tgt/INTERFACE_PRECOMPILE_HEADERS

View File

@@ -26,12 +26,6 @@ manual for more on defining buildsystem properties.
.. include:: LINK_LIBRARIES_INDIRECTION.txt
``INTERFACE_LINK_LIBRARIES`` adds transitive link dependencies for a
target's dependents. In advanced use cases, one may update the
direct link dependencies of a target's dependents by using the
:prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT` and
:prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE` target properties.
Creating Relocatable Packages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -1,223 +0,0 @@
INTERFACE_LINK_LIBRARIES_DIRECT
-------------------------------
.. versionadded:: 3.23
List of libraries that consumers of this library should treat
as direct link dependencies.
This target property may be set to *include* items in a dependent
target's final set of direct link dependencies. See the
:prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE` target property
to exclude items.
The initial set of a dependent target's direct link dependencies is
specified by its :prop_tgt:`LINK_LIBRARIES` target property. Indirect
link dependencies are specified by the transitive closure of the direct
link dependencies' :prop_tgt:`INTERFACE_LINK_LIBRARIES` properties.
Any link dependency may specify additional direct link dependencies
using the ``INTERFACE_LINK_LIBRARIES_DIRECT`` target property.
The set of direct link dependencies is then filtered to exclude items named
by any dependency's :prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE`
target property.
.. |INTERFACE_PROPERTY_LINK_DIRECT| replace:: ``INTERFACE_LINK_LIBRARIES_DIRECT``
.. include:: INTERFACE_LINK_LIBRARIES_DIRECT.txt
Direct Link Dependencies as Usage Requirements
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The ``INTERFACE_PROPERTY_LINK_DIRECT`` and
``INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE`` target properties
are :ref:`usage requirements <Target Usage Requirements>`.
Their effects propagate to dependent targets transitively, and can
therefore affect the direct link dependencies of every target in a
chain of dependent libraries. Whenever some library target ``X`` links
to another library target ``Y`` whose direct or transitive usage
requirements contain ``INTERFACE_PROPERTY_LINK_DIRECT`` or
``INTERFACE_PROPERTY_LINK_DIRECT_EXCLUDE``, the properties may affect
``X``'s list of direct link dependencies:
* If ``X`` is a shared library or executable, its dependencies are linked.
They also affect the usage requirements with which ``X``'s sources are
compiled.
* If ``X`` is a static library or object library, it does not actually
link, so its dependencies at most affect the usage requirements with
which ``X``'s sources are compiled.
The properties may also affect the list of direct link dependencies
on ``X``'s dependents:
* If ``X`` links ``Y`` publicly:
.. code-block:: cmake
target_link_libraries(X PUBLIC Y)
then ``Y`` is placed in ``X``'s :prop_tgt:`INTERFACE_LINK_LIBRARIES`,
so ``Y``'s usage requirements, including ``INTERFACE_PROPERTY_LINK_DIRECT``
and ``INTERFACE_PROPERTY_LINK_DIRECT_EXCLUDE``, are propagated
to ``X``'s dependents.
* If ``X`` links ``Y`` privately:
.. code-block:: cmake
target_link_libraries(X PRIVATE Y)
then ``Y`` is not placed in ``X``'s :prop_tgt:`INTERFACE_LINK_LIBRARIES`,
so ``Y``'s usage requirements, even ``INTERFACE_PROPERTY_LINK_DIRECT``
and ``INTERFACE_PROPERTY_LINK_DIRECT_EXCLUDE``, are not propagated
to ``X``'s dependents.
(If ``X`` is a static library or object library, then ``$<LINK_ONLY:Y>``
is placed in ``X``'s :prop_tgt:`INTERFACE_LINK_LIBRARIES`, but the
:genex:`LINK_ONLY` generator expression block ``Y``'s usage requirements.)
* In either case, the content of ``X``'s :prop_tgt:`INTERFACE_LINK_LIBRARIES`
is not affected by ``Y``'s ``INTERFACE_PROPERTY_LINK_DIRECT`` or
``INTERFACE_PROPERTY_LINK_DIRECT_EXCLUDE``.
One may limit the effects of ``INTERFACE_PROPERTY_LINK_DIRECT`` and
``INTERFACE_PROPERTY_LINK_DIRECT_EXCLUDE`` to a subset of dependent
targets by using the :genex:`TARGET_PROPERTY` generator expression.
For example, to limit the effects to executable targets, use an
entry of the form::
"$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:...>"
Similarly, to limit the effects to specific targets, use an entry
of the form::
"$<$<BOOL:$<TARGET_PROPERTY:USE_IT>>:...>"
This entry will only affect targets that set their ``USE_IT``
target property to a true value.
Direct Link Dependency Ordering
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The list of direct link dependencies for a target is computed from an
initial ordered list in its :prop_tgt:`LINK_LIBRARIES` target property.
For each item, additional direct link dependencies are discovered from
its direct and transitive ``INTERFACE_LINK_LIBRARIES_DIRECT`` usage
requirements. Each discovered item is injected before the item that
specified it. However, a discovered item is added at most once,
and only if it did not appear anywhere in the initial list.
This gives :prop_tgt:`LINK_LIBRARIES` control over ordering of
those direct link dependencies that it explicitly specifies.
Once all direct link dependencies have been collected, items named by
all of their :prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE`
usage requirements are removed from the final list. This does not
affect the order of the items that remain.
Example: Static Plugins
^^^^^^^^^^^^^^^^^^^^^^^
Consider a static library ``Foo`` that provides a static plugin
``FooPlugin`` to consuming application executables, where the
implementation of the plugin depends on ``Foo`` and other things.
In this case, the application should link to ``FooPlugin`` directly,
before ``Foo``. However, the application author only knows about ``Foo``.
We can express this as follows:
.. code-block:: cmake
# Core library used by other components.
add_library(Core STATIC core.cpp)
# Foo is a static library for use by applications.
# Implementation of Foo depends on Core.
add_library(Foo STATIC foo.cpp foo_plugin_helper.cpp)
target_link_libraries(Foo PRIVATE Core)
# Extra parts of Foo for use by its static plugins.
# Implementation of Foo's extra parts depends on both Core and Foo.
add_library(FooExtras STATIC foo_extras.cpp)
target_link_libraries(FooExtras PRIVATE Core Foo)
# The Foo library has an associated static plugin
# that should be linked into the final executable.
# Implementation of the plugin depends on Core, Foo, and FooExtras.
add_library(FooPlugin STATIC foo_plugin.cpp)
target_link_libraries(FooPlugin PRIVATE Core Foo FooExtras)
# An app that links Foo should link Foo's plugin directly.
set_property(TARGET Foo PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT FooPlugin)
# An app does not need to link Foo directly because the plugin links it.
set_property(TARGET Foo PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE Foo)
An application ``app`` only needs to specify that it links to ``Foo``:
.. code-block:: cmake
add_executable(app main.cpp)
target_link_libraries(app PRIVATE Foo)
The ``INTERFACE_LINK_LIBRARIES_DIRECT`` target property on ``Foo`` tells
CMake to pretend that ``app`` also links directly to ``FooPlugin``.
The ``INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE`` target property on ``Foo``
tells CMake to pretend that ``app`` did *not* link directly to ``Foo``.
Instead, ``Foo`` will be linked as a dependency of ``FooPlugin``. The
final link line for ``app`` will link the libraries in the following
order:
* ``FooPlugin`` as a direct link dependency of ``app``
(via ``Foo``'s usage requiremens).
* ``FooExtras`` as a dependency of ``FooPlugin``.
* ``Foo`` as a dependency of ``FooPlugin`` and ``FooExtras``.
* ``Core`` as a dependency of ``FooPlugin``, ``FooExtras``, and ``Foo``.
Note that without the ``INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE`` target
property, ``Foo`` would be linked twice: once as a direct dependency
of ``app``, and once as a dependency of ``FooPlugin``.
Example: Opt-In Static Plugins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In the above `Example: Static Plugins`_, the ``app`` executable specifies
that it links directly to ``Foo``. In a real application, there might
be an intermediate library:
.. code-block:: cmake
add_library(app_impl STATIC app_impl.cpp)
target_link_libraries(app_impl PUBLIC Foo)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE app_impl)
In this case we do not want ``Foo``'s ``INTERFACE_LINK_LIBRARIES_DIRECT``
and ``INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE`` target properties to affect
the direct dependencies of ``app_impl``. To avoid this, we can revise
the property values to make their effects opt-in:
.. code-block:: cmake
# An app that links Foo should link Foo's plugin directly.
set_property(TARGET Foo PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT
"$<$<BOOL:$<TARGET_PROPERTY:FOO_STATIC_PLUGINS>>:FooPlugin>"
)
# An app does not need to link Foo directly because the plugin links it.
set_property(TARGET Foo PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
"$<$<BOOL:$<TARGET_PROPERTY:FOO_STATIC_PLUGINS>>:Foo>"
)
Now, the ``app`` executable can opt-in to get ``Foo``'s plugin(s):
.. code-block:: cmake
set_property(TARGET app PROPERTY FOO_STATIC_PLUGINS 1)
The final link line for ``app`` will now link the libraries in the following
order:
* ``FooPlugin`` as a direct link dependency of ``app``
(via ``Foo``'s usage requiremens).
* ``app_impl`` as a direct link dependency of ``app``.
* ``FooExtras`` as a dependency of ``FooPlugin``.
* ``Foo`` as a dependency of ``app_impl``, ``FooPlugin``, and ``FooExtras``.
* ``Core`` as a dependency of ``FooPlugin``, ``FooExtras``, and ``Foo``.

View File

@@ -1,9 +0,0 @@
The value of |INTERFACE_PROPERTY_LINK_DIRECT| may use
:manual:`generator expressions <cmake-generator-expressions(7)>`.
.. note::
The |INTERFACE_PROPERTY_LINK_DIRECT| target property is intended for
advanced use cases such as injection of static plugins into a consuming
executable. It should not be used as a substitute for organizing
normal calls to :command:`target_link_libraries`.

View File

@@ -1,34 +0,0 @@
INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
---------------------------------------
.. versionadded:: 3.23
List of libraries that consumers of this library should *not* treat
as direct link dependencies.
This target property may be set to *exclude* items from a dependent
target's final set of direct link dependencies. This property is
processed after the :prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT`
target property of all other dependencies of the dependent target, so
exclusion from direct link dependence takes priority over inclusion.
The initial set of a dependent target's direct link dependencies is
specified by its :prop_tgt:`LINK_LIBRARIES` target property. Indirect
link dependencies are specified by the transitive closure of the direct
link dependencies' :prop_tgt:`INTERFACE_LINK_LIBRARIES` properties.
Any link dependency may specify additional direct link dependencies
using the :prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT` target property.
The set of direct link dependencies is then filtered to exclude items named
by any dependency's ``INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE`` target
property.
Excluding an item from a dependent target's direct link dependencies
does not mean the dependent target won't link the item. The item
may still be linked as an indirect link dependency via the
:prop_tgt:`INTERFACE_LINK_LIBRARIES` property on other dependencies.
.. |INTERFACE_PROPERTY_LINK_DIRECT| replace:: ``INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE``
.. include:: INTERFACE_LINK_LIBRARIES_DIRECT.txt
See the :prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT` target property
documentation for more details and examples.

View File

@@ -20,8 +20,3 @@ for available expressions. See the :manual:`cmake-buildsystem(7)` manual
for more on defining buildsystem properties.
.. include:: LINK_LIBRARIES_INDIRECTION.txt
In advanced use cases, the list of direct link dependencies specified
by this property may be updated by usage requirements from dependencies.
See the :prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT` and
:prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE` target properties.

View File

@@ -130,11 +130,6 @@ Properties
not be treated as a system library (i.e. its include directories
are not automatically ``SYSTEM``).
* The :prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT` and
:prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE` target properties
were added to express usage requirements affecting a consumer's
direct link dependencies.
* The :prop_tgt:`XCODE_EMBED_PLUGINS <XCODE_EMBED_<type>>` target property
was added to tell the :generator:`Xcode` generator what targets to put in
the ``Embed PlugIns`` build phase.

View File

@@ -2,7 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportFileGenerator.h"
#include <array>
#include <cassert>
#include <cstring>
#include <sstream>
@@ -176,24 +175,18 @@ bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty(
if (!target->IsLinkable()) {
return false;
}
static const std::array<std::string, 3> linkIfaceProps = {
{ "INTERFACE_LINK_LIBRARIES", "INTERFACE_LINK_LIBRARIES_DIRECT",
"INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE" }
};
bool hadINTERFACE_LINK_LIBRARIES = false;
for (std::string const& linkIfaceProp : linkIfaceProps) {
if (cmValue input = target->GetProperty(linkIfaceProp)) {
std::string prepro =
cmGeneratorExpression::Preprocess(*input, preprocessRule);
if (!prepro.empty()) {
this->ResolveTargetsInGeneratorExpressions(
prepro, target, missingTargets, ReplaceFreeTargets);
properties[linkIfaceProp] = prepro;
hadINTERFACE_LINK_LIBRARIES = true;
}
cmValue input = target->GetProperty("INTERFACE_LINK_LIBRARIES");
if (input) {
std::string prepro =
cmGeneratorExpression::Preprocess(*input, preprocessRule);
if (!prepro.empty()) {
this->ResolveTargetsInGeneratorExpressions(
prepro, target, missingTargets, ReplaceFreeTargets);
properties["INTERFACE_LINK_LIBRARIES"] = prepro;
return true;
}
}
return hadINTERFACE_LINK_LIBRARIES;
return false;
}
static bool isSubDirectory(std::string const& a, std::string const& b)

View File

@@ -111,8 +111,6 @@ void cmExportTryCompileFileGenerator::PopulateProperties(
std::vector<std::string> props = target->GetPropertyKeys();
// Include special properties that might be relevant here.
props.emplace_back("INTERFACE_LINK_LIBRARIES");
props.emplace_back("INTERFACE_LINK_LIBRARIES_DIRECT");
props.emplace_back("INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE");
for (std::string const& p : props) {
cmValue v = target->GetProperty(p);
if (!v) {

View File

@@ -189,8 +189,6 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(
}
return prop == "LINK_LIBRARIES"_s || prop == "INTERFACE_LINK_LIBRARIES"_s ||
prop == "INTERFACE_LINK_LIBRARIES_DIRECT"_s ||
prop == "INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE"_s ||
prop == "LINK_INTERFACE_LIBRARIES"_s ||
prop == "IMPORTED_LINK_INTERFACE_LIBRARIES"_s ||
cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES_") ||

View File

@@ -58,10 +58,6 @@ using LinkInterfaceFor = cmGeneratorTarget::LinkInterfaceFor;
const cmsys::RegularExpression FrameworkRegularExpression(
"^(.*/)?([^/]*)\\.framework/(.*)$");
const std::string kINTERFACE_LINK_LIBRARIES = "INTERFACE_LINK_LIBRARIES";
const std::string kINTERFACE_LINK_LIBRARIES_DIRECT =
"INTERFACE_LINK_LIBRARIES_DIRECT";
const std::string kINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE =
"INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE";
}
template <>
@@ -6671,10 +6667,12 @@ cm::optional<cmLinkItem> cmGeneratorTarget::LookupLinkItem(
return maybeItem;
}
void cmGeneratorTarget::ExpandLinkItems(
std::string const& prop, cmBTStringRange entries, std::string const& config,
cmGeneratorTarget const* headTarget, LinkInterfaceFor interfaceFor,
LinkInterfaceField field, cmLinkInterface& iface) const
void cmGeneratorTarget::ExpandLinkItems(std::string const& prop,
cmBTStringRange entries,
std::string const& config,
cmGeneratorTarget const* headTarget,
LinkInterfaceFor interfaceFor,
cmLinkInterface& iface) const
{
if (entries.empty()) {
return;
@@ -6698,19 +6696,9 @@ void cmGeneratorTarget::ExpandLinkItems(
this, headTarget->LinkerLanguage));
for (std::string const& lib : libs) {
if (cm::optional<cmLinkItem> maybeItem = this->LookupLinkItem(
lib, cge->GetBacktrace(), &scope,
field == LinkInterfaceField::Libraries ? LookupSelf::No
: LookupSelf::Yes)) {
lib, cge->GetBacktrace(), &scope, LookupSelf::No)) {
cmLinkItem item = std::move(*maybeItem);
if (field == LinkInterfaceField::HeadInclude) {
iface.HeadInclude.emplace_back(std::move(item));
continue;
}
if (field == LinkInterfaceField::HeadExclude) {
iface.HeadExclude.emplace_back(std::move(item));
continue;
}
if (!item.Target) {
// Report explicitly linked object files separately.
std::string const& maybeObj = item.AsStr();
@@ -7181,9 +7169,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
this->GetPolicyStatusCMP0022() != cmPolicies::WARN);
if (cmp0022NEW) {
// CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES.
haveExplicitLibraries = !this->Target->GetLinkInterfaceEntries().empty() ||
!this->Target->GetLinkInterfaceDirectEntries().empty() ||
!this->Target->GetLinkInterfaceDirectExcludeEntries().empty();
haveExplicitLibraries = !this->Target->GetLinkInterfaceEntries().empty();
} else {
// CMP0022 OLD behavior is to use LINK_INTERFACE_LIBRARIES if set on a
// shared lib or executable.
@@ -7248,24 +7234,15 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
if (cmp0022NEW) {
// The interface libraries are specified by INTERFACE_LINK_LIBRARIES.
// Use its special representation directly to get backtraces.
this->ExpandLinkItems(
kINTERFACE_LINK_LIBRARIES, this->Target->GetLinkInterfaceEntries(),
config, headTarget, interfaceFor, LinkInterfaceField::Libraries, iface);
this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES_DIRECT,
this->Target->GetLinkInterfaceDirectEntries(),
config, headTarget, interfaceFor,
LinkInterfaceField::HeadInclude, iface);
this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE,
this->Target->GetLinkInterfaceDirectExcludeEntries(),
config, headTarget, interfaceFor,
LinkInterfaceField::HeadExclude, iface);
this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES,
this->Target->GetLinkInterfaceEntries(), config,
headTarget, interfaceFor, iface);
} else if (explicitLibrariesCMP0022OLD) {
// The interface libraries have been explicitly set in pre-CMP0022 style.
std::vector<BT<std::string>> entries;
entries.emplace_back(*explicitLibrariesCMP0022OLD);
this->ExpandLinkItems(linkIfacePropCMP0022OLD, cmMakeRange(entries),
config, headTarget, interfaceFor,
LinkInterfaceField::Libraries, iface);
config, headTarget, interfaceFor, iface);
}
// If the link interface is explicit, do not fall back to the link impl.
@@ -7285,8 +7262,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
cmLinkInterface ifaceNew;
this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES,
this->Target->GetLinkInterfaceEntries(), config,
headTarget, interfaceFor,
LinkInterfaceField::Libraries, ifaceNew);
headTarget, interfaceFor, ifaceNew);
if (ifaceNew.Libraries != iface.Libraries) {
std::string oldLibraries = cmJoin(impl->Libraries, ";");
std::string newLibraries = cmJoin(ifaceNew.Libraries, ";");
@@ -7426,17 +7402,8 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
iface.LibrariesDone = true;
iface.Multiplicity = info->Multiplicity;
cmExpandList(info->Languages, iface.Languages);
this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES_DIRECT,
cmMakeRange(info->LibrariesHeadInclude), config,
headTarget, interfaceFor,
LinkInterfaceField::HeadInclude, iface);
this->ExpandLinkItems(kINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE,
cmMakeRange(info->LibrariesHeadExclude), config,
headTarget, interfaceFor,
LinkInterfaceField::HeadExclude, iface);
this->ExpandLinkItems(info->LibrariesProp, cmMakeRange(info->Libraries),
config, headTarget, interfaceFor,
LinkInterfaceField::Libraries, iface);
config, headTarget, interfaceFor, iface);
std::vector<std::string> deps = cmExpandedList(info->SharedDeps);
LookupLinkItemScope scope{ this->LocalGenerator };
for (std::string const& dep : deps) {
@@ -7529,14 +7496,6 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
}
}
}
for (BT<std::string> const& entry :
this->Target->GetLinkInterfaceDirectEntries()) {
info.LibrariesHeadInclude.emplace_back(entry);
}
for (BT<std::string> const& entry :
this->Target->GetLinkInterfaceDirectExcludeEntries()) {
info.LibrariesHeadExclude.emplace_back(entry);
}
if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
if (loc) {
info.LibName = *loc;
@@ -7970,112 +7929,6 @@ bool cmGeneratorTarget::IsNullImpliedByLinkLibraries(
return cm::contains(this->LinkImplicitNullProperties, p);
}
namespace {
class TransitiveLinkImpl
{
cmGeneratorTarget const* Self;
std::string const& Config;
cmLinkImplementation& Impl;
std::set<cmLinkItem> Emitted;
std::set<cmLinkItem> Excluded;
std::unordered_set<cmGeneratorTarget const*> Followed;
void Follow(cmGeneratorTarget const* target);
public:
TransitiveLinkImpl(cmGeneratorTarget const* self, std::string const& config,
cmLinkImplementation& impl)
: Self(self)
, Config(config)
, Impl(impl)
{
}
void Compute();
};
void TransitiveLinkImpl::Follow(cmGeneratorTarget const* target)
{
if (!target || !this->Followed.insert(target).second ||
target->GetPolicyStatusCMP0022() == cmPolicies::OLD ||
target->GetPolicyStatusCMP0022() == cmPolicies::WARN) {
return;
}
// Get this target's usage requirements.
cmLinkInterfaceLibraries const* iface = target->GetLinkInterfaceLibraries(
this->Config, this->Self, LinkInterfaceFor::Usage);
if (!iface) {
return;
}
if (iface->HadContextSensitiveCondition) {
this->Impl.HadContextSensitiveCondition = true;
}
// Process 'INTERFACE_LINK_LIBRARIES_DIRECT' usage requirements.
for (cmLinkItem const& item : iface->HeadInclude) {
// Inject direct dependencies from the item's usage requirements
// before the item itself.
this->Follow(item.Target);
// Add the item itself, but at most once.
if (this->Emitted.insert(item).second) {
this->Impl.Libraries.emplace_back(item, /* checkCMP0027= */ false);
}
}
// Follow transitive dependencies.
for (cmLinkItem const& item : iface->Libraries) {
this->Follow(item.Target);
}
// Record exclusions from 'INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE'
// usage requirements.
for (cmLinkItem const& item : iface->HeadExclude) {
this->Excluded.insert(item);
}
}
void TransitiveLinkImpl::Compute()
{
// Save the original items and start with an empty list.
std::vector<cmLinkImplItem> original = std::move(this->Impl.Libraries);
// Avoid injecting any original items as usage requirements.
// This gives LINK_LIBRARIES final control over the order
// if it explicitly lists everything.
this->Emitted.insert(original.cbegin(), original.cend());
// Process each original item.
for (cmLinkImplItem& item : original) {
// Inject direct dependencies listed in 'INTERFACE_LINK_LIBRARIES_DIRECT'
// usage requirements before the item itself.
this->Follow(item.Target);
// Add the item itself.
this->Impl.Libraries.emplace_back(std::move(item));
}
// Remove items listed in 'INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE'
// usage requirements found through any dependency above.
this->Impl.Libraries.erase(
std::remove_if(this->Impl.Libraries.begin(), this->Impl.Libraries.end(),
[this](cmLinkImplItem const& item) {
return this->Excluded.find(item) != this->Excluded.end();
}),
this->Impl.Libraries.end());
}
void ComputeLinkImplTransitive(cmGeneratorTarget const* self,
std::string const& config,
cmLinkImplementation& impl)
{
TransitiveLinkImpl transitiveLinkImpl(self, config, impl);
transitiveLinkImpl.Compute();
}
}
void cmGeneratorTarget::ComputeLinkImplementationLibraries(
const std::string& config, cmOptionalLinkImplementation& impl,
cmGeneratorTarget const* head) const
@@ -8182,11 +8035,6 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
cge->GetMaxLanguageStandard(this, this->MaxLanguageStandards);
}
// Update the list of direct link dependencies from usage requirements.
if (head == this) {
ComputeLinkImplTransitive(this, config, impl);
}
// Get the list of configurations considered to be DEBUG.
std::vector<std::string> debugConfigs =
this->Makefile->GetCMakeInstance()->GetDebugConfigs();

View File

@@ -1006,8 +1006,6 @@ private:
std::string Languages;
std::string LibrariesProp;
std::vector<BT<std::string>> Libraries;
std::vector<BT<std::string>> LibrariesHeadInclude;
std::vector<BT<std::string>> LibrariesHeadExclude;
std::string SharedDeps;
};
@@ -1068,16 +1066,10 @@ private:
bool IsLinkLookupScope(std::string const& n,
cmLocalGenerator const*& lg) const;
enum class LinkInterfaceField
{
Libraries,
HeadExclude,
HeadInclude,
};
void ExpandLinkItems(std::string const& prop, cmBTStringRange entries,
std::string const& config,
const cmGeneratorTarget* headTarget,
LinkInterfaceFor interfaceFor, LinkInterfaceField field,
LinkInterfaceFor interfaceFor,
cmLinkInterface& iface) const;
struct LookupLinkItemScope

View File

@@ -70,12 +70,6 @@ struct cmLinkInterfaceLibraries
// Object files listed in the interface.
std::vector<cmLinkItem> Objects;
// Items to be included as if directly linked by the head target.
std::vector<cmLinkItem> HeadInclude;
// Items to be excluded from direct linking by the head target.
std::vector<cmLinkItem> HeadExclude;
// Whether the list depends on a genex referencing the head target.
bool HadHeadSensitiveCondition = false;

View File

@@ -203,8 +203,6 @@ public:
std::vector<BT<std::string>> LinkDirectoriesEntries;
std::vector<BT<std::string>> LinkImplementationPropertyEntries;
std::vector<BT<std::string>> LinkInterfacePropertyEntries;
std::vector<BT<std::string>> LinkInterfaceDirectPropertyEntries;
std::vector<BT<std::string>> LinkInterfaceDirectExcludePropertyEntries;
std::vector<BT<std::string>> HeaderSetsEntries;
std::vector<BT<std::string>> InterfaceHeaderSetsEntries;
std::vector<std::pair<cmTarget::TLLSignature, cmListFileContext>>
@@ -1144,16 +1142,6 @@ cmBTStringRange cmTarget::GetLinkInterfaceEntries() const
return cmMakeRange(this->impl->LinkInterfacePropertyEntries);
}
cmBTStringRange cmTarget::GetLinkInterfaceDirectEntries() const
{
return cmMakeRange(this->impl->LinkInterfaceDirectPropertyEntries);
}
cmBTStringRange cmTarget::GetLinkInterfaceDirectExcludeEntries() const
{
return cmMakeRange(this->impl->LinkInterfaceDirectExcludePropertyEntries);
}
cmBTStringRange cmTarget::GetHeaderSetsEntries() const
{
return cmMakeRange(this->impl->HeaderSetsEntries);
@@ -1198,8 +1186,6 @@ MAKE_PROP(HEADER_SET);
MAKE_PROP(HEADER_SETS);
MAKE_PROP(INTERFACE_HEADER_SETS);
MAKE_PROP(INTERFACE_LINK_LIBRARIES);
MAKE_PROP(INTERFACE_LINK_LIBRARIES_DIRECT);
MAKE_PROP(INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE);
#undef MAKE_PROP
}
@@ -1331,19 +1317,6 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value)
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
this->impl->LinkInterfacePropertyEntries.emplace_back(value, lfbt);
}
} else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT) {
this->impl->LinkInterfaceDirectPropertyEntries.clear();
if (value) {
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
this->impl->LinkInterfaceDirectPropertyEntries.emplace_back(value, lfbt);
}
} else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE) {
this->impl->LinkInterfaceDirectExcludePropertyEntries.clear();
if (value) {
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
this->impl->LinkInterfaceDirectExcludePropertyEntries.emplace_back(value,
lfbt);
}
} else if (prop == propSOURCES) {
this->impl->SourceEntries.clear();
if (value) {
@@ -1602,17 +1575,6 @@ void cmTarget::AppendProperty(const std::string& prop,
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
this->impl->LinkInterfacePropertyEntries.emplace_back(value, lfbt);
}
} else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT) {
if (!value.empty()) {
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
this->impl->LinkInterfaceDirectPropertyEntries.emplace_back(value, lfbt);
}
} else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE) {
if (!value.empty()) {
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
this->impl->LinkInterfaceDirectExcludePropertyEntries.emplace_back(value,
lfbt);
}
} else if (prop == "SOURCES") {
cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace();
this->impl->SourceEntries.emplace_back(value, lfbt);
@@ -1923,8 +1885,6 @@ cmValue cmTarget::GetProperty(const std::string& prop) const
propHEADER_SETS,
propINTERFACE_HEADER_SETS,
propINTERFACE_LINK_LIBRARIES,
propINTERFACE_LINK_LIBRARIES_DIRECT,
propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE,
};
if (specialProps.count(prop)) {
if (prop == propC_STANDARD || prop == propCXX_STANDARD ||
@@ -1954,25 +1914,6 @@ cmValue cmTarget::GetProperty(const std::string& prop) const
output = cmJoin(this->impl->LinkInterfacePropertyEntries, ";");
return cmValue(output);
}
if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT) {
if (this->impl->LinkInterfaceDirectPropertyEntries.empty()) {
return nullptr;
}
static std::string output;
output = cmJoin(this->impl->LinkInterfaceDirectPropertyEntries, ";");
return cmValue(output);
}
if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE) {
if (this->impl->LinkInterfaceDirectExcludePropertyEntries.empty()) {
return nullptr;
}
static std::string output;
output =
cmJoin(this->impl->LinkInterfaceDirectExcludePropertyEntries, ";");
return cmValue(output);
}
// the type property returns what type the target is
if (prop == propTYPE) {
return cmValue(cmState::GetTargetTypeName(this->GetType()));

View File

@@ -269,8 +269,6 @@ public:
cmBTStringRange GetLinkImplementationEntries() const;
cmBTStringRange GetLinkInterfaceEntries() const;
cmBTStringRange GetLinkInterfaceDirectEntries() const;
cmBTStringRange GetLinkInterfaceDirectExcludeEntries() const;
cmBTStringRange GetHeaderSetsEntries() const;

View File

@@ -3589,8 +3589,6 @@ if(BUILD_TESTING)
--test-command InterfaceLinkLibraries)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/InterfaceLinkLibraries")
ADD_TEST_MACRO(InterfaceLinkLibrariesDirect)
if(NOT CMake_TEST_EXTERNAL_CMAKE)
add_subdirectory(CMakeTests)
endif()

View File

@@ -163,16 +163,6 @@ install(
cmake_policy(PUSH)
cmake_policy(SET CMP0022 NEW)
# Test control over direct linking.
include(../../InterfaceLinkLibrariesDirect/testStaticLibPlugin.cmake)
include(../../InterfaceLinkLibrariesDirect/testSharedLibWithHelper.cmake)
include(../../InterfaceLinkLibrariesDirect/testExeWithPluginHelper.cmake)
if(NOT maybe_OBJECTS_DESTINATION)
target_compile_definitions(testSharedLibHelperObj INTERFACE testSharedLibHelperObj_NO_OBJECT)
target_compile_definitions(testExePluginHelperObj INTERFACE testExePluginHelperObj_NO_OBJECT)
endif()
# Test exporting dependent libraries into different exports
add_library(testLibRequired testLibRequired.c)
add_library(testLibDepends testLibDepends.c)
@@ -554,9 +544,6 @@ install(
testLibDeprecation
testLibCycleA testLibCycleB
testLibNoSONAME
testStaticLibWithPlugin testStaticLibPluginExtra testStaticLibPlugin
testSharedLibWithHelper testSharedLibHelperObj
testExeWithPluginHelper testExePluginHelperObj
testMod1 testMod2
cmp0022NEW cmp0022OLD
TopDirLib SubDirLinkA
@@ -632,9 +619,6 @@ export(TARGETS testExe2 testLib4 testLib5 testLib6 testLib7 testExe3 testExe4 te
testLib4lib testLib4libdbg testLib4libopt
testLibCycleA testLibCycleB
testLibNoSONAME
testStaticLibWithPlugin testStaticLibPluginExtra testStaticLibPlugin
testSharedLibWithHelper testSharedLibHelperObj
testExeWithPluginHelper testExePluginHelperObj
testMod1 testMod2
testLibPerConfigDest
NAMESPACE bld_

View File

@@ -68,23 +68,16 @@ target_link_libraries(imp_testExe1
exp_testLib7
exp_testLibCycleA
exp_testLibPerConfigDest
exp_testStaticLibWithPlugin
)
add_library(imp_testInterfaceInclude1 STATIC imp_testInterfaceInclude1.c)
target_include_directories(imp_testInterfaceInclude1 SYSTEM PRIVATE testInterfaceIncludeSystem)
target_link_libraries(imp_testInterfaceInclude1 PRIVATE exp_testInterfaceIncludeUser)
add_executable(imp_UseSharedLibWithHelper1 ../../../InterfaceLinkLibrariesDirect/UseSharedLibWithHelper.c)
target_link_libraries(imp_UseSharedLibWithHelper1 PRIVATE exp_testSharedLibWithHelper testSharedLibHelperExclude)
# Try building a plugin to an executable imported from the install tree.
add_library(imp_mod1 MODULE imp_mod1.c)
target_link_libraries(imp_mod1 exp_testExe2)
add_library(imp_ExePlugin1 MODULE ../../../InterfaceLinkLibrariesDirect/ExePlugin.c)
target_link_libraries(imp_ExePlugin1 PRIVATE exp_testExeWithPluginHelper testExePluginHelperExclude)
# Try referencing an executable imported from the build tree.
add_custom_command(
OUTPUT ${Import_BINARY_DIR}/bld_generated.c
@@ -119,7 +112,6 @@ target_link_libraries(imp_testExe1b
bld_testLib7
bld_testLibCycleA
bld_testLibPerConfigDest
bld_testStaticLibWithPlugin
)
add_library(imp_testInterfaceInclude1b STATIC imp_testInterfaceInclude1.c)
@@ -191,16 +183,10 @@ target_link_libraries(SubDirLink_bld PRIVATE bld_TopDirLib bld_SubDirLinkA)
add_executable(SubDirLink_exp SubDirLink.c)
target_link_libraries(SubDirLink_exp PRIVATE exp_TopDirLib exp_SubDirLinkA)
add_executable(imp_UseSharedLibWithHelper1b ../../../InterfaceLinkLibrariesDirect/UseSharedLibWithHelper.c)
target_link_libraries(imp_UseSharedLibWithHelper1b PRIVATE bld_testSharedLibWithHelper testSharedLibHelperExclude)
# Try building a plugin to an executable imported from the build tree.
add_library(imp_mod1b MODULE imp_mod1.c)
target_link_libraries(imp_mod1b bld_testExe2)
add_library(imp_ExePlugin1b MODULE ../../../InterfaceLinkLibrariesDirect/ExePlugin.c)
target_link_libraries(imp_ExePlugin1b PRIVATE bld_testExeWithPluginHelper testExePluginHelperExclude)
# Export/CMakeLists.txt pretends the RelWithDebInfo (as well as Debug)
# configuration should link to debug libs.
foreach(c DEBUG RELWITHDEBINFO)

View File

@@ -10,7 +10,6 @@ extern int testLib6(void);
extern int testLib7(void);
extern int testLibCycleA1(void);
extern int testLibPerConfigDest(void);
extern int testStaticLibPlugin(void);
/* Switch a symbol between debug and optimized builds to make sure the
proper library is found from the testLib4 link interface. */
@@ -25,7 +24,6 @@ int main()
{
return (testLib2() + generated_by_testExe1() + testLib3() + testLib4() +
testLib5() + testLib6() + testLib7() + testLibCycleA1() +
testLibPerConfigDest() + testStaticLibPlugin() +
generated_by_testExe3() + generated_by_testExe4() + testLib4lib() +
testLib4libcfg());
testLibPerConfigDest() + generated_by_testExe3() +
generated_by_testExe4() + testLib4lib() + testLib4libcfg());
}

View File

@@ -1,156 +0,0 @@
cmake_minimum_required(VERSION 3.21)
project(InterfaceLinkLibrariesDirect C)
include(testStaticLibPlugin.cmake)
add_executable(InterfaceLinkLibrariesDirect main.c)
target_link_libraries(InterfaceLinkLibrariesDirect PRIVATE testStaticLibWithPlugin)
include(testSharedLibWithHelper.cmake)
add_executable(UseSharedLibWithHelper UseSharedLibWithHelper.c)
target_link_libraries(UseSharedLibWithHelper PRIVATE testSharedLibWithHelper testSharedLibHelperExclude)
include(testExeWithPluginHelper.cmake)
add_library(ExePlugin MODULE ExePlugin.c)
target_link_libraries(ExePlugin PRIVATE testExeWithPluginHelper testExePluginHelperExclude)
#----------------------------------------------------------------------------
# Offer usage requirements and symbols to be used through static libs below.
add_library(A STATIC
a_always.c
# Good symbols that direct_from_A libraries poison if incorrectly used.
a_not_direct_from_A.c
a_not_direct_from_A_for_exe.c
a_not_direct_from_A_optional.c
# Bad symbols in direct_from_A libraries below to ensure they come first.
a_poison_direct_from_A.c
a_poison_direct_from_A_for_exe.c
a_poison_direct_from_A_optional.c
)
# Propagates as usage requirement from A.
add_library(direct_from_A STATIC direct_from_A.c direct_from_A_poison.c)
target_compile_definitions(direct_from_A INTERFACE DEF_DIRECT_FROM_A)
set_property(TARGET A APPEND PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT direct_from_A)
# Propagates as usage requirement from A, but only for executables.
add_library(direct_from_A_for_exe STATIC direct_from_A_for_exe.c direct_from_A_for_exe_poison.c)
target_compile_definitions(direct_from_A_for_exe INTERFACE DEF_DIRECT_FROM_A_FOR_EXE)
set_property(TARGET A APPEND PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT
"$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:direct_from_A_for_exe>")
# Propagates as usage requirement from A, but only for targets that opt-in.
add_library(direct_from_A_optional STATIC direct_from_A_optional.c direct_from_A_optional_poison.c)
target_compile_definitions(direct_from_A_optional INTERFACE DEF_DIRECT_FROM_A_OPTIONAL)
set_property(TARGET A APPEND PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT
"$<$<BOOL:$<TARGET_PROPERTY:A_LINK_OPTIONAL>>:direct_from_A_optional>")
# Uses and propagates A's usage requirements.
# Does not use the exe-only or optional usage requirements.
add_library(static_A_public STATIC static_A_public.c)
target_link_libraries(static_A_public PUBLIC A)
# Uses A's usage requirements, but does not propagate them.
# Does not use the exe-only usage requirement. Does use the optional one.
add_library(static_A_private STATIC static_A_private.c)
target_link_libraries(static_A_private PRIVATE A)
set_property(TARGET static_A_private PROPERTY A_LINK_OPTIONAL 1)
# Uses A's usage requirements, including an optional one.
add_executable(exe_use_static_A_public exe_use_static_A_public.c)
target_link_libraries(exe_use_static_A_public PRIVATE static_A_public)
set_property(TARGET exe_use_static_A_public PROPERTY A_LINK_OPTIONAL 1)
# Does not use A's usage requirements.
add_executable(exe_use_static_A_private exe_use_static_A_private.c)
target_link_libraries(exe_use_static_A_private PRIVATE static_A_private)
#----------------------------------------------------------------------------
# Test how original and injected dependencies get ordered.
# A bunch of static libraries that need to be linked in alphabetic order.
# Each library has an extra source to poison all symbols meant to be
# provided by earlier libraries. This enforces ordering on platforms
# whose linkers re-visit static libraries.
add_library(order_A STATIC order_A.c)
add_library(order_B STATIC order_B.c order_B_poison.c)
add_library(order_C STATIC order_C.c order_C_poison.c)
add_library(order_D STATIC order_D.c order_D_poison.c)
add_library(order_E STATIC order_E.c order_E_poison.c)
add_library(order_F STATIC order_F.c order_F_poison.c)
add_library(order_G STATIC order_G.c order_G_poison.c)
add_library(order_H STATIC order_H.c order_H_poison.c)
add_library(order_I STATIC order_I.c order_I_poison.c)
add_library(order_J STATIC order_J.c order_J_poison.c)
# An executable to drive linking.
add_executable(order_main order_main.c)
# In the following diagram, connection by a slash means the top
# target lists the bottom target in a link interface property:
#
# \ => INTERFACE_LINK_LIBRARIES
# / => INTERFACE_LINK_LIBRARIES_DIRECT
#
# The top of each tree represents an entry in the exe's LINK_LIBRARIES.
# CMake should evaluate this graph to generate the proper link order.
#
# D H
# / \ / \
# B J F I
# / / / / \
# A C E G J
set_property(TARGET order_main PROPERTY LINK_LIBRARIES order_D order_H)
set_property(TARGET order_D PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT order_B)
set_property(TARGET order_D PROPERTY INTERFACE_LINK_LIBRARIES order_J)
set_property(TARGET order_B PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT order_A)
set_property(TARGET order_J PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT order_C)
set_property(TARGET order_H PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT order_F)
set_property(TARGET order_H PROPERTY INTERFACE_LINK_LIBRARIES order_I)
set_property(TARGET order_F PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT order_E)
set_property(TARGET order_I PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT order_G)
set_property(TARGET order_I PROPERTY INTERFACE_LINK_LIBRARIES order_J)
#----------------------------------------------------------------------------
# Test that the original LINK_LIBRARIES cannot be re-ordered by injection
# from usage requirements.
# A bunch of static libraries that need to be linked in alphabetic order.
# Each library has an extra source to poison all symbols meant to be
# provided by earlier libraries. This enforces ordering on platforms
# whose linkers re-visit static libraries.
add_library(force_A STATIC order_A.c)
add_library(force_B STATIC order_B.c order_B_poison.c)
add_library(force_C STATIC order_C.c order_C_poison.c)
add_library(force_D STATIC order_D.c order_D_poison.c)
add_library(force_E STATIC order_E.c order_E_poison.c)
add_library(force_F STATIC order_F.c order_F_poison.c)
add_library(force_G STATIC order_G.c order_G_poison.c)
add_library(force_H STATIC order_H.c order_H_poison.c)
add_library(force_I STATIC order_I.c order_I_poison.c)
add_library(force_J STATIC order_J.c order_J_poison.c)
# An executable to drive linking.
add_executable(force_main order_main.c)
# The executable explicitly lists all the libraries in the right order.
target_link_libraries(force_main PRIVATE force_A force_B force_C force_D force_E force_F force_G force_H)
# Add legitimate normal dependencies.
set_property(TARGET force_D PROPERTY INTERFACE_LINK_LIBRARIES force_J)
set_property(TARGET force_H PROPERTY INTERFACE_LINK_LIBRARIES force_I)
set_property(TARGET force_I PROPERTY INTERFACE_LINK_LIBRARIES force_J)
# Add bogus injected direct dependencies to verify that they do not
# change the original order of LINK_LIBRARIES.
set_property(TARGET force_A PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT force_B)
set_property(TARGET force_B PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT force_C)
set_property(TARGET force_C PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT force_D)
set_property(TARGET force_D PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT force_E)
set_property(TARGET force_E PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT force_F)
set_property(TARGET force_F PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT force_G)
set_property(TARGET force_G PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT force_H)

View File

@@ -1,21 +0,0 @@
extern int testExePluginHelperObj(int n);
#ifdef testExePluginHelperObj_NO_OBJECT
int testExePluginHelperObj(int n)
{
return n;
}
#endif
#if defined(_WIN32)
__declspec(dllimport)
#endif
int testExePluginAPI(int n);
#if defined(_WIN32)
__declspec(dllexport)
#endif
int testExePlugin(int n)
{
return testExePluginAPI(n) + testExePluginHelperObj(n);
}

View File

@@ -1,18 +0,0 @@
extern int testSharedLibHelperObj(int n);
#ifdef testSharedLibHelperObj_NO_OBJECT
int testSharedLibHelperObj(int n)
{
return n;
}
#endif
#if defined(_WIN32)
__declspec(dllimport)
#endif
int testSharedLibWithHelper(int n);
int main(void)
{
return testSharedLibWithHelper(0) + testSharedLibHelperObj(0);
}

View File

@@ -1,3 +0,0 @@
void a_always(void)
{
}

View File

@@ -1,3 +0,0 @@
void not_direct_from_A(void)
{
}

View File

@@ -1,3 +0,0 @@
void not_direct_from_A_for_exe(void)
{
}

View File

@@ -1,3 +0,0 @@
void not_direct_from_A_optional(void)
{
}

View File

@@ -1,5 +0,0 @@
extern void poison_direct_from_A(void);
void direct_from_A(void)
{
poison_direct_from_A();
}

View File

@@ -1,5 +0,0 @@
extern void poison_direct_from_A_for_exe(void);
void direct_from_A_for_exe(void)
{
poison_direct_from_A_for_exe();
}

View File

@@ -1,5 +0,0 @@
extern void poison_direct_from_A_optional(void);
void direct_from_A_optional(void)
{
poison_direct_from_A_optional();
}

View File

@@ -1,3 +0,0 @@
void direct_from_A(void)
{
}

View File

@@ -1,3 +0,0 @@
void direct_from_A_for_exe(void)
{
}

View File

@@ -1,5 +0,0 @@
extern void poison_not_direct_from_A_for_exe(void);
void not_direct_from_A_for_exe(void)
{
poison_not_direct_from_A_for_exe();
}

View File

@@ -1,3 +0,0 @@
void direct_from_A_optional(void)
{
}

View File

@@ -1,5 +0,0 @@
extern void poison_not_direct_from_A_optional(void);
void not_direct_from_A_optional(void)
{
poison_not_direct_from_A_optional();
}

View File

@@ -1,5 +0,0 @@
extern void poison_not_direct_from_A(void);
void not_direct_from_A(void)
{
poison_not_direct_from_A();
}

View File

@@ -1,23 +0,0 @@
#ifdef DEF_DIRECT_FROM_A
# error "DEF_DIRECT_FROM_A incorrectly defined"
#endif
#ifdef DEF_DIRECT_FROM_A_FOR_EXE
# error "DEF_DIRECT_FROM_A_FOR_EXE incorrectly defined"
#endif
#ifdef DEF_DIRECT_FROM_A_OPTIONAL
# error "DEF_DIRECT_FROM_A_OPTIONAL incorrectly defined"
#endif
extern void static_A_private(void);
extern void not_direct_from_A(void);
extern void not_direct_from_A_for_exe(void);
extern void not_direct_from_A_optional(void);
int main(void)
{
static_A_private();
not_direct_from_A();
not_direct_from_A_for_exe();
not_direct_from_A_optional();
return 0;
}

View File

@@ -1,23 +0,0 @@
#ifndef DEF_DIRECT_FROM_A
# error "DEF_DIRECT_FROM_A incorrectly not defined"
#endif
#ifndef DEF_DIRECT_FROM_A_FOR_EXE
# error "DEF_DIRECT_FROM_A_FOR_EXE incorrectly not defined"
#endif
#ifndef DEF_DIRECT_FROM_A_OPTIONAL
# error "DEF_DIRECT_FROM_A_OPTIONAL incorrectly not defined"
#endif
extern void static_A_public(void);
extern void direct_from_A(void);
extern void direct_from_A_for_exe(void);
extern void direct_from_A_optional(void);
int main(void)
{
static_A_public();
direct_from_A();
direct_from_A_for_exe();
direct_from_A_optional();
return 0;
}

View File

@@ -1,5 +0,0 @@
extern int testStaticLibPlugin(void);
int main(void)
{
return testStaticLibPlugin();
}

View File

@@ -1,5 +0,0 @@
extern void order_B(void);
void order_A(void)
{
order_B();
}

View File

@@ -1,5 +0,0 @@
extern void order_C(void);
void order_B(void)
{
order_C();
}

View File

@@ -1,6 +0,0 @@
extern void order_B_poison(void);
void order_A(void)
{
order_B_poison();
}

View File

@@ -1,5 +0,0 @@
extern void order_D(void);
void order_C(void)
{
order_D();
}

View File

@@ -1,11 +0,0 @@
extern void order_C_poison(void);
void order_A(void)
{
order_C_poison();
}
void order_B(void)
{
order_C_poison();
}

View File

@@ -1,5 +0,0 @@
extern void order_E(void);
void order_D(void)
{
order_E();
}

View File

@@ -1,16 +0,0 @@
extern void order_D_poison(void);
void order_A(void)
{
order_D_poison();
}
void order_B(void)
{
order_D_poison();
}
void order_C(void)
{
order_D_poison();
}

View File

@@ -1,5 +0,0 @@
extern void order_F(void);
void order_E(void)
{
order_F();
}

View File

@@ -1,21 +0,0 @@
extern void order_E_poison(void);
void order_A(void)
{
order_E_poison();
}
void order_B(void)
{
order_E_poison();
}
void order_C(void)
{
order_E_poison();
}
void order_D(void)
{
order_E_poison();
}

View File

@@ -1,5 +0,0 @@
extern void order_G(void);
void order_F(void)
{
order_G();
}

View File

@@ -1,26 +0,0 @@
extern void order_F_poison(void);
void order_A(void)
{
order_F_poison();
}
void order_B(void)
{
order_F_poison();
}
void order_C(void)
{
order_F_poison();
}
void order_D(void)
{
order_F_poison();
}
void order_E(void)
{
order_F_poison();
}

View File

@@ -1,5 +0,0 @@
extern void order_H(void);
void order_G(void)
{
order_H();
}

View File

@@ -1,31 +0,0 @@
extern void order_G_poison(void);
void order_A(void)
{
order_G_poison();
}
void order_B(void)
{
order_G_poison();
}
void order_C(void)
{
order_G_poison();
}
void order_D(void)
{
order_G_poison();
}
void order_E(void)
{
order_G_poison();
}
void order_F(void)
{
order_G_poison();
}

View File

@@ -1,5 +0,0 @@
extern void order_I(void);
void order_H(void)
{
order_I();
}

View File

@@ -1,36 +0,0 @@
extern void order_H_poison(void);
void order_A(void)
{
order_H_poison();
}
void order_B(void)
{
order_H_poison();
}
void order_C(void)
{
order_H_poison();
}
void order_D(void)
{
order_H_poison();
}
void order_E(void)
{
order_H_poison();
}
void order_F(void)
{
order_H_poison();
}
void order_G(void)
{
order_H_poison();
}

View File

@@ -1,5 +0,0 @@
extern void order_J(void);
void order_I(void)
{
order_J();
}

View File

@@ -1,41 +0,0 @@
extern void order_I_poison(void);
void order_A(void)
{
order_I_poison();
}
void order_B(void)
{
order_I_poison();
}
void order_C(void)
{
order_I_poison();
}
void order_D(void)
{
order_I_poison();
}
void order_E(void)
{
order_I_poison();
}
void order_F(void)
{
order_I_poison();
}
void order_G(void)
{
order_I_poison();
}
void order_H(void)
{
order_I_poison();
}

View File

@@ -1,3 +0,0 @@
void order_J(void)
{
}

View File

@@ -1,46 +0,0 @@
extern void order_J_poison(void);
void order_A(void)
{
order_J_poison();
}
void order_B(void)
{
order_J_poison();
}
void order_C(void)
{
order_J_poison();
}
void order_D(void)
{
order_J_poison();
}
void order_E(void)
{
order_J_poison();
}
void order_F(void)
{
order_J_poison();
}
void order_G(void)
{
order_J_poison();
}
void order_H(void)
{
order_J_poison();
}
void order_I(void)
{
order_J_poison();
}

View File

@@ -1,6 +0,0 @@
extern void order_A(void);
int main(void)
{
order_A();
return 0;
}

View File

@@ -1,16 +0,0 @@
#ifndef DEF_DIRECT_FROM_A
# error "DEF_DIRECT_FROM_A incorrectly not defined"
#endif
#ifdef DEF_DIRECT_FROM_A_FOR_EXE
# error "DEF_DIRECT_FROM_A_FOR_EXE incorrectly defined"
#endif
#ifndef DEF_DIRECT_FROM_A_OPTIONAL
# error "DEF_DIRECT_FROM_A_OPTIONAL incorrectly not defined"
#endif
extern void a_always(void);
void static_A_private(void)
{
a_always();
}

View File

@@ -1,16 +0,0 @@
#ifndef DEF_DIRECT_FROM_A
# error "DEF_DIRECT_FROM_A incorrectly not defined"
#endif
#ifdef DEF_DIRECT_FROM_A_FOR_EXE
# error "DEF_DIRECT_FROM_A_FOR_EXE incorrectly defined"
#endif
#ifdef DEF_DIRECT_FROM_A_OPTIONAL
# error "DEF_DIRECT_FROM_A_OPTIONAL incorrectly defined"
#endif
extern void a_always(void);
void static_A_public(void)
{
a_always();
}

View File

@@ -1,4 +0,0 @@
int testExePluginHelperObj(int n)
{
return n;
}

View File

@@ -1,12 +0,0 @@
#ifdef _WIN32
__declspec(dllexport)
#endif
int testExePluginAPI(int n)
{
return n;
}
int main(void)
{
return 0;
}

View File

@@ -1,7 +0,0 @@
# Logic common to InterfaceLinkLibrariesDirect and ExportImport tests.
set(src ${CMAKE_CURRENT_LIST_DIR})
add_executable(testExeWithPluginHelper ${src}/testExeWithPluginHelper.c)
add_library(testExePluginHelperObj OBJECT ${src}/testExePluginHelperObj.c)
set_property(TARGET testExeWithPluginHelper PROPERTY ENABLE_EXPORTS 1)
set_property(TARGET testExeWithPluginHelper PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT $<TARGET_NAME:testExePluginHelperObj>)
set_property(TARGET testExeWithPluginHelper PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE $<1:testExePluginHelperExclude>)

View File

@@ -1,4 +0,0 @@
int testSharedLibHelperObj(int n)
{
return n;
}

View File

@@ -1,7 +0,0 @@
#ifdef _WIN32
__declspec(dllexport)
#endif
int testSharedLibWithHelper(int n)
{
return n;
}

View File

@@ -1,6 +0,0 @@
# Logic common to InterfaceLinkLibrariesDirect and ExportImport tests.
set(src ${CMAKE_CURRENT_LIST_DIR})
add_library(testSharedLibWithHelper SHARED ${src}/testSharedLibWithHelper.c)
add_library(testSharedLibHelperObj OBJECT ${src}/testSharedLibHelperObj.c)
set_property(TARGET testSharedLibWithHelper PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT $<TARGET_NAME:testSharedLibHelperObj>)
set_property(TARGET testSharedLibWithHelper PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE $<1:testSharedLibHelperExclude>)

View File

@@ -1,6 +0,0 @@
extern int testStaticLibWithPlugin1(void);
extern int testStaticLibPluginExtra(void);
int testStaticLibPlugin(void)
{
return testStaticLibWithPlugin1() + testStaticLibPluginExtra();
}

View File

@@ -1,14 +0,0 @@
# Logic common to InterfaceLinkLibrariesDirect and ExportImport tests.
set(src ${CMAKE_CURRENT_LIST_DIR})
add_library(testStaticLibWithPlugin STATIC
${src}/testStaticLibWithPlugin1.c # used by testStaticLibPlugin
${src}/testStaticLibWithPlugin2.c # used by testStaticLibPluginExtra
${src}/testStaticLibWithPluginBad1.c # link error if not after testStaticLibPlugin
${src}/testStaticLibWithPluginBad2.c # link error if not after testStaticLibPluginExtra
)
add_library(testStaticLibPluginExtra STATIC ${src}/testStaticLibPluginExtra.c)
add_library(testStaticLibPlugin STATIC ${src}/testStaticLibPlugin.c)
target_link_libraries(testStaticLibPlugin PUBLIC testStaticLibWithPlugin testStaticLibPluginExtra)
target_link_libraries(testStaticLibPluginExtra PUBLIC testStaticLibWithPlugin)
set_property(TARGET testStaticLibWithPlugin PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT testStaticLibPlugin)
set_property(TARGET testStaticLibWithPlugin PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE testStaticLibWithPlugin)

View File

@@ -1,5 +0,0 @@
extern int testStaticLibWithPlugin2(void);
int testStaticLibPluginExtra(void)
{
return testStaticLibWithPlugin2();
}

View File

@@ -1,4 +0,0 @@
int testStaticLibWithPlugin1(void)
{
return 0;
}

View File

@@ -1,4 +0,0 @@
int testStaticLibWithPlugin2(void)
{
return 0;
}

View File

@@ -1,6 +0,0 @@
/* Produce an error if if the object compiled from this source is used. */
extern int testStaticLibWithPlugin_linked_before_testStaticLibPlugin(void);
int testStaticLibPlugin(void)
{
return testStaticLibWithPlugin_linked_before_testStaticLibPlugin();
}

View File

@@ -1,7 +0,0 @@
/* Produce an error if if the object compiled from this source is used. */
extern int testStaticLibWithPlugin_linked_before_testStaticLibPluginExtra(
void);
int testStaticLibPluginExtra(void)
{
return testStaticLibWithPlugin_linked_before_testStaticLibPluginExtra();
}

View File

@@ -1,6 +0,0 @@
extern int BarObject1(void);
int main(void)
{
return BarObject1();
}

View File

@@ -1,5 +0,0 @@
extern int BarObject2(void);
int BarObject1(void)
{
return BarObject2();
}

View File

@@ -1,5 +0,0 @@
extern int BarObject3(void);
int BarObject2(void)
{
return BarObject3();
}

View File

@@ -1,4 +0,0 @@
int BarObject3(void)
{
return 0;
}

View File

@@ -9,17 +9,3 @@ add_library(FooObject2 OBJECT FooObject.c)
target_link_libraries(FooObject2 INTERFACE FooStatic)
add_executable(Transitive2 Transitive.c)
target_link_libraries(Transitive2 PRIVATE FooObject2)
add_library(FooObjectDirect OBJECT FooObject.c)
add_library(FooStaticDirect STATIC FooStatic.c)
set_property(TARGET FooStaticDirect PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT FooObjectDirect)
add_executable(TransitiveDirect Transitive.c)
target_link_libraries(TransitiveDirect PRIVATE FooStaticDirect)
add_library(BarObject1 OBJECT BarObject1.c)
add_library(BarObject2 OBJECT BarObject2.c)
add_library(BarObject3 OBJECT BarObject3.c)
set_property(TARGET BarObject1 PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT BarObject2)
set_property(TARGET BarObject2 PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT BarObject3)
add_executable(BarMain BarMain.c)
target_link_libraries(BarMain PRIVATE BarObject1)