mirror of
https://github.com/Kitware/CMake.git
synced 2026-02-22 15:10:20 -06:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@@ -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``.
|
||||
@@ -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`.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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_") ||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -269,8 +269,6 @@ public:
|
||||
cmBTStringRange GetLinkImplementationEntries() const;
|
||||
|
||||
cmBTStringRange GetLinkInterfaceEntries() const;
|
||||
cmBTStringRange GetLinkInterfaceDirectEntries() const;
|
||||
cmBTStringRange GetLinkInterfaceDirectExcludeEntries() const;
|
||||
|
||||
cmBTStringRange GetHeaderSetsEntries() const;
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
void a_always(void)
|
||||
{
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
void not_direct_from_A(void)
|
||||
{
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
void not_direct_from_A_for_exe(void)
|
||||
{
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
void not_direct_from_A_optional(void)
|
||||
{
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
extern void poison_direct_from_A(void);
|
||||
void direct_from_A(void)
|
||||
{
|
||||
poison_direct_from_A();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
extern void poison_direct_from_A_optional(void);
|
||||
void direct_from_A_optional(void)
|
||||
{
|
||||
poison_direct_from_A_optional();
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
void direct_from_A(void)
|
||||
{
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
void direct_from_A_for_exe(void)
|
||||
{
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
void direct_from_A_optional(void)
|
||||
{
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
extern void poison_not_direct_from_A(void);
|
||||
void not_direct_from_A(void)
|
||||
{
|
||||
poison_not_direct_from_A();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
extern int testStaticLibPlugin(void);
|
||||
int main(void)
|
||||
{
|
||||
return testStaticLibPlugin();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
extern void order_B(void);
|
||||
void order_A(void)
|
||||
{
|
||||
order_B();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
extern void order_C(void);
|
||||
void order_B(void)
|
||||
{
|
||||
order_C();
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
extern void order_B_poison(void);
|
||||
|
||||
void order_A(void)
|
||||
{
|
||||
order_B_poison();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
extern void order_D(void);
|
||||
void order_C(void)
|
||||
{
|
||||
order_D();
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
extern void order_C_poison(void);
|
||||
|
||||
void order_A(void)
|
||||
{
|
||||
order_C_poison();
|
||||
}
|
||||
|
||||
void order_B(void)
|
||||
{
|
||||
order_C_poison();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
extern void order_E(void);
|
||||
void order_D(void)
|
||||
{
|
||||
order_E();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
extern void order_F(void);
|
||||
void order_E(void)
|
||||
{
|
||||
order_F();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
extern void order_G(void);
|
||||
void order_F(void)
|
||||
{
|
||||
order_G();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
extern void order_H(void);
|
||||
void order_G(void)
|
||||
{
|
||||
order_H();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
extern void order_I(void);
|
||||
void order_H(void)
|
||||
{
|
||||
order_I();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
extern void order_J(void);
|
||||
void order_I(void)
|
||||
{
|
||||
order_J();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
void order_J(void)
|
||||
{
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
extern void order_A(void);
|
||||
int main(void)
|
||||
{
|
||||
order_A();
|
||||
return 0;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
int testExePluginHelperObj(int n)
|
||||
{
|
||||
return n;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int testExePluginAPI(int n)
|
||||
{
|
||||
return n;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -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>)
|
||||
@@ -1,4 +0,0 @@
|
||||
int testSharedLibHelperObj(int n)
|
||||
{
|
||||
return n;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int testSharedLibWithHelper(int n)
|
||||
{
|
||||
return n;
|
||||
}
|
||||
@@ -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>)
|
||||
@@ -1,6 +0,0 @@
|
||||
extern int testStaticLibWithPlugin1(void);
|
||||
extern int testStaticLibPluginExtra(void);
|
||||
int testStaticLibPlugin(void)
|
||||
{
|
||||
return testStaticLibWithPlugin1() + testStaticLibPluginExtra();
|
||||
}
|
||||
@@ -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)
|
||||
@@ -1,5 +0,0 @@
|
||||
extern int testStaticLibWithPlugin2(void);
|
||||
int testStaticLibPluginExtra(void)
|
||||
{
|
||||
return testStaticLibWithPlugin2();
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
int testStaticLibWithPlugin1(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
int testStaticLibWithPlugin2(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
extern int BarObject1(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return BarObject1();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
extern int BarObject2(void);
|
||||
int BarObject1(void)
|
||||
{
|
||||
return BarObject2();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
extern int BarObject3(void);
|
||||
int BarObject2(void)
|
||||
{
|
||||
return BarObject3();
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
int BarObject3(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user