mirror of
https://github.com/Kitware/CMake.git
synced 2026-04-28 01:49:23 -05:00
Merge topic 'custom-transitive-properties'
c16acd35b3GenEx: Add support for custom transitive link propertiesb9ee79b8a1GenEx: Add support for custom transitive compile properties633afa0b2ecmGeneratorExpressionDAGChecker: Make config name available in constructore64d09a729cmGeneratorTarget: Add GetLinkImplementationClosure mode for linkinga11cbcc268cmGeneratorTarget: Add TransitiveProperty constructor to help some compilersaf59289904Help: Format TARGET_PROPERTY special evaluation rules as a definition list Acked-by: Kitware Robot <kwrobot@kitware.com> Tested-by: buildbot <buildbot@kitware.com> Acked-by: alcroito <alexandru.croitor@qt.io> Merge-request: !9516
This commit is contained in:
@@ -602,6 +602,65 @@ linking consumers.
|
||||
List of files on which linking the target's consumers depends, for
|
||||
those that are executables, shared libraries, or module libraries.
|
||||
|
||||
.. _`Custom Transitive Properties`:
|
||||
|
||||
Custom Transitive Properties
|
||||
----------------------------
|
||||
|
||||
.. versionadded:: 3.30
|
||||
|
||||
The :genex:`TARGET_PROPERTY` generator expression evaluates the above
|
||||
`build specification <Target Build Specification_>`_ and
|
||||
`usage requirement <Target Usage Requirements_>`_ properties
|
||||
as builtin transitive properties. It also supports custom transitive
|
||||
properties defined by the :prop_tgt:`TRANSITIVE_COMPILE_PROPERTIES`
|
||||
and :prop_tgt:`TRANSITIVE_LINK_PROPERTIES` properties on the target
|
||||
and its link dependencies.
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
add_library(example INTERFACE)
|
||||
set_target_properties(example PROPERTIES
|
||||
TRANSITIVE_COMPILE_PROPERTIES "CUSTOM_C"
|
||||
TRANSITIVE_LINK_PROPERTIES "CUSTOM_L"
|
||||
|
||||
INTERFACE_CUSTOM_C "EXAMPLE_CUSTOM_C"
|
||||
INTERFACE_CUSTOM_L "EXAMPLE_CUSTOM_L"
|
||||
)
|
||||
|
||||
add_library(mylib STATIC mylib.c)
|
||||
target_link_libraries(mylib PRIVATE example)
|
||||
set_target_properties(mylib PROPERTIES
|
||||
CUSTOM_C "MYLIB_PRIVATE_CUSTOM_C"
|
||||
CUSTOM_L "MYLIB_PRIVATE_CUSTOM_L"
|
||||
INTERFACE_CUSTOM_C "MYLIB_IFACE_CUSTOM_C"
|
||||
INTERFACE_CUSTOM_L "MYLIB_IFACE_CUSTOM_L"
|
||||
)
|
||||
|
||||
add_executable(myexe myexe.c)
|
||||
target_link_libraries(myexe PRIVATE mylib)
|
||||
set_target_properties(myexe PROPERTIES
|
||||
CUSTOM_C "MYEXE_CUSTOM_C"
|
||||
CUSTOM_L "MYEXE_CUSTOM_L"
|
||||
)
|
||||
|
||||
add_custom_target(print ALL VERBATIM
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
# Prints "MYLIB_PRIVATE_CUSTOM_C;EXAMPLE_CUSTOM_C"
|
||||
"$<TARGET_PROPERTY:mylib,CUSTOM_C>"
|
||||
|
||||
# Prints "MYLIB_PRIVATE_CUSTOM_L;EXAMPLE_CUSTOM_L"
|
||||
"$<TARGET_PROPERTY:mylib,CUSTOM_L>"
|
||||
|
||||
# Prints "MYEXE_CUSTOM_C"
|
||||
"$<TARGET_PROPERTY:myexe,CUSTOM_C>"
|
||||
|
||||
# Prints "MYEXE_CUSTOM_L;MYLIB_IFACE_CUSTOM_L;EXAMPLE_CUSTOM_L"
|
||||
"$<TARGET_PROPERTY:myexe,CUSTOM_L>"
|
||||
)
|
||||
|
||||
.. _`Compatible Interface Properties`:
|
||||
|
||||
Compatible Interface Properties
|
||||
|
||||
@@ -1775,11 +1775,11 @@ These expressions look up the values of
|
||||
|
||||
The expressions have special evaluation rules for some properties:
|
||||
|
||||
* :ref:`Target Build Specification` properties evaluate as a
|
||||
:ref:`semicolon-separated list <CMake Language Lists>` representing the union
|
||||
of the value on the target itself with the values of the corresponding
|
||||
:ref:`Target Usage Requirements` on targets named by the target's
|
||||
:prop_tgt:`LINK_LIBRARIES`:
|
||||
:ref:`Target Build Specification Properties <Target Build Specification>`
|
||||
These evaluate as a :ref:`semicolon-separated list <CMake Language Lists>`
|
||||
representing the union of the value on the target itself with the values
|
||||
of the corresponding :ref:`Target Usage Requirements` on targets named by
|
||||
the target's :prop_tgt:`LINK_LIBRARIES`:
|
||||
|
||||
* For :ref:`Target Compile Properties`, evaluation of corresponding usage
|
||||
requirements is transitive over the closure of the linked targets'
|
||||
@@ -1793,10 +1793,11 @@ The expressions have special evaluation rules for some properties:
|
||||
|
||||
Evaluation of :prop_tgt:`LINK_LIBRARIES` itself is not transitive.
|
||||
|
||||
* :ref:`Target Usage Requirements` evaluate as a
|
||||
:ref:`semicolon-separated list <CMake Language Lists>` representing the union
|
||||
of the value on the target itself with the values of the same properties on
|
||||
targets named by the target's :prop_tgt:`INTERFACE_LINK_LIBRARIES`:
|
||||
:ref:`Target Usage Requirement Properties <Target Usage Requirements>`
|
||||
These evaluate as a :ref:`semicolon-separated list <CMake Language Lists>`
|
||||
representing the union of the value on the target itself with the values
|
||||
of the same properties on targets named by the target's
|
||||
:prop_tgt:`INTERFACE_LINK_LIBRARIES`:
|
||||
|
||||
* For :ref:`Transitive Compile Properties`, evaluation is transitive over
|
||||
the closure of the target's :prop_tgt:`INTERFACE_LINK_LIBRARIES`
|
||||
@@ -1809,13 +1810,70 @@ The expressions have special evaluation rules for some properties:
|
||||
|
||||
Evaluation of :prop_tgt:`INTERFACE_LINK_LIBRARIES` itself is not transitive.
|
||||
|
||||
* :ref:`Compatible Interface Properties` evaluate as a single value
|
||||
combined from the target itself, from targets named by the target's
|
||||
:prop_tgt:`LINK_LIBRARIES`, and from the transitive closure of the
|
||||
linked targets' :prop_tgt:`INTERFACE_LINK_LIBRARIES`. Values of a
|
||||
compatible interface property from multiple targets combine based on
|
||||
the type of compatibility required by the ``COMPATIBLE_INTERFACE_*``
|
||||
property defining it.
|
||||
:ref:`Custom Transitive Properties`
|
||||
.. versionadded:: 3.30
|
||||
|
||||
These are processed during evaluation as follows:
|
||||
|
||||
* Evaluation of :genex:`$<TARGET_PROPERTY:tgt,PROP>` for some property
|
||||
``PROP``, named without an ``INTERFACE_`` prefix,
|
||||
checks the :prop_tgt:`TRANSITIVE_COMPILE_PROPERTIES`
|
||||
and :prop_tgt:`TRANSITIVE_LINK_PROPERTIES` properties on target ``tgt``,
|
||||
on targets named by its :prop_tgt:`LINK_LIBRARIES`, and on the
|
||||
transitive closure of targets named by the linked targets'
|
||||
:prop_tgt:`INTERFACE_LINK_LIBRARIES`.
|
||||
|
||||
If ``PROP`` is listed by one of those properties, then it evaluates as
|
||||
a :ref:`semicolon-separated list <CMake Language Lists>` representing
|
||||
the union of the value on the target itself with the values of the
|
||||
corresponding ``INTERFACE_PROP`` on targets named by the target's
|
||||
:prop_tgt:`LINK_LIBRARIES`:
|
||||
|
||||
* If ``PROP`` is named by :prop_tgt:`TRANSITIVE_COMPILE_PROPERTIES`,
|
||||
evaluation of the corresponding ``INTERFACE_PROP`` is transitive over
|
||||
the closure of the linked targets' :prop_tgt:`INTERFACE_LINK_LIBRARIES`,
|
||||
excluding entries guarded by the :genex:`LINK_ONLY` generator expression.
|
||||
|
||||
* If ``PROP`` is named by :prop_tgt:`TRANSITIVE_LINK_PROPERTIES`,
|
||||
evaluation of the corresponding ``INTERFACE_PROP`` is transitive over
|
||||
the closure of the linked targets' :prop_tgt:`INTERFACE_LINK_LIBRARIES`,
|
||||
including entries guarded by the :genex:`LINK_ONLY` generator expression.
|
||||
|
||||
* Evaluation of :genex:`$<TARGET_PROPERTY:tgt,INTERFACE_PROP>` for some
|
||||
property ``INTERFACE_PROP``, named with an ``INTERFACE_`` prefix,
|
||||
checks the :prop_tgt:`TRANSITIVE_COMPILE_PROPERTIES`
|
||||
and :prop_tgt:`TRANSITIVE_LINK_PROPERTIES` properties on target ``tgt``,
|
||||
and on the transitive closure of targets named by its
|
||||
:prop_tgt:`INTERFACE_LINK_LIBRARIES`.
|
||||
|
||||
If the corresponding ``PROP`` is listed by one of those properties,
|
||||
then ``INTERFACE_PROP`` evaluates as a
|
||||
:ref:`semicolon-separated list <CMake Language Lists>` representing the
|
||||
union of the value on the target itself with the value of the same
|
||||
property on targets named by the target's
|
||||
:prop_tgt:`INTERFACE_LINK_LIBRARIES`:
|
||||
|
||||
* If ``PROP`` is named by :prop_tgt:`TRANSITIVE_COMPILE_PROPERTIES`,
|
||||
evaluation of the corresponding ``INTERFACE_PROP`` is transitive over
|
||||
the closure of the target's :prop_tgt:`INTERFACE_LINK_LIBRARIES`,
|
||||
excluding entries guarded by the :genex:`LINK_ONLY` generator expression.
|
||||
|
||||
* If ``PROP`` is named by :prop_tgt:`TRANSITIVE_LINK_PROPERTIES`,
|
||||
evaluation of the corresponding ``INTERFACE_PROP`` is transitive over
|
||||
the closure of the target's :prop_tgt:`INTERFACE_LINK_LIBRARIES`,
|
||||
including entries guarded by the :genex:`LINK_ONLY` generator expression.
|
||||
|
||||
If a ``PROP`` is named by both :prop_tgt:`TRANSITIVE_COMPILE_PROPERTIES`
|
||||
and :prop_tgt:`TRANSITIVE_LINK_PROPERTIES`, the latter takes precedence.
|
||||
|
||||
:ref:`Compatible Interface Properties`
|
||||
These evaluate as a single value combined from the target itself,
|
||||
from targets named by the target's :prop_tgt:`LINK_LIBRARIES`, and
|
||||
from the transitive closure of the linked targets'
|
||||
:prop_tgt:`INTERFACE_LINK_LIBRARIES`. Values of a compatible
|
||||
interface property from multiple targets combine based on the type
|
||||
of compatibility required by the ``COMPATIBLE_INTERFACE_*`` property
|
||||
defining it.
|
||||
|
||||
|
||||
Target Artifacts
|
||||
|
||||
@@ -401,6 +401,8 @@ Properties on Targets
|
||||
/prop_tgt/Swift_MODULE_NAME
|
||||
/prop_tgt/SYSTEM
|
||||
/prop_tgt/TEST_LAUNCHER
|
||||
/prop_tgt/TRANSITIVE_COMPILE_PROPERTIES
|
||||
/prop_tgt/TRANSITIVE_LINK_PROPERTIES
|
||||
/prop_tgt/TYPE
|
||||
/prop_tgt/UNITY_BUILD
|
||||
/prop_tgt/UNITY_BUILD_BATCH_SIZE
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
TRANSITIVE_COMPILE_PROPERTIES
|
||||
-----------------------------
|
||||
|
||||
.. versionadded:: 3.30
|
||||
|
||||
Properties that the :genex:`TARGET_PROPERTY` generator expression, on the
|
||||
target and its dependents, evaluates as the union of values collected from
|
||||
the transitive closure of link dependencies, excluding entries guarded by
|
||||
:genex:`LINK_ONLY`.
|
||||
|
||||
The value is a :ref:`semicolon-separated list <CMake Language Lists>`
|
||||
of :ref:`custom transitive property <Custom Transitive Properties>` names.
|
||||
Any leading ``INTERFACE_`` prefix is ignored, e.g., ``INTERFACE_PROP`` is
|
||||
treated as just ``PROP``.
|
||||
|
||||
See documentation of the :genex:`TARGET_PROPERTY` generator expression
|
||||
for details of custom transitive property evaluation. See also the
|
||||
:prop_tgt:`TRANSITIVE_LINK_PROPERTIES` target property, which includes
|
||||
entries guarded by :genex:`LINK_ONLY`.
|
||||
@@ -0,0 +1,19 @@
|
||||
TRANSITIVE_LINK_PROPERTIES
|
||||
--------------------------
|
||||
|
||||
.. versionadded:: 3.30
|
||||
|
||||
Properties that the :genex:`TARGET_PROPERTY` generator expression, on the
|
||||
target and its dependents, evaluates as the union of values collected from
|
||||
the transitive closure of link dependencies, including entries guarded by
|
||||
:genex:`LINK_ONLY`.
|
||||
|
||||
The value is a :ref:`semicolon-separated list <CMake Language Lists>`
|
||||
of :ref:`custom transitive property <Custom Transitive Properties>` names.
|
||||
Any leading ``INTERFACE_`` prefix is ignored, e.g., ``INTERFACE_PROP`` is
|
||||
treated as just ``PROP``.
|
||||
|
||||
See documentation of the :genex:`TARGET_PROPERTY` generator expression
|
||||
for details of custom transitive property evaluation. See also the
|
||||
:prop_tgt:`TRANSITIVE_COMPILE_PROPERTIES` target property, which excludes
|
||||
entries guarded by :genex:`LINK_ONLY`..
|
||||
@@ -0,0 +1,7 @@
|
||||
custom-transitive-properties
|
||||
----------------------------
|
||||
|
||||
* The :genex:`TARGET_PROPERTY` generator expression learned to evaluate
|
||||
:ref:`custom transitive properties <Custom Transitive Properties>`
|
||||
defined by new :prop_tgt:`TRANSITIVE_COMPILE_PROPERTIES` and
|
||||
:prop_tgt:`TRANSITIVE_LINK_PROPERTIES` target properties.
|
||||
@@ -500,9 +500,9 @@ std::string cmCommonTargetGenerator::GetLinkerLauncher(
|
||||
std::string propName = lang + "_LINKER_LAUNCHER";
|
||||
cmValue launcherProp = this->GeneratorTarget->GetProperty(propName);
|
||||
if (cmNonempty(launcherProp)) {
|
||||
cmGeneratorExpressionDAGChecker dagChecker(this->GeneratorTarget, propName,
|
||||
nullptr, nullptr,
|
||||
this->LocalCommonGenerator);
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
this->GeneratorTarget, propName, nullptr, nullptr,
|
||||
this->LocalCommonGenerator, config);
|
||||
std::string evaluatedLinklauncher = cmGeneratorExpression::Evaluate(
|
||||
*launcherProp, this->LocalCommonGenerator, config, this->GeneratorTarget,
|
||||
&dagChecker, this->GeneratorTarget, lang);
|
||||
|
||||
@@ -581,7 +581,8 @@ cmComputeLinkDepends::cmComputeLinkDepends(const cmGeneratorTarget* target,
|
||||
"LINK_LIBRARY_OVERRIDE",
|
||||
nullptr,
|
||||
nullptr,
|
||||
this->Target->GetLocalGenerator()
|
||||
this->Target->GetLocalGenerator(),
|
||||
config
|
||||
};
|
||||
auto overrideFeature = cmGeneratorExpression::Evaluate(
|
||||
*feature, this->Target->GetLocalGenerator(), config,
|
||||
@@ -599,7 +600,8 @@ cmComputeLinkDepends::cmComputeLinkDepends(const cmGeneratorTarget* target,
|
||||
"LINK_LIBRARY_OVERRIDE",
|
||||
nullptr,
|
||||
nullptr,
|
||||
target->GetLocalGenerator() };
|
||||
target->GetLocalGenerator(),
|
||||
config };
|
||||
auto overrideValue = cmGeneratorExpression::Evaluate(
|
||||
*linkLibraryOverride, target->GetLocalGenerator(), config, target, &dag,
|
||||
target, linkLanguage);
|
||||
|
||||
@@ -152,6 +152,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
|
||||
gte, cmGeneratorExpression::BuildInterface, properties);
|
||||
}
|
||||
this->PopulateCompatibleInterfaceProperties(gte, properties);
|
||||
this->PopulateCustomTransitiveInterfaceProperties(
|
||||
gte, cmGeneratorExpression::BuildInterface, properties);
|
||||
|
||||
this->GenerateInterfaceProperties(gte, os, properties);
|
||||
|
||||
|
||||
@@ -604,6 +604,27 @@ void cmExportFileGenerator::PopulateCompatibleInterfaceProperties(
|
||||
}
|
||||
}
|
||||
|
||||
void cmExportFileGenerator::PopulateCustomTransitiveInterfaceProperties(
|
||||
cmGeneratorTarget const* target,
|
||||
cmGeneratorExpression::PreprocessContext preprocessRule,
|
||||
ImportPropertyMap& properties)
|
||||
{
|
||||
this->PopulateInterfaceProperty("TRANSITIVE_COMPILE_PROPERTIES", target,
|
||||
properties);
|
||||
this->PopulateInterfaceProperty("TRANSITIVE_LINK_PROPERTIES", target,
|
||||
properties);
|
||||
std::set<std::string> ifaceProperties;
|
||||
for (std::string const& config : this->Configurations) {
|
||||
for (auto const& i : target->GetCustomTransitiveProperties(
|
||||
config, cmGeneratorTarget::PropertyFor::Interface)) {
|
||||
ifaceProperties.emplace(i.second.InterfaceName);
|
||||
}
|
||||
}
|
||||
for (std::string const& ip : ifaceProperties) {
|
||||
this->PopulateInterfaceProperty(ip, target, preprocessRule, properties);
|
||||
}
|
||||
}
|
||||
|
||||
void cmExportFileGenerator::GenerateInterfaceProperties(
|
||||
const cmGeneratorTarget* target, std::ostream& os,
|
||||
const ImportPropertyMap& properties)
|
||||
|
||||
@@ -145,6 +145,10 @@ protected:
|
||||
ImportPropertyMap& properties);
|
||||
void PopulateCompatibleInterfaceProperties(cmGeneratorTarget const* target,
|
||||
ImportPropertyMap& properties);
|
||||
void PopulateCustomTransitiveInterfaceProperties(
|
||||
cmGeneratorTarget const* target,
|
||||
cmGeneratorExpression::PreprocessContext preprocessRule,
|
||||
ImportPropertyMap& properties);
|
||||
virtual void GenerateInterfaceProperties(
|
||||
cmGeneratorTarget const* target, std::ostream& os,
|
||||
const ImportPropertyMap& properties);
|
||||
|
||||
@@ -160,6 +160,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
|
||||
properties);
|
||||
|
||||
this->PopulateCompatibleInterfaceProperties(gt, properties);
|
||||
this->PopulateCustomTransitiveInterfaceProperties(
|
||||
gt, cmGeneratorExpression::InstallInterface, properties);
|
||||
|
||||
this->GenerateInterfaceProperties(gt, os, properties);
|
||||
|
||||
|
||||
@@ -76,10 +76,12 @@ std::string cmExportTryCompileFileGenerator::FindTargets(
|
||||
// To please constraint checks of DAGChecker, this property must have
|
||||
// LINK_OPTIONS property as parent
|
||||
parentDagChecker = cm::make_unique<cmGeneratorExpressionDAGChecker>(
|
||||
tgt, "LINK_OPTIONS", nullptr, nullptr, tgt->GetLocalGenerator());
|
||||
tgt, "LINK_OPTIONS", nullptr, nullptr, tgt->GetLocalGenerator(),
|
||||
this->Config);
|
||||
}
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
tgt, propName, nullptr, parentDagChecker.get(), tgt->GetLocalGenerator());
|
||||
tgt, propName, nullptr, parentDagChecker.get(), tgt->GetLocalGenerator(),
|
||||
this->Config);
|
||||
|
||||
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(*prop);
|
||||
|
||||
|
||||
@@ -425,7 +425,7 @@ const std::string& cmGeneratorExpressionInterpreter::Evaluate(
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
this->HeadTarget,
|
||||
property == "COMPILE_FLAGS" ? "COMPILE_OPTIONS" : property, nullptr,
|
||||
nullptr, this->LocalGenerator);
|
||||
nullptr, this->LocalGenerator, this->Config);
|
||||
|
||||
return this->CompiledGeneratorExpression->Evaluate(
|
||||
this->LocalGenerator, this->Config, this->HeadTarget, &dagChecker, nullptr,
|
||||
|
||||
@@ -20,17 +20,19 @@
|
||||
cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
|
||||
cmGeneratorTarget const* target, std::string property,
|
||||
const GeneratorExpressionContent* content,
|
||||
cmGeneratorExpressionDAGChecker* parent, cmLocalGenerator const* contextLG)
|
||||
cmGeneratorExpressionDAGChecker* parent, cmLocalGenerator const* contextLG,
|
||||
std::string const& contextConfig)
|
||||
: cmGeneratorExpressionDAGChecker(cmListFileBacktrace(), target,
|
||||
std::move(property), content, parent,
|
||||
contextLG)
|
||||
contextLG, contextConfig)
|
||||
{
|
||||
}
|
||||
|
||||
cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
|
||||
cmListFileBacktrace backtrace, cmGeneratorTarget const* target,
|
||||
std::string property, const GeneratorExpressionContent* content,
|
||||
cmGeneratorExpressionDAGChecker* parent, cmLocalGenerator const* contextLG)
|
||||
cmGeneratorExpressionDAGChecker* parent, cmLocalGenerator const* contextLG,
|
||||
std::string const& contextConfig)
|
||||
: Parent(parent)
|
||||
, Top(parent ? parent->Top : this)
|
||||
, Target(target)
|
||||
@@ -42,7 +44,9 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
|
||||
this->TopIsTransitiveProperty = parent->TopIsTransitiveProperty;
|
||||
} else {
|
||||
this->TopIsTransitiveProperty =
|
||||
this->Target->IsTransitiveProperty(this->Property, contextLG)
|
||||
this->Target
|
||||
->IsTransitiveProperty(this->Property, contextLG, contextConfig,
|
||||
this->EvaluatingLinkLibraries())
|
||||
.has_value();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,12 +22,14 @@ struct cmGeneratorExpressionDAGChecker
|
||||
std::string property,
|
||||
const GeneratorExpressionContent* content,
|
||||
cmGeneratorExpressionDAGChecker* parent,
|
||||
cmLocalGenerator const* contextLG);
|
||||
cmLocalGenerator const* contextLG,
|
||||
std::string const& contextConfig);
|
||||
cmGeneratorExpressionDAGChecker(cmGeneratorTarget const* target,
|
||||
std::string property,
|
||||
const GeneratorExpressionContent* content,
|
||||
cmGeneratorExpressionDAGChecker* parent,
|
||||
cmLocalGenerator const* contextLG);
|
||||
cmLocalGenerator const* contextLG,
|
||||
std::string const& contextConfig);
|
||||
|
||||
enum Result
|
||||
{
|
||||
|
||||
@@ -488,7 +488,7 @@ protected:
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
context->Backtrace, context->HeadTarget,
|
||||
genexOperator + ":" + expression, content, dagCheckerParent,
|
||||
context->LG);
|
||||
context->LG, context->Config);
|
||||
switch (dagChecker.Check()) {
|
||||
case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
|
||||
case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: {
|
||||
@@ -2873,19 +2873,22 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
||||
return target->GetLinkerLanguage(context->Config);
|
||||
}
|
||||
|
||||
bool const evaluatingLinkLibraries =
|
||||
dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries();
|
||||
|
||||
std::string interfacePropertyName;
|
||||
bool isInterfaceProperty = false;
|
||||
cmGeneratorTarget::UseTo usage = cmGeneratorTarget::UseTo::Compile;
|
||||
|
||||
if (cm::optional<cmGeneratorTarget::TransitiveProperty> transitiveProp =
|
||||
target->IsTransitiveProperty(propertyName, context->LG)) {
|
||||
target->IsTransitiveProperty(propertyName, context->LG,
|
||||
context->Config,
|
||||
evaluatingLinkLibraries)) {
|
||||
interfacePropertyName = std::string(transitiveProp->InterfaceName);
|
||||
isInterfaceProperty = transitiveProp->InterfaceName == propertyName;
|
||||
usage = transitiveProp->Usage;
|
||||
}
|
||||
|
||||
bool evaluatingLinkLibraries = false;
|
||||
|
||||
if (dagCheckerParent) {
|
||||
// This $<TARGET_PROPERTY:...> node has been reached while evaluating
|
||||
// another target property value. Check that the outermost evaluation
|
||||
@@ -2894,8 +2897,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
||||
dagCheckerParent->EvaluatingPICExpression() ||
|
||||
dagCheckerParent->EvaluatingLinkerLauncher()) {
|
||||
// No check required.
|
||||
} else if (dagCheckerParent->EvaluatingLinkLibraries()) {
|
||||
evaluatingLinkLibraries = true;
|
||||
} else if (evaluatingLinkLibraries) {
|
||||
if (!interfacePropertyName.empty()) {
|
||||
reportError(
|
||||
context, content->GetOriginalExpression(),
|
||||
@@ -2915,9 +2917,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
||||
dagCheckerParent, usage));
|
||||
}
|
||||
|
||||
cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, target,
|
||||
propertyName, content,
|
||||
dagCheckerParent, context->LG);
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
context->Backtrace, target, propertyName, content, dagCheckerParent,
|
||||
context->LG, context->Config);
|
||||
|
||||
switch (dagChecker.Check()) {
|
||||
case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
|
||||
|
||||
@@ -511,11 +511,15 @@ void cmGeneratorTarget::ClearSourcesCache()
|
||||
this->SourcesAreContextDependent = Tribool::Indeterminate;
|
||||
this->Objects.clear();
|
||||
this->VisitedConfigsForObjects.clear();
|
||||
this->LinkImplClosureForLinkMap.clear();
|
||||
this->LinkImplClosureForUsageMap.clear();
|
||||
this->LinkImplMap.clear();
|
||||
this->LinkImplUsageRequirementsOnlyMap.clear();
|
||||
this->IncludeDirectoriesCache.clear();
|
||||
this->CompileOptionsCache.clear();
|
||||
this->CompileDefinitionsCache.clear();
|
||||
this->CustomTransitiveBuildPropertiesMap.clear();
|
||||
this->CustomTransitiveInterfacePropertiesMap.clear();
|
||||
this->PrecompileHeadersCache.clear();
|
||||
this->LinkOptionsCache.clear();
|
||||
this->LinkDirectoriesCache.clear();
|
||||
@@ -707,8 +711,8 @@ std::string cmGeneratorTarget::GetLinkerTypeProperty(
|
||||
std::string propName{ "LINKER_TYPE" };
|
||||
auto linkerType = this->GetProperty(propName);
|
||||
if (!linkerType.IsEmpty()) {
|
||||
cmGeneratorExpressionDAGChecker dagChecker(this, propName, nullptr,
|
||||
nullptr, this->LocalGenerator);
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
this, propName, nullptr, nullptr, this->LocalGenerator, config);
|
||||
auto ltype =
|
||||
cmGeneratorExpression::Evaluate(*linkerType, this->GetLocalGenerator(),
|
||||
config, this, &dagChecker, this, lang);
|
||||
@@ -1174,7 +1178,7 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(
|
||||
if (iter == this->SystemIncludesCache.end()) {
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
this, "SYSTEM_INCLUDE_DIRECTORIES", nullptr, nullptr,
|
||||
this->LocalGenerator);
|
||||
this->LocalGenerator, config);
|
||||
|
||||
bool excludeImported = this->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED");
|
||||
|
||||
@@ -1186,7 +1190,7 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(
|
||||
}
|
||||
|
||||
std::vector<cmGeneratorTarget const*> const& deps =
|
||||
this->GetLinkImplementationClosure(config);
|
||||
this->GetLinkImplementationClosure(config, UseTo::Compile);
|
||||
for (cmGeneratorTarget const* dep : deps) {
|
||||
handleSystemIncludesDep(this->LocalGenerator, dep, config, this,
|
||||
&dagChecker, result, excludeImported, language);
|
||||
@@ -1934,8 +1938,8 @@ void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result,
|
||||
return;
|
||||
}
|
||||
|
||||
cmGeneratorExpressionDAGChecker dagChecker(this, "AUTOUIC_OPTIONS", nullptr,
|
||||
nullptr, this->LocalGenerator);
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
this, "AUTOUIC_OPTIONS", nullptr, nullptr, this->LocalGenerator, config);
|
||||
cmExpandList(cmGeneratorExpression::Evaluate(prop, this->LocalGenerator,
|
||||
config, this, &dagChecker),
|
||||
result);
|
||||
|
||||
@@ -892,6 +892,13 @@ public:
|
||||
|
||||
struct TransitiveProperty
|
||||
{
|
||||
#if defined(__SUNPRO_CC) || (defined(__ibmxl__) && defined(__clang__))
|
||||
TransitiveProperty(cm::string_view interfaceName, UseTo usage)
|
||||
: InterfaceName(interfaceName)
|
||||
, Usage(usage)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
cm::string_view InterfaceName;
|
||||
UseTo Usage;
|
||||
};
|
||||
@@ -900,7 +907,8 @@ public:
|
||||
BuiltinTransitiveProperties;
|
||||
|
||||
cm::optional<TransitiveProperty> IsTransitiveProperty(
|
||||
cm::string_view prop, cmLocalGenerator const* lg) const;
|
||||
cm::string_view prop, cmLocalGenerator const* lg,
|
||||
std::string const& config, bool evaluatingLinkLibraries) const;
|
||||
|
||||
bool HaveInstallTreeRPATH(const std::string& config) const;
|
||||
|
||||
@@ -982,6 +990,30 @@ public:
|
||||
bool DiscoverSyntheticTargets(cmSyntheticTargetCache& cache,
|
||||
std::string const& config);
|
||||
|
||||
class CustomTransitiveProperty : public TransitiveProperty
|
||||
{
|
||||
std::unique_ptr<std::string> InterfaceNameBuf;
|
||||
CustomTransitiveProperty(std::unique_ptr<std::string> interfaceNameBuf,
|
||||
UseTo usage);
|
||||
|
||||
public:
|
||||
CustomTransitiveProperty(std::string interfaceName, UseTo usage);
|
||||
};
|
||||
struct CustomTransitiveProperties
|
||||
: public std::map<std::string, CustomTransitiveProperty>
|
||||
{
|
||||
void Add(cmValue props, UseTo usage);
|
||||
};
|
||||
|
||||
enum class PropertyFor
|
||||
{
|
||||
Build,
|
||||
Interface,
|
||||
};
|
||||
|
||||
CustomTransitiveProperties const& GetCustomTransitiveProperties(
|
||||
std::string const& config, PropertyFor propertyFor) const;
|
||||
|
||||
private:
|
||||
void AddSourceCommon(const std::string& src, bool before = false);
|
||||
|
||||
@@ -1049,6 +1081,11 @@ private:
|
||||
std::string const& base, std::string const& suffix,
|
||||
std::string const& name, cmValue version) const;
|
||||
|
||||
mutable std::map<std::string, CustomTransitiveProperties>
|
||||
CustomTransitiveBuildPropertiesMap;
|
||||
mutable std::map<std::string, CustomTransitiveProperties>
|
||||
CustomTransitiveInterfacePropertiesMap;
|
||||
|
||||
struct CompatibleInterfacesBase
|
||||
{
|
||||
std::set<std::string> PropsBool;
|
||||
@@ -1080,7 +1117,8 @@ private:
|
||||
{
|
||||
bool Done = false;
|
||||
};
|
||||
mutable std::map<std::string, LinkImplClosure> LinkImplClosureMap;
|
||||
mutable std::map<std::string, LinkImplClosure> LinkImplClosureForLinkMap;
|
||||
mutable std::map<std::string, LinkImplClosure> LinkImplClosureForUsageMap;
|
||||
|
||||
using LinkInterfaceMapType = std::map<std::string, cmHeadToLinkInterfaceMap>;
|
||||
mutable LinkInterfaceMapType LinkInterfaceMap;
|
||||
@@ -1298,9 +1336,15 @@ private:
|
||||
void ComputeLinkInterfaceRuntimeLibraries(
|
||||
const std::string& config, cmOptionalLinkInterface& iface) const;
|
||||
|
||||
// If this method is made public, or call sites are added outside of
|
||||
// methods computing cached members, add dedicated caching members.
|
||||
std::vector<cmGeneratorTarget const*> GetLinkInterfaceClosure(
|
||||
std::string const& config, cmGeneratorTarget const* headTarget,
|
||||
UseTo usage) const;
|
||||
|
||||
public:
|
||||
const std::vector<const cmGeneratorTarget*>& GetLinkImplementationClosure(
|
||||
const std::string& config) const;
|
||||
const std::string& config, UseTo usage) const;
|
||||
|
||||
mutable std::map<std::string, std::string> MaxLanguageStandards;
|
||||
std::map<std::string, std::string> const& GetMaxLanguageStandards() const
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmValue.h"
|
||||
|
||||
namespace {
|
||||
using UseTo = cmGeneratorTarget::UseTo;
|
||||
}
|
||||
|
||||
const cmGeneratorTarget::CompatibleInterfacesBase&
|
||||
cmGeneratorTarget::GetCompatibleInterfaces(std::string const& config) const
|
||||
{
|
||||
@@ -41,7 +45,7 @@ cmGeneratorTarget::GetCompatibleInterfaces(std::string const& config) const
|
||||
compat.PropsBool.insert("POSITION_INDEPENDENT_CODE");
|
||||
compat.PropsString.insert("AUTOUIC_OPTIONS");
|
||||
std::vector<cmGeneratorTarget const*> const& deps =
|
||||
this->GetLinkImplementationClosure(config);
|
||||
this->GetLinkImplementationClosure(config, UseTo::Compile);
|
||||
for (cmGeneratorTarget const* li : deps) {
|
||||
#define CM_READ_COMPATIBLE_INTERFACE(X, x) \
|
||||
if (cmValue prop = li->GetProperty("COMPATIBLE_INTERFACE_" #X)) { \
|
||||
@@ -573,7 +577,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
|
||||
assert((impliedByUse ^ explicitlySet) || (!impliedByUse && !explicitlySet));
|
||||
|
||||
std::vector<cmGeneratorTarget const*> const& deps =
|
||||
tgt->GetLinkImplementationClosure(config);
|
||||
tgt->GetLinkImplementationClosure(config, UseTo::Compile);
|
||||
|
||||
if (deps.empty()) {
|
||||
return propContent;
|
||||
|
||||
@@ -48,8 +48,8 @@ std::string AddLangSpecificInterfaceIncludeDirectories(
|
||||
cmGeneratorExpressionDAGChecker* context)
|
||||
{
|
||||
cmGeneratorExpressionDAGChecker dag{
|
||||
target->GetBacktrace(), target, propertyName, nullptr, context,
|
||||
target->GetLocalGenerator()
|
||||
target->GetBacktrace(), target, propertyName, nullptr, context,
|
||||
target->GetLocalGenerator(), config
|
||||
};
|
||||
switch (dag.Check()) {
|
||||
case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
|
||||
@@ -101,8 +101,8 @@ void AddLangSpecificImplicitIncludeDirectories(
|
||||
if (const auto* libraries =
|
||||
target->GetLinkImplementationLibraries(config, UseTo::Compile)) {
|
||||
cmGeneratorExpressionDAGChecker dag{
|
||||
target->GetBacktrace(), target, propertyName, nullptr, nullptr,
|
||||
target->GetLocalGenerator()
|
||||
target->GetBacktrace(), target, propertyName, nullptr, nullptr,
|
||||
target->GetLocalGenerator(), config
|
||||
};
|
||||
|
||||
for (const cmLinkImplItem& library : libraries->Libraries) {
|
||||
@@ -254,8 +254,9 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories(
|
||||
std::vector<BT<std::string>> includes;
|
||||
std::unordered_set<std::string> uniqueIncludes;
|
||||
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
this, "INCLUDE_DIRECTORIES", nullptr, nullptr, this->LocalGenerator);
|
||||
cmGeneratorExpressionDAGChecker dagChecker(this, "INCLUDE_DIRECTORIES",
|
||||
nullptr, nullptr,
|
||||
this->LocalGenerator, config);
|
||||
|
||||
cmList debugProperties{ this->Makefile->GetDefinition(
|
||||
"CMAKE_DEBUG_TARGET_PROPERTIES") };
|
||||
|
||||
@@ -268,23 +268,40 @@ static void processILibs(const std::string& config,
|
||||
cmGeneratorTarget const* headTarget,
|
||||
cmLinkItem const& item, cmGlobalGenerator* gg,
|
||||
std::vector<cmGeneratorTarget const*>& tgts,
|
||||
std::set<cmGeneratorTarget const*>& emitted)
|
||||
std::set<cmGeneratorTarget const*>& emitted,
|
||||
UseTo usage)
|
||||
{
|
||||
if (item.Target && emitted.insert(item.Target).second) {
|
||||
tgts.push_back(item.Target);
|
||||
if (cmLinkInterfaceLibraries const* iface =
|
||||
item.Target->GetLinkInterfaceLibraries(config, headTarget,
|
||||
UseTo::Compile)) {
|
||||
item.Target->GetLinkInterfaceLibraries(config, headTarget, usage)) {
|
||||
for (cmLinkItem const& lib : iface->Libraries) {
|
||||
processILibs(config, headTarget, lib, gg, tgts, emitted);
|
||||
processILibs(config, headTarget, lib, gg, tgts, emitted, usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<cmGeneratorTarget const*>
|
||||
cmGeneratorTarget::GetLinkInterfaceClosure(std::string const& config,
|
||||
cmGeneratorTarget const* headTarget,
|
||||
UseTo usage) const
|
||||
{
|
||||
cmGlobalGenerator* gg = this->GetLocalGenerator()->GetGlobalGenerator();
|
||||
std::vector<cmGeneratorTarget const*> tgts;
|
||||
std::set<cmGeneratorTarget const*> emitted;
|
||||
if (cmLinkInterfaceLibraries const* iface =
|
||||
this->GetLinkInterfaceLibraries(config, headTarget, usage)) {
|
||||
for (cmLinkItem const& lib : iface->Libraries) {
|
||||
processILibs(config, headTarget, lib, gg, tgts, emitted, usage);
|
||||
}
|
||||
}
|
||||
return tgts;
|
||||
}
|
||||
|
||||
const std::vector<const cmGeneratorTarget*>&
|
||||
cmGeneratorTarget::GetLinkImplementationClosure(
|
||||
const std::string& config) const
|
||||
cmGeneratorTarget::GetLinkImplementationClosure(const std::string& config,
|
||||
UseTo usage) const
|
||||
{
|
||||
// There is no link implementation for targets that cannot compile sources.
|
||||
if (!this->CanCompileSources()) {
|
||||
@@ -292,18 +309,21 @@ cmGeneratorTarget::GetLinkImplementationClosure(
|
||||
return empty;
|
||||
}
|
||||
|
||||
LinkImplClosure& tgts = this->LinkImplClosureMap[config];
|
||||
LinkImplClosure& tgts =
|
||||
(usage == UseTo::Compile ? this->LinkImplClosureForUsageMap[config]
|
||||
: this->LinkImplClosureForLinkMap[config]);
|
||||
if (!tgts.Done) {
|
||||
tgts.Done = true;
|
||||
std::set<cmGeneratorTarget const*> emitted;
|
||||
|
||||
cmLinkImplementationLibraries const* impl =
|
||||
this->GetLinkImplementationLibraries(config, UseTo::Compile);
|
||||
this->GetLinkImplementationLibraries(config, usage);
|
||||
assert(impl);
|
||||
|
||||
for (cmLinkImplItem const& lib : impl->Libraries) {
|
||||
processILibs(config, this, lib,
|
||||
this->LocalGenerator->GetGlobalGenerator(), tgts, emitted);
|
||||
this->LocalGenerator->GetGlobalGenerator(), tgts, emitted,
|
||||
usage);
|
||||
}
|
||||
}
|
||||
return tgts;
|
||||
@@ -518,7 +538,7 @@ void cmGeneratorTarget::ExpandLinkItems(std::string const& prop,
|
||||
}
|
||||
// Keep this logic in sync with ComputeLinkImplementationLibraries.
|
||||
cmGeneratorExpressionDAGChecker dagChecker(this, prop, nullptr, nullptr,
|
||||
this->LocalGenerator);
|
||||
this->LocalGenerator, config);
|
||||
// The $<LINK_ONLY> expression may be in a link interface to specify
|
||||
// private link dependencies that are otherwise excluded from usage
|
||||
// requirements.
|
||||
@@ -1268,8 +1288,8 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
|
||||
// Collect libraries directly linked in this configuration.
|
||||
for (auto const& entry : entryRange) {
|
||||
// Keep this logic in sync with ExpandLinkItems.
|
||||
cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr,
|
||||
nullptr, this->LocalGenerator);
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
this, "LINK_LIBRARIES", nullptr, nullptr, this->LocalGenerator, config);
|
||||
// The $<LINK_ONLY> expression may be used to specify link dependencies
|
||||
// that are otherwise excluded from usage requirements.
|
||||
if (usage == UseTo::Compile) {
|
||||
|
||||
@@ -125,8 +125,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDirectories(
|
||||
std::vector<BT<std::string>> result;
|
||||
std::unordered_set<std::string> uniqueDirectories;
|
||||
|
||||
cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DIRECTORIES", nullptr,
|
||||
nullptr, this->LocalGenerator);
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
this, "LINK_DIRECTORIES", nullptr, nullptr, this->LocalGenerator, config);
|
||||
|
||||
cmList debugProperties{ this->Makefile->GetDefinition(
|
||||
"CMAKE_DEBUG_TARGET_PROPERTIES") };
|
||||
|
||||
@@ -217,8 +217,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileOptions(
|
||||
std::vector<BT<std::string>> result;
|
||||
std::unordered_set<std::string> uniqueOptions;
|
||||
|
||||
cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_OPTIONS", nullptr,
|
||||
nullptr, this->LocalGenerator);
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
this, "COMPILE_OPTIONS", nullptr, nullptr, this->LocalGenerator, config);
|
||||
|
||||
cmList debugProperties{ this->Makefile->GetDefinition(
|
||||
"CMAKE_DEBUG_TARGET_PROPERTIES") };
|
||||
@@ -258,8 +258,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileFeatures(
|
||||
std::vector<BT<std::string>> result;
|
||||
std::unordered_set<std::string> uniqueFeatures;
|
||||
|
||||
cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_FEATURES", nullptr,
|
||||
nullptr, this->LocalGenerator);
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
this, "COMPILE_FEATURES", nullptr, nullptr, this->LocalGenerator, config);
|
||||
|
||||
cmList debugProperties{ this->Makefile->GetDefinition(
|
||||
"CMAKE_DEBUG_TARGET_PROPERTIES") };
|
||||
@@ -308,8 +308,9 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions(
|
||||
std::vector<BT<std::string>> list;
|
||||
std::unordered_set<std::string> uniqueOptions;
|
||||
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
this, "COMPILE_DEFINITIONS", nullptr, nullptr, this->LocalGenerator);
|
||||
cmGeneratorExpressionDAGChecker dagChecker(this, "COMPILE_DEFINITIONS",
|
||||
nullptr, nullptr,
|
||||
this->LocalGenerator, config);
|
||||
|
||||
cmList debugProperties{ this->Makefile->GetDefinition(
|
||||
"CMAKE_DEBUG_TARGET_PROPERTIES") };
|
||||
@@ -372,8 +373,9 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetPrecompileHeaders(
|
||||
}
|
||||
std::unordered_set<std::string> uniqueOptions;
|
||||
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
this, "PRECOMPILE_HEADERS", nullptr, nullptr, this->LocalGenerator);
|
||||
cmGeneratorExpressionDAGChecker dagChecker(this, "PRECOMPILE_HEADERS",
|
||||
nullptr, nullptr,
|
||||
this->LocalGenerator, config);
|
||||
|
||||
cmList debugProperties{ this->Makefile->GetDefinition(
|
||||
"CMAKE_DEBUG_TARGET_PROPERTIES") };
|
||||
@@ -430,8 +432,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions(
|
||||
std::vector<BT<std::string>> result;
|
||||
std::unordered_set<std::string> uniqueOptions;
|
||||
|
||||
cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_OPTIONS", nullptr,
|
||||
nullptr, this->LocalGenerator);
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
this, "LINK_OPTIONS", nullptr, nullptr, this->LocalGenerator, config);
|
||||
|
||||
cmList debugProperties{ this->Makefile->GetDefinition(
|
||||
"CMAKE_DEBUG_TARGET_PROPERTIES") };
|
||||
@@ -599,8 +601,9 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetStaticLibraryLinkOptions(
|
||||
std::vector<BT<std::string>> result;
|
||||
std::unordered_set<std::string> uniqueOptions;
|
||||
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
this, "STATIC_LIBRARY_OPTIONS", nullptr, nullptr, this->LocalGenerator);
|
||||
cmGeneratorExpressionDAGChecker dagChecker(this, "STATIC_LIBRARY_OPTIONS",
|
||||
nullptr, nullptr,
|
||||
this->LocalGenerator, config);
|
||||
|
||||
EvaluatedTargetPropertyEntries entries;
|
||||
if (cmValue linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) {
|
||||
@@ -631,8 +634,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends(
|
||||
{
|
||||
std::vector<BT<std::string>> result;
|
||||
std::unordered_set<std::string> uniqueOptions;
|
||||
cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DEPENDS", nullptr,
|
||||
nullptr, this->LocalGenerator);
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
this, "LINK_DEPENDS", nullptr, nullptr, this->LocalGenerator, config);
|
||||
|
||||
EvaluatedTargetPropertyEntries entries;
|
||||
if (cmValue linkDepends = this->GetProperty("LINK_DEPENDS")) {
|
||||
|
||||
@@ -265,7 +265,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
|
||||
}
|
||||
|
||||
cmGeneratorExpressionDAGChecker dagChecker(this, "SOURCES", nullptr, nullptr,
|
||||
this->LocalGenerator);
|
||||
this->LocalGenerator, config);
|
||||
|
||||
EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
|
||||
this, config, std::string(), &dagChecker, this->SourceEntries);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <cm/memory>
|
||||
#include <cm/optional>
|
||||
#include <cm/string_view>
|
||||
#include <cmext/string_view>
|
||||
@@ -19,6 +20,7 @@
|
||||
#include "cmGeneratorExpressionDAGChecker.h"
|
||||
#include "cmGeneratorExpressionNode.h"
|
||||
#include "cmLinkItem.h"
|
||||
#include "cmList.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmPolicies.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
@@ -107,9 +109,9 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty(
|
||||
// Evaluate $<TARGET_PROPERTY:this,prop> as if it were compiled. This is
|
||||
// a subset of TargetPropertyNode::Evaluate without stringify/parse steps
|
||||
// but sufficient for transitive interface properties.
|
||||
cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, this, prop,
|
||||
nullptr, dagCheckerParent,
|
||||
this->LocalGenerator);
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
context->Backtrace, this, prop, nullptr, dagCheckerParent,
|
||||
this->LocalGenerator, context->Config);
|
||||
switch (dagChecker.Check()) {
|
||||
case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
|
||||
dagChecker.ReportError(
|
||||
@@ -176,11 +178,16 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty(
|
||||
|
||||
cm::optional<cmGeneratorTarget::TransitiveProperty>
|
||||
cmGeneratorTarget::IsTransitiveProperty(cm::string_view prop,
|
||||
cmLocalGenerator const* lg) const
|
||||
cmLocalGenerator const* lg,
|
||||
std::string const& config,
|
||||
bool evaluatingLinkLibraries) const
|
||||
{
|
||||
cm::optional<TransitiveProperty> result;
|
||||
static const cm::string_view kINTERFACE_ = "INTERFACE_"_s;
|
||||
if (cmHasPrefix(prop, kINTERFACE_)) {
|
||||
PropertyFor const propertyFor = cmHasPrefix(prop, kINTERFACE_)
|
||||
? PropertyFor::Interface
|
||||
: PropertyFor::Build;
|
||||
if (propertyFor == PropertyFor::Interface) {
|
||||
prop = prop.substr(kINTERFACE_.length());
|
||||
}
|
||||
auto i = BuiltinTransitiveProperties.find(prop);
|
||||
@@ -202,6 +209,86 @@ cmGeneratorTarget::IsTransitiveProperty(cm::string_view prop,
|
||||
result = TransitiveProperty{ "INTERFACE_COMPILE_DEFINITIONS"_s,
|
||||
UseTo::Compile };
|
||||
}
|
||||
} else if (!evaluatingLinkLibraries) {
|
||||
// Honor TRANSITIVE_COMPILE_PROPERTIES and TRANSITIVE_LINK_PROPERTIES
|
||||
// from the link closure when we are not evaluating the closure itself.
|
||||
CustomTransitiveProperties const& ctp =
|
||||
this->GetCustomTransitiveProperties(config, propertyFor);
|
||||
auto ci = ctp.find(std::string(prop));
|
||||
if (ci != ctp.end()) {
|
||||
result = ci->second;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
cmGeneratorTarget::CustomTransitiveProperty::CustomTransitiveProperty(
|
||||
std::string interfaceName, UseTo usage)
|
||||
: CustomTransitiveProperty(
|
||||
cm::make_unique<std::string>(std::move(interfaceName)), usage)
|
||||
{
|
||||
}
|
||||
cmGeneratorTarget::CustomTransitiveProperty::CustomTransitiveProperty(
|
||||
std::unique_ptr<std::string> interfaceNameBuf, UseTo usage)
|
||||
: TransitiveProperty{ *interfaceNameBuf, usage }
|
||||
, InterfaceNameBuf(std::move(interfaceNameBuf))
|
||||
{
|
||||
}
|
||||
|
||||
void cmGeneratorTarget::CustomTransitiveProperties::Add(cmValue props,
|
||||
UseTo usage)
|
||||
{
|
||||
if (props) {
|
||||
cmList propsList(*props);
|
||||
for (std::string p : propsList) {
|
||||
std::string ip;
|
||||
static const cm::string_view kINTERFACE_ = "INTERFACE_"_s;
|
||||
if (cmHasPrefix(p, kINTERFACE_)) {
|
||||
ip = std::move(p);
|
||||
p = ip.substr(kINTERFACE_.length());
|
||||
} else {
|
||||
ip = cmStrCat(kINTERFACE_, p);
|
||||
}
|
||||
this->emplace(std::move(p),
|
||||
CustomTransitiveProperty(std::move(ip), usage));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cmGeneratorTarget::CustomTransitiveProperties const&
|
||||
cmGeneratorTarget::GetCustomTransitiveProperties(std::string const& config,
|
||||
PropertyFor propertyFor) const
|
||||
{
|
||||
std::map<std::string, CustomTransitiveProperties>& ctpm =
|
||||
propertyFor == PropertyFor::Build
|
||||
? this->CustomTransitiveBuildPropertiesMap
|
||||
: this->CustomTransitiveInterfacePropertiesMap;
|
||||
auto i = ctpm.find(config);
|
||||
if (i == ctpm.end()) {
|
||||
CustomTransitiveProperties ctp;
|
||||
auto addTransitiveProperties = [this, &config, propertyFor,
|
||||
&ctp](std::string const& tp, UseTo usage) {
|
||||
// Add transitive properties named by the target itself.
|
||||
ctp.Add(this->GetProperty(tp), usage);
|
||||
// Add transitive properties named by the target's link dependencies.
|
||||
if (propertyFor == PropertyFor::Build) {
|
||||
for (cmGeneratorTarget const* gt :
|
||||
this->GetLinkImplementationClosure(config, usage)) {
|
||||
ctp.Add(gt->GetProperty(tp), usage);
|
||||
}
|
||||
} else {
|
||||
// The set of custom transitive INTERFACE_ properties does not
|
||||
// depend on the consumer. Use the target as its own head.
|
||||
cmGeneratorTarget const* headTarget = this;
|
||||
for (cmGeneratorTarget const* gt :
|
||||
this->GetLinkInterfaceClosure(config, headTarget, usage)) {
|
||||
ctp.Add(gt->GetProperty(tp), usage);
|
||||
}
|
||||
}
|
||||
};
|
||||
addTransitiveProperties("TRANSITIVE_LINK_PROPERTIES", UseTo::Link);
|
||||
addTransitiveProperties("TRANSITIVE_COMPILE_PROPERTIES", UseTo::Compile);
|
||||
i = ctpm.emplace(config, std::move(ctp)).first;
|
||||
}
|
||||
return i->second;
|
||||
}
|
||||
|
||||
@@ -1918,14 +1918,14 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
|
||||
info.SetBool("MOC_RELAXED_MODE", this->Moc.RelaxedMode);
|
||||
info.SetBool("MOC_PATH_PREFIX", this->Moc.PathPrefix);
|
||||
|
||||
cmGeneratorExpressionDAGChecker dagChecker(this->GenTarget,
|
||||
"AUTOMOC_MACRO_NAMES", nullptr,
|
||||
nullptr, this->LocalGen);
|
||||
EvaluatedTargetPropertyEntries InterfaceAutoMocMacroNamesEntries;
|
||||
|
||||
if (this->MultiConfig) {
|
||||
for (auto const& cfg : this->ConfigsList) {
|
||||
if (!cfg.empty()) {
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
this->GenTarget, "AUTOMOC_MACRO_NAMES", nullptr, nullptr,
|
||||
this->LocalGen, cfg);
|
||||
AddInterfaceEntries(this->GenTarget, cfg,
|
||||
"INTERFACE_AUTOMOC_MACRO_NAMES", "CXX",
|
||||
&dagChecker, InterfaceAutoMocMacroNamesEntries,
|
||||
@@ -1933,6 +1933,9 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cmGeneratorExpressionDAGChecker dagChecker(
|
||||
this->GenTarget, "AUTOMOC_MACRO_NAMES", nullptr, nullptr,
|
||||
this->LocalGen, this->ConfigDefault);
|
||||
AddInterfaceEntries(this->GenTarget, this->ConfigDefault,
|
||||
"INTERFACE_AUTOMOC_MACRO_NAMES", "CXX", &dagChecker,
|
||||
InterfaceAutoMocMacroNamesEntries,
|
||||
|
||||
@@ -527,6 +527,7 @@ if(BUILD_TESTING)
|
||||
set_property(TEST CompileOptions APPEND PROPERTY LABELS "Fortran")
|
||||
|
||||
ADD_TEST_MACRO(CompatibleInterface CompatibleInterface)
|
||||
ADD_TEST_MACRO(CustomTransitiveProperties CustomTransitiveProperties)
|
||||
ADD_TEST_MACRO(AliasTarget AliasTarget)
|
||||
ADD_TEST_MACRO(StagingPrefix StagingPrefix)
|
||||
ADD_TEST_MACRO(ImportedSameName ImportedSameName)
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
cmake_minimum_required(VERSION 3.29)
|
||||
cmake_policy(SET CMP0166 NEW)
|
||||
project(CustomTransitiveProperties C)
|
||||
|
||||
add_library(iface1 INTERFACE)
|
||||
set_target_properties(iface1 PROPERTIES
|
||||
TRANSITIVE_COMPILE_PROPERTIES "CUSTOM_A" # LINK_ONLY not pierced
|
||||
TRANSITIVE_LINK_PROPERTIES "CUSTOM_U" # LINK_ONLY pierced
|
||||
|
||||
INTERFACE_CUSTOM_A "CUSTOM_A_IFACE1;CUSTOM_A_TARGET_NAME_$<UPPER_CASE:$<TARGET_PROPERTY:NAME>>"
|
||||
INTERFACE_CUSTOM_B "CUSTOM_B_IFACE1"
|
||||
INTERFACE_CUSTOM_C "CUSTOM_C_IFACE1"
|
||||
INTERFACE_CUSTOM_U "CUSTOM_U_IFACE1;CUSTOM_U_TARGET_NAME_$<UPPER_CASE:$<TARGET_PROPERTY:NAME>>"
|
||||
INTERFACE_CUSTOM_V "CUSTOM_V_IFACE1"
|
||||
INTERFACE_CUSTOM_W "CUSTOM_W_IFACE1"
|
||||
)
|
||||
|
||||
add_library(iface2 INTERFACE)
|
||||
set_target_properties(iface2 PROPERTIES
|
||||
INTERFACE_CUSTOM_A "CUSTOM_A_IFACE2;CUSTOM_A_TARGET_TYPE_$<TARGET_PROPERTY:TYPE>"
|
||||
INTERFACE_CUSTOM_U "CUSTOM_U_IFACE2;CUSTOM_U_TARGET_TYPE_$<TARGET_PROPERTY:TYPE>"
|
||||
)
|
||||
target_link_libraries(iface2 INTERFACE iface1)
|
||||
|
||||
# Test that the INTERFACE prefix is removed.
|
||||
set(unnecessary_INTERFACE_ "INTERFACE_")
|
||||
|
||||
add_library(static1 STATIC static1.c)
|
||||
target_link_libraries(static1 PRIVATE iface2)
|
||||
set_target_properties(static1 PROPERTIES
|
||||
TRANSITIVE_COMPILE_PROPERTIES "${unnecessary_INTERFACE_}CUSTOM_B" # LINK_ONLY not pierced
|
||||
TRANSITIVE_LINK_PROPERTIES "${unnecessary_INTERFACE_}CUSTOM_V" # LINK_ONLY pierced
|
||||
|
||||
CUSTOM_A "CUSTOM_A_STATIC1"
|
||||
CUSTOM_B "CUSTOM_B_STATIC1"
|
||||
CUSTOM_U "CUSTOM_U_STATIC1"
|
||||
CUSTOM_V "CUSTOM_V_STATIC1"
|
||||
INTERFACE_CUSTOM_A "CUSTOM_A_STATIC1_IFACE"
|
||||
INTERFACE_CUSTOM_B "CUSTOM_B_STATIC1_IFACE"
|
||||
INTERFACE_CUSTOM_U "CUSTOM_U_STATIC1_IFACE"
|
||||
INTERFACE_CUSTOM_V "CUSTOM_V_STATIC1_IFACE"
|
||||
)
|
||||
target_compile_definitions(static1 PRIVATE
|
||||
$<TARGET_PROPERTY:CUSTOM_A>
|
||||
$<TARGET_PROPERTY:CUSTOM_B>
|
||||
$<TARGET_PROPERTY:CUSTOM_U>
|
||||
$<TARGET_PROPERTY:CUSTOM_V>
|
||||
)
|
||||
|
||||
add_library(object1 OBJECT object1.c)
|
||||
target_link_libraries(object1 PRIVATE iface2)
|
||||
set_target_properties(object1 PROPERTIES
|
||||
TRANSITIVE_COMPILE_PROPERTIES "${unnecessary_INTERFACE_}CUSTOM_C" # LINK_ONLY not pierced
|
||||
TRANSITIVE_LINK_PROPERTIES "${unnecessary_INTERFACE_}CUSTOM_W" # LINK_ONLY pierced
|
||||
|
||||
CUSTOM_A "CUSTOM_A_OBJECT1"
|
||||
CUSTOM_C "CUSTOM_C_OBJECT1"
|
||||
CUSTOM_U "CUSTOM_U_OBJECT1"
|
||||
CUSTOM_W "CUSTOM_W_OBJECT1"
|
||||
INTERFACE_CUSTOM_A "CUSTOM_A_OBJECT1_IFACE"
|
||||
INTERFACE_CUSTOM_C "CUSTOM_C_OBJECT1_IFACE"
|
||||
INTERFACE_CUSTOM_U "CUSTOM_U_OBJECT1_IFACE"
|
||||
INTERFACE_CUSTOM_W "CUSTOM_W_OBJECT1_IFACE"
|
||||
)
|
||||
target_compile_definitions(object1 PRIVATE
|
||||
$<TARGET_PROPERTY:CUSTOM_A>
|
||||
$<TARGET_PROPERTY:CUSTOM_C>
|
||||
$<TARGET_PROPERTY:CUSTOM_U>
|
||||
$<TARGET_PROPERTY:CUSTOM_W>
|
||||
)
|
||||
|
||||
add_executable(CustomTransitiveProperties main.c)
|
||||
target_link_libraries(CustomTransitiveProperties PRIVATE static1 object1)
|
||||
set_target_properties(CustomTransitiveProperties PROPERTIES
|
||||
CUSTOM_A "CUSTOM_A_MAIN"
|
||||
CUSTOM_B "CUSTOM_B_MAIN"
|
||||
CUSTOM_C "CUSTOM_C_MAIN"
|
||||
CUSTOM_U "CUSTOM_U_MAIN"
|
||||
CUSTOM_V "CUSTOM_V_MAIN"
|
||||
CUSTOM_W "CUSTOM_W_MAIN"
|
||||
)
|
||||
|
||||
# Test TRANSITIVE_*_PROPERTY evaluation within usage requirements.
|
||||
target_compile_definitions(CustomTransitiveProperties PRIVATE
|
||||
$<TARGET_PROPERTY:CUSTOM_A>
|
||||
$<TARGET_PROPERTY:CUSTOM_B>
|
||||
$<TARGET_PROPERTY:CUSTOM_C>
|
||||
$<TARGET_PROPERTY:CUSTOM_U>
|
||||
$<TARGET_PROPERTY:CUSTOM_V>
|
||||
$<TARGET_PROPERTY:CUSTOM_W>
|
||||
)
|
||||
|
||||
# Test TRANSITIVE_*_PROPERTY evaluation outside of usage requirements.
|
||||
set(out "${CMAKE_CURRENT_BINARY_DIR}/out-$<CONFIG>.txt")
|
||||
file(GENERATE OUTPUT "${out}" CONTENT "# file(GENERATE) produced:
|
||||
iface1 CUSTOM_A: '$<TARGET_PROPERTY:iface1,CUSTOM_A>'
|
||||
iface1 INTERFACE_CUSTOM_A: '$<TARGET_PROPERTY:iface1,INTERFACE_CUSTOM_A>'
|
||||
iface2 CUSTOM_A: '$<TARGET_PROPERTY:iface2,CUSTOM_A>'
|
||||
iface2 INTERFACE_CUSTOM_A: '$<TARGET_PROPERTY:iface2,INTERFACE_CUSTOM_A>'
|
||||
static1 CUSTOM_A: '$<TARGET_PROPERTY:static1,CUSTOM_A>'
|
||||
static1 INTERFACE_CUSTOM_A: '$<TARGET_PROPERTY:static1,INTERFACE_CUSTOM_A>'
|
||||
static1 CUSTOM_B: '$<TARGET_PROPERTY:static1,CUSTOM_B>'
|
||||
static1 INTERFACE_CUSTOM_B: '$<TARGET_PROPERTY:static1,INTERFACE_CUSTOM_B>'
|
||||
static1 CUSTOM_U: '$<TARGET_PROPERTY:static1,CUSTOM_U>'
|
||||
static1 INTERFACE_CUSTOM_U: '$<TARGET_PROPERTY:static1,INTERFACE_CUSTOM_U>'
|
||||
static1 CUSTOM_V: '$<TARGET_PROPERTY:static1,CUSTOM_V>'
|
||||
static1 INTERFACE_CUSTOM_V: '$<TARGET_PROPERTY:static1,INTERFACE_CUSTOM_V>'
|
||||
object1 CUSTOM_A: '$<TARGET_PROPERTY:object1,CUSTOM_A>'
|
||||
object1 INTERFACE_CUSTOM_A: '$<TARGET_PROPERTY:object1,INTERFACE_CUSTOM_A>'
|
||||
object1 CUSTOM_C: '$<TARGET_PROPERTY:object1,CUSTOM_C>'
|
||||
object1 INTERFACE_CUSTOM_C: '$<TARGET_PROPERTY:object1,INTERFACE_CUSTOM_C>'
|
||||
object1 CUSTOM_U: '$<TARGET_PROPERTY:object1,CUSTOM_U>'
|
||||
object1 INTERFACE_CUSTOM_U: '$<TARGET_PROPERTY:object1,INTERFACE_CUSTOM_U>'
|
||||
object1 CUSTOM_W: '$<TARGET_PROPERTY:object1,CUSTOM_W>'
|
||||
object1 INTERFACE_CUSTOM_W: '$<TARGET_PROPERTY:object1,INTERFACE_CUSTOM_W>'
|
||||
main CUSTOM_A: '$<TARGET_PROPERTY:CustomTransitiveProperties,CUSTOM_A>'
|
||||
main INTERFACE_CUSTOM_A: '$<TARGET_PROPERTY:CustomTransitiveProperties,INTERFACE_CUSTOM_A>'
|
||||
main CUSTOM_B: '$<TARGET_PROPERTY:CustomTransitiveProperties,CUSTOM_B>'
|
||||
main INTERFACE_CUSTOM_B: '$<TARGET_PROPERTY:CustomTransitiveProperties,INTERFACE_CUSTOM_B>'
|
||||
main CUSTOM_C: '$<TARGET_PROPERTY:CustomTransitiveProperties,CUSTOM_C>'
|
||||
main INTERFACE_CUSTOM_C: '$<TARGET_PROPERTY:CustomTransitiveProperties,INTERFACE_CUSTOM_C>'
|
||||
main CUSTOM_U: '$<TARGET_PROPERTY:CustomTransitiveProperties,CUSTOM_U>'
|
||||
main INTERFACE_CUSTOM_U: '$<TARGET_PROPERTY:CustomTransitiveProperties,INTERFACE_CUSTOM_U>'
|
||||
main CUSTOM_V: '$<TARGET_PROPERTY:CustomTransitiveProperties,CUSTOM_V>'
|
||||
main INTERFACE_CUSTOM_V: '$<TARGET_PROPERTY:CustomTransitiveProperties,INTERFACE_CUSTOM_V>'
|
||||
main CUSTOM_W: '$<TARGET_PROPERTY:CustomTransitiveProperties,CUSTOM_W>'
|
||||
main INTERFACE_CUSTOM_W: '$<TARGET_PROPERTY:CustomTransitiveProperties,INTERFACE_CUSTOM_W>'
|
||||
")
|
||||
add_custom_target(check ALL VERBATIM
|
||||
COMMAND ${CMAKE_COMMAND} -Dconfig=$<CONFIG> -Dout=${out} -P${CMAKE_CURRENT_SOURCE_DIR}/check.cmake
|
||||
COMMAND CustomTransitiveProperties
|
||||
"$<TARGET_PROPERTY:static1,CUSTOM_A>" "CUSTOM_A_STATIC1;CUSTOM_A_IFACE2;CUSTOM_A_TARGET_TYPE_STATIC_LIBRARY;CUSTOM_A_IFACE1;CUSTOM_A_TARGET_NAME_STATIC1"
|
||||
"$<TARGET_PROPERTY:static1,CUSTOM_B>" "CUSTOM_B_STATIC1;CUSTOM_B_IFACE1"
|
||||
"$<TARGET_PROPERTY:static1,CUSTOM_U>" "CUSTOM_U_STATIC1;CUSTOM_U_IFACE2;CUSTOM_U_TARGET_TYPE_STATIC_LIBRARY;CUSTOM_U_IFACE1;CUSTOM_U_TARGET_NAME_STATIC1"
|
||||
"$<TARGET_PROPERTY:static1,CUSTOM_V>" "CUSTOM_V_STATIC1;CUSTOM_V_IFACE1"
|
||||
"$<TARGET_PROPERTY:object1,CUSTOM_A>" "CUSTOM_A_OBJECT1;CUSTOM_A_IFACE2;CUSTOM_A_TARGET_TYPE_OBJECT_LIBRARY;CUSTOM_A_IFACE1;CUSTOM_A_TARGET_NAME_OBJECT1"
|
||||
"$<TARGET_PROPERTY:object1,CUSTOM_C>" "CUSTOM_C_OBJECT1;CUSTOM_C_IFACE1"
|
||||
"$<TARGET_PROPERTY:object1,CUSTOM_U>" "CUSTOM_U_OBJECT1;CUSTOM_U_IFACE2;CUSTOM_U_TARGET_TYPE_OBJECT_LIBRARY;CUSTOM_U_IFACE1;CUSTOM_U_TARGET_NAME_OBJECT1"
|
||||
"$<TARGET_PROPERTY:object1,CUSTOM_W>" "CUSTOM_W_OBJECT1;CUSTOM_W_IFACE1"
|
||||
"$<TARGET_PROPERTY:CustomTransitiveProperties,CUSTOM_A>" "CUSTOM_A_MAIN"
|
||||
"$<TARGET_PROPERTY:CustomTransitiveProperties,CUSTOM_B>" "CUSTOM_B_MAIN;CUSTOM_B_STATIC1_IFACE"
|
||||
"$<TARGET_PROPERTY:CustomTransitiveProperties,CUSTOM_C>" "CUSTOM_C_MAIN;CUSTOM_C_OBJECT1_IFACE"
|
||||
"$<TARGET_PROPERTY:CustomTransitiveProperties,CUSTOM_U>" "CUSTOM_U_MAIN;CUSTOM_U_STATIC1_IFACE;CUSTOM_U_IFACE2;CUSTOM_U_TARGET_TYPE_EXECUTABLE;CUSTOM_U_IFACE1;CUSTOM_U_TARGET_NAME_CUSTOMTRANSITIVEPROPERTIES;CUSTOM_U_OBJECT1_IFACE"
|
||||
"$<TARGET_PROPERTY:CustomTransitiveProperties,CUSTOM_V>" "CUSTOM_V_MAIN;CUSTOM_V_STATIC1_IFACE;CUSTOM_V_IFACE1"
|
||||
"$<TARGET_PROPERTY:CustomTransitiveProperties,CUSTOM_W>" "CUSTOM_W_MAIN;CUSTOM_W_IFACE1;CUSTOM_W_OBJECT1_IFACE"
|
||||
)
|
||||
@@ -0,0 +1,47 @@
|
||||
set(expect [[
|
||||
# file\(GENERATE\) produced:
|
||||
iface1 CUSTOM_A: ''
|
||||
iface1 INTERFACE_CUSTOM_A: 'CUSTOM_A_IFACE1;CUSTOM_A_TARGET_NAME_IFACE1'
|
||||
iface2 CUSTOM_A: ''
|
||||
iface2 INTERFACE_CUSTOM_A: 'CUSTOM_A_IFACE2;CUSTOM_A_TARGET_TYPE_INTERFACE_LIBRARY;CUSTOM_A_IFACE1;CUSTOM_A_TARGET_NAME_IFACE2'
|
||||
static1 CUSTOM_A: 'CUSTOM_A_STATIC1;CUSTOM_A_IFACE2;CUSTOM_A_TARGET_TYPE_STATIC_LIBRARY;CUSTOM_A_IFACE1;CUSTOM_A_TARGET_NAME_STATIC1'
|
||||
static1 INTERFACE_CUSTOM_A: 'CUSTOM_A_STATIC1_IFACE'
|
||||
static1 CUSTOM_B: 'CUSTOM_B_STATIC1;CUSTOM_B_IFACE1'
|
||||
static1 INTERFACE_CUSTOM_B: 'CUSTOM_B_STATIC1_IFACE'
|
||||
static1 CUSTOM_U: 'CUSTOM_U_STATIC1;CUSTOM_U_IFACE2;CUSTOM_U_TARGET_TYPE_STATIC_LIBRARY;CUSTOM_U_IFACE1;CUSTOM_U_TARGET_NAME_STATIC1'
|
||||
static1 INTERFACE_CUSTOM_U: 'CUSTOM_U_STATIC1_IFACE;CUSTOM_U_IFACE2;CUSTOM_U_TARGET_TYPE_STATIC_LIBRARY;CUSTOM_U_IFACE1;CUSTOM_U_TARGET_NAME_STATIC1'
|
||||
static1 CUSTOM_V: 'CUSTOM_V_STATIC1;CUSTOM_V_IFACE1'
|
||||
static1 INTERFACE_CUSTOM_V: 'CUSTOM_V_STATIC1_IFACE;CUSTOM_V_IFACE1'
|
||||
object1 CUSTOM_A: 'CUSTOM_A_OBJECT1;CUSTOM_A_IFACE2;CUSTOM_A_TARGET_TYPE_OBJECT_LIBRARY;CUSTOM_A_IFACE1;CUSTOM_A_TARGET_NAME_OBJECT1'
|
||||
object1 INTERFACE_CUSTOM_A: 'CUSTOM_A_OBJECT1_IFACE'
|
||||
object1 CUSTOM_C: 'CUSTOM_C_OBJECT1;CUSTOM_C_IFACE1'
|
||||
object1 INTERFACE_CUSTOM_C: 'CUSTOM_C_OBJECT1_IFACE'
|
||||
object1 CUSTOM_U: 'CUSTOM_U_OBJECT1;CUSTOM_U_IFACE2;CUSTOM_U_TARGET_TYPE_OBJECT_LIBRARY;CUSTOM_U_IFACE1;CUSTOM_U_TARGET_NAME_OBJECT1'
|
||||
object1 INTERFACE_CUSTOM_U: 'CUSTOM_U_OBJECT1_IFACE;CUSTOM_U_IFACE2;CUSTOM_U_TARGET_TYPE_OBJECT_LIBRARY;CUSTOM_U_IFACE1;CUSTOM_U_TARGET_NAME_OBJECT1'
|
||||
object1 CUSTOM_W: 'CUSTOM_W_OBJECT1;CUSTOM_W_IFACE1'
|
||||
object1 INTERFACE_CUSTOM_W: 'CUSTOM_W_OBJECT1_IFACE;CUSTOM_W_IFACE1'
|
||||
main CUSTOM_A: 'CUSTOM_A_MAIN'
|
||||
main INTERFACE_CUSTOM_A: ''
|
||||
main CUSTOM_B: 'CUSTOM_B_MAIN;CUSTOM_B_STATIC1_IFACE'
|
||||
main INTERFACE_CUSTOM_B: ''
|
||||
main CUSTOM_C: 'CUSTOM_C_MAIN;CUSTOM_C_OBJECT1_IFACE'
|
||||
main INTERFACE_CUSTOM_C: ''
|
||||
main CUSTOM_U: 'CUSTOM_U_MAIN;CUSTOM_U_STATIC1_IFACE;CUSTOM_U_IFACE2;CUSTOM_U_TARGET_TYPE_EXECUTABLE;CUSTOM_U_IFACE1;CUSTOM_U_TARGET_NAME_CUSTOMTRANSITIVEPROPERTIES;CUSTOM_U_OBJECT1_IFACE'
|
||||
main INTERFACE_CUSTOM_U: ''
|
||||
main CUSTOM_V: 'CUSTOM_V_MAIN;CUSTOM_V_STATIC1_IFACE;CUSTOM_V_IFACE1'
|
||||
main INTERFACE_CUSTOM_V: ''
|
||||
main CUSTOM_W: 'CUSTOM_W_MAIN;CUSTOM_W_IFACE1;CUSTOM_W_OBJECT1_IFACE'
|
||||
main INTERFACE_CUSTOM_W: ''
|
||||
]])
|
||||
string(REGEX REPLACE "\r\n" "\n" expect "${expect}")
|
||||
string(REGEX REPLACE "\n+$" "" expect "${expect}")
|
||||
|
||||
file(READ "${out}" actual)
|
||||
string(REGEX REPLACE "\r\n" "\n" actual "${actual}")
|
||||
string(REGEX REPLACE "\n+$" "" actual "${actual}")
|
||||
|
||||
if(NOT actual MATCHES "^${expect}$")
|
||||
string(REPLACE "\n" "\n expect> " expect " expect> ${expect}")
|
||||
string(REPLACE "\n" "\n actual> " actual " actual> ${actual}")
|
||||
message(FATAL_ERROR "Expected file(GENERATE) output:\n${expect}\ndoes not match actual output:\n${actual}")
|
||||
endif()
|
||||
@@ -0,0 +1,137 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef CUSTOM_A_IFACE1
|
||||
# error "CUSTOM_A_IFACE1 incorrectly defined"
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_A_IFACE2
|
||||
# error "CUSTOM_A_IFACE2 incorrectly defined"
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_A_STATIC1_IFACE
|
||||
# error "CUSTOM_A_STATIC1_IFACE incorrectly defined"
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_A_OBJECT1_IFACE
|
||||
# error "CUSTOM_A_OBJECT1_IFACE incorrectly defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_A_MAIN
|
||||
# error "CUSTOM_A_MAIN incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_B_IFACE1
|
||||
# error "CUSTOM_B_IFACE1 incorrectly defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_B_STATIC1_IFACE
|
||||
# error "CUSTOM_B_STATIC1_IFACE incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_B_MAIN
|
||||
# error "CUSTOM_B_MAIN incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_C_IFACE1
|
||||
# error "CUSTOM_C_IFACE1 incorrectly defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_C_OBJECT1_IFACE
|
||||
# error "CUSTOM_C_OBJECT1_IFACE incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_C_MAIN
|
||||
# error "CUSTOM_C_MAIN incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_U_IFACE1
|
||||
# error "CUSTOM_U_IFACE1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_U_IFACE2
|
||||
# error "CUSTOM_U_IFACE2 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_U_MAIN
|
||||
# error "CUSTOM_U_MAIN incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_U_STATIC1
|
||||
# error "CUSTOM_U_STATIC1 incorrectly defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_U_STATIC1_IFACE
|
||||
# error "CUSTOM_U_STATIC1_IFACE incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_U_OBJECT1
|
||||
# error "CUSTOM_U_OBJECT1 incorrectly defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_U_OBJECT1_IFACE
|
||||
# error "CUSTOM_U_OBJECT1_IFACE incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_U_TARGET_NAME_CUSTOMTRANSITIVEPROPERTIES
|
||||
# error \
|
||||
"CUSTOM_U_TARGET_NAME_CUSTOMTRANSITIVEPROPERTIES incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_U_TARGET_TYPE_EXECUTABLE
|
||||
# error "CUSTOM_U_TARGET_TYPE_EXECUTABLE incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_V_IFACE1
|
||||
# error "CUSTOM_V_IFACE1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_V_MAIN
|
||||
# error "CUSTOM_V_MAIN incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_V_STATIC1
|
||||
# error "CUSTOM_V_STATIC1 incorrectly defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_V_STATIC1_IFACE
|
||||
# error "CUSTOM_V_STATIC1_IFACE incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_W_IFACE1
|
||||
# error "CUSTOM_W_IFACE1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_W_MAIN
|
||||
# error "CUSTOM_W_MAIN incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_W_OBJECT1
|
||||
# error "CUSTOM_W_OBJECT1 incorrectly defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_W_OBJECT1_IFACE
|
||||
# error "CUSTOM_W_OBJECT1_IFACE incorrectly not defined"
|
||||
#endif
|
||||
|
||||
extern int static1(void);
|
||||
extern int object1(void);
|
||||
|
||||
int check_args(int argc, char** argv)
|
||||
{
|
||||
int result = 0;
|
||||
int i;
|
||||
for (i = 2; i < argc; i += 2) {
|
||||
if (strcmp(argv[i - 1], argv[i]) != 0) {
|
||||
fprintf(stderr, "Argument %d expected '%s' but got '%s'.\n", i, argv[i],
|
||||
argv[i - 1]);
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
return static1() + object1() + check_args(argc, argv);
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef CUSTOM_A_IFACE1
|
||||
# error "CUSTOM_A_IFACE1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_A_IFACE2
|
||||
# error "CUSTOM_A_IFACE2 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_A_OBJECT1
|
||||
# error "CUSTOM_A_OBJECT1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_A_TARGET_NAME_OBJECT1
|
||||
# error "CUSTOM_A_TARGET_NAME_OBJECT1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_A_TARGET_TYPE_OBJECT_LIBRARY
|
||||
# error "CUSTOM_A_TARGET_TYPE_OBJECT_LIBRARY incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_C_IFACE1
|
||||
# error "CUSTOM_C_IFACE1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_C_OBJECT1
|
||||
# error "CUSTOM_C_OBJECT1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_C_OBJECT1_IFACE
|
||||
# error "CUSTOM_C_OBJECT1_IFACE incorrectly defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_U_IFACE1
|
||||
# error "CUSTOM_U_IFACE1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_U_IFACE2
|
||||
# error "CUSTOM_U_IFACE2 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_U_OBJECT1
|
||||
# error "CUSTOM_U_OBJECT1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_U_TARGET_NAME_OBJECT1
|
||||
# error "CUSTOM_U_TARGET_NAME_OBJECT1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_U_TARGET_TYPE_OBJECT_LIBRARY
|
||||
# error "CUSTOM_U_TARGET_TYPE_OBJECT_LIBRARY incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_W_IFACE1
|
||||
# error "CUSTOM_W_IFACE1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_W_OBJECT1
|
||||
# error "CUSTOM_W_OBJECT1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
int object1(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef CUSTOM_A_IFACE1
|
||||
# error "CUSTOM_A_IFACE1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_A_IFACE2
|
||||
# error "CUSTOM_A_IFACE2 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_A_STATIC1
|
||||
# error "CUSTOM_A_STATIC1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_A_TARGET_NAME_STATIC1
|
||||
# error "CUSTOM_A_TARGET_NAME_STATIC1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_A_TARGET_TYPE_STATIC_LIBRARY
|
||||
# error "CUSTOM_A_TARGET_TYPE_STATIC_LIBRARY incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_B_IFACE1
|
||||
# error "CUSTOM_B_IFACE1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_B_STATIC1
|
||||
# error "CUSTOM_B_STATIC1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_B_STATIC1_IFACE
|
||||
# error "CUSTOM_B_STATIC1_IFACE incorrectly defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_U_IFACE1
|
||||
# error "CUSTOM_U_IFACE1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_U_IFACE2
|
||||
# error "CUSTOM_U_IFACE2 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_U_STATIC1
|
||||
# error "CUSTOM_U_STATIC1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_U_TARGET_NAME_STATIC1
|
||||
# error "CUSTOM_U_TARGET_NAME_STATIC1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_U_TARGET_TYPE_STATIC_LIBRARY
|
||||
# error "CUSTOM_U_TARGET_TYPE_STATIC_LIBRARY incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_V_IFACE1
|
||||
# error "CUSTOM_V_IFACE1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
#ifndef CUSTOM_V_STATIC1
|
||||
# error "CUSTOM_V_STATIC1 incorrectly not defined"
|
||||
#endif
|
||||
|
||||
int static1(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -116,6 +116,37 @@ target_link_libraries(testLib9 INTERFACE testLib9ObjIface PUBLIC testLib9ObjPub
|
||||
target_link_libraries(testLib9 PUBLIC Foo::Foo)
|
||||
cmake_policy(POP)
|
||||
|
||||
block()
|
||||
cmake_policy(SET CMP0022 NEW)
|
||||
add_library(testLib10 STATIC testLib10.c)
|
||||
set_target_properties(testLib10 PROPERTIES
|
||||
TRANSITIVE_COMPILE_PROPERTIES "CUSTOM_C"
|
||||
TRANSITIVE_LINK_PROPERTIES "CUSTOM_L"
|
||||
INTERFACE_CUSTOM_C "TESTLIB10_INTERFACE_CUSTOM_C"
|
||||
INTERFACE_CUSTOM_L "TESTLIB10_INTERFACE_CUSTOM_L"
|
||||
)
|
||||
target_compile_definitions(testLib10 INTERFACE
|
||||
"$<TARGET_PROPERTY:CUSTOM_C>"
|
||||
"$<TARGET_PROPERTY:CUSTOM_L>"
|
||||
)
|
||||
add_library(testLib11 STATIC testLib11.c)
|
||||
target_link_libraries(testLib11 PRIVATE testLib10)
|
||||
set_target_properties(testLib11 PROPERTIES
|
||||
INTERFACE_CUSTOM_C "TESTLIB11_INTERFACE_CUSTOM_C"
|
||||
INTERFACE_CUSTOM_L "TESTLIB11_INTERFACE_CUSTOM_L"
|
||||
TRANSITIVE_COMPILE_PROPERTIES "CUSTOM_D"
|
||||
TRANSITIVE_LINK_PROPERTIES "CUSTOM_M"
|
||||
INTERFACE_CUSTOM_D "TESTLIB11_INTERFACE_CUSTOM_D"
|
||||
INTERFACE_CUSTOM_M "TESTLIB11_INTERFACE_CUSTOM_M"
|
||||
)
|
||||
target_compile_definitions(testLib11 INTERFACE
|
||||
"$<TARGET_PROPERTY:CUSTOM_C>"
|
||||
"$<TARGET_PROPERTY:CUSTOM_D>"
|
||||
"$<TARGET_PROPERTY:CUSTOM_L>"
|
||||
"$<TARGET_PROPERTY:CUSTOM_M>"
|
||||
)
|
||||
endblock()
|
||||
|
||||
# Test using the target_link_libraries command to set the
|
||||
# LINK_INTERFACE_LIBRARIES* properties. We construct two libraries
|
||||
# providing the same two symbols. In each library one of the symbols
|
||||
@@ -574,6 +605,7 @@ install(
|
||||
testExe2lib testLib4lib testLib4libdbg testLib4libopt
|
||||
testLib6 testLib7 testLib8
|
||||
testLib9
|
||||
testLib10 testLib11
|
||||
testLibDeprecation
|
||||
testLibCycleA testLibCycleB
|
||||
testLibNoSONAME
|
||||
@@ -653,6 +685,7 @@ export(TARGETS testExe1 testLib1 testLib2 testLib3
|
||||
export(TARGETS testExe2 testLib4 testLib5 testLib6 testLib7 testExe3 testExe4 testExe2lib
|
||||
testLib8
|
||||
testLib9 testLib9ObjPub testLib9ObjPriv testLib9ObjIface
|
||||
testLib10 testLib11
|
||||
testLibDeprecation
|
||||
testLib4lib testLib4libdbg testLib4libopt
|
||||
testLibCycleA testLibCycleB
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
int testLib10(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
int testLib10(void);
|
||||
|
||||
int testLib11(void)
|
||||
{
|
||||
return testLib10();
|
||||
}
|
||||
@@ -328,6 +328,16 @@ foreach(vis Pub Priv Iface)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Create executables to verify custom transitive properties.
|
||||
add_executable(imp_testLib10 imp_testLib10.c)
|
||||
target_link_libraries(imp_testLib10 PRIVATE exp_testLib10)
|
||||
add_executable(imp_testLib10b imp_testLib10.c)
|
||||
target_link_libraries(imp_testLib10b PRIVATE bld_testLib10)
|
||||
add_executable(imp_testLib11 imp_testLib11.c)
|
||||
target_link_libraries(imp_testLib11 PRIVATE exp_testLib11)
|
||||
add_executable(imp_testLib11b imp_testLib11.c)
|
||||
target_link_libraries(imp_testLib11b PRIVATE bld_testLib11)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Test that handling imported targets, including transitive dependencies,
|
||||
# works in CheckFunctionExists (...and hopefully all other try_compile() checks
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef TESTLIB10_INTERFACE_CUSTOM_C
|
||||
# error "TESTLIB10_INTERFACE_CUSTOM_C incorrectly not defined!"
|
||||
#endif
|
||||
|
||||
#ifndef TESTLIB10_INTERFACE_CUSTOM_L
|
||||
# error "TESTLIB10_INTERFACE_CUSTOM_L incorrectly not defined!"
|
||||
#endif
|
||||
|
||||
int testLib10(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return testLib10();
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifdef TESTLIB10_INTERFACE_CUSTOM_C
|
||||
# error "TESTLIB10_INTERFACE_CUSTOM_C incorrectly defined!"
|
||||
#endif
|
||||
|
||||
#ifdef TESTLIB11_INTERFACE_CUSTOM_C
|
||||
# error "TESTLIB11_INTERFACE_CUSTOM_C incorrectly defined!"
|
||||
#endif
|
||||
|
||||
#ifndef TESTLIB11_INTERFACE_CUSTOM_D
|
||||
# error "TESTLIB11_INTERFACE_CUSTOM_D incorrectly not defined!"
|
||||
#endif
|
||||
|
||||
#ifndef TESTLIB10_INTERFACE_CUSTOM_L
|
||||
# error "TESTLIB10_INTERFACE_CUSTOM_L incorrectly not defined!"
|
||||
#endif
|
||||
|
||||
#ifndef TESTLIB11_INTERFACE_CUSTOM_L
|
||||
# error "TESTLIB11_INTERFACE_CUSTOM_L incorrectly not defined!"
|
||||
#endif
|
||||
|
||||
#ifndef TESTLIB11_INTERFACE_CUSTOM_M
|
||||
# error "TESTLIB11_INTERFACE_CUSTOM_M incorrectly not defined!"
|
||||
#endif
|
||||
|
||||
int testLib11(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return testLib11();
|
||||
}
|
||||
Reference in New Issue
Block a user