mirror of
https://github.com/reactos/CMake.git
synced 2024-11-24 12:09:48 +00:00
Merge topic 'Genex-LINK_LANGUAGE'
461efa7b51
Genex: Add $<LINK_LANGUAGE:...> and $<LINK_LANG_AND_ID:...>
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !4244
This commit is contained in:
commit
2a9cf88917
@ -259,6 +259,109 @@ Variable Queries
|
||||
add_executable(myapp main.cpp)
|
||||
target_link_libraries(myapp myapp_c myapp_cxx)
|
||||
|
||||
.. _`Boolean LINK_LANGUAGE Generator Expression`:
|
||||
|
||||
``$<LINK_LANG_AND_ID:language,compiler_ids>``
|
||||
``1`` when the language used for link step matches ``language`` and the
|
||||
CMake's compiler id of the language linker matches any one of the entries
|
||||
in ``compiler_ids``, otherwise ``0``. This expression is a short form for the
|
||||
combination of ``$<LINK_LANGUAGE:language>`` and
|
||||
``$<LANG_COMPILER_ID:compiler_ids>``. This expression may be used to specify
|
||||
link libraries, link options, link directories and link dependencies of a
|
||||
particular language and linker combination in a target. For example:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
add_library(libC_Clang ...)
|
||||
add_library(libCXX_Clang ...)
|
||||
add_library(libC_Intel ...)
|
||||
add_library(libCXX_Intel ...)
|
||||
|
||||
add_executable(myapp main.c)
|
||||
if (CXX_CONFIG)
|
||||
target_sources(myapp PRIVATE file.cxx)
|
||||
endif()
|
||||
target_link_libraries(myapp
|
||||
PRIVATE $<$<LINK_LANG_AND_ID:CXX,Clang,AppleClang>:libCXX_Clang>
|
||||
$<$<LINK_LANG_AND_ID:C,Clang,AppleClang>:libC_Clang>
|
||||
$<$<LINK_LANG_AND_ID:CXX,Intel>:libCXX_Intel>
|
||||
$<$<LINK_LANG_AND_ID:C,Intel>:libC_Intel>)
|
||||
|
||||
This specifies the use of different link libraries based on both the
|
||||
compiler id and link language. This example will have target ``libCXX_Clang``
|
||||
as link dependency when ``Clang`` or ``AppleClang`` is the ``CXX``
|
||||
linker, and ``libCXX_Intel`` when ``Intel`` is the ``CXX`` linker.
|
||||
Likewise when the ``C`` linker is ``Clang`` or ``AppleClang``, target
|
||||
``libC_Clang`` will be added as link dependency and ``libC_Intel`` when
|
||||
``Intel`` is the ``C`` linker.
|
||||
|
||||
See :ref:`the note related to
|
||||
<Constraints LINK_LANGUAGE Generator Expression>`
|
||||
``$<LINK_LANGUAGE:language>`` for constraints about the usage of this
|
||||
generator expression.
|
||||
|
||||
``$<LINK_LANGUAGE:languages>``
|
||||
``1`` when the language used for link step matches any of the entries
|
||||
in ``languages``, otherwise ``0``. This expression may be used to specify
|
||||
link libraries, link options, link directories and link dependencies of a
|
||||
particular language in a target. For example:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
add_library(api_C ...)
|
||||
add_library(api_CXX ...)
|
||||
add_library(api INTERFACE)
|
||||
target_link_options(api INTERFACE $<$<LINK_LANGUAGE:C>:-opt_c>
|
||||
$<$<LINK_LANGUAGE:CXX>:-opt_cxx>)
|
||||
target_link_libraries(api INTERFACE $<$<LINK_LANGUAGE:C>:api_C>
|
||||
$<$<LINK_LANGUAGE:CXX>:api_CXX>)
|
||||
|
||||
add_executable(myapp1 main.c)
|
||||
target_link_options(myapp1 PRIVATE api)
|
||||
|
||||
add_executable(myapp2 main.cpp)
|
||||
target_link_options(myapp2 PRIVATE api)
|
||||
|
||||
This specifies to use the ``api`` target for linking targets ``myapp1`` and
|
||||
``myapp2``. In practice, ``myapp1`` will link with target ``api_C`` and
|
||||
option ``-opt_c`` because it will use ``C`` as link language. And ``myapp2``
|
||||
will link with ``api_CXX`` and option ``-opt_cxx`` because ``CXX`` will be
|
||||
the link language.
|
||||
|
||||
.. _`Constraints LINK_LANGUAGE Generator Expression`:
|
||||
|
||||
.. note::
|
||||
|
||||
To determine the link language of a target, it is required to collect,
|
||||
transitively, all the targets which will be linked to it. So, for link
|
||||
libraries properties, a double evaluation will be done. During the first
|
||||
evaluation, ``$<LINK_LANGUAGE:..>`` expressions will always return ``0``.
|
||||
The link language computed after this first pass will be used to do the
|
||||
second pass. To avoid inconsistency, it is required that the second pass
|
||||
do not change the link language. Moreover, to avoid unexpected
|
||||
side-effects, it is required to specify complete entities as part of the
|
||||
``$<LINK_LANGUAGE:..>`` expression. For example:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
add_library(lib STATIC file.cxx)
|
||||
add_library(libother STATIC file.c)
|
||||
|
||||
# bad usage
|
||||
add_executable(myapp1 main.c)
|
||||
target_link_libraries(myapp1 PRIVATE lib$<$<LINK_LANGUAGE:C>:other>)
|
||||
|
||||
# correct usage
|
||||
add_executable(myapp2 main.c)
|
||||
target_link_libraries(myapp2 PRIVATE $<$<LINK_LANGUAGE:C>:libother>)
|
||||
|
||||
In this example, for ``myapp1``, the first pass will, unexpectedly,
|
||||
determine that the link language is ``CXX`` because the evaluation of the
|
||||
generator expression will be an empty string so ``myapp1`` will depends on
|
||||
target ``lib`` which is ``C++``. On the contrary, for ``myapp2``, the first
|
||||
evaluation will give ``C`` as link language, so the second pass will
|
||||
correctly add target ``libother`` as link dependency.
|
||||
|
||||
String-Valued Generator Expressions
|
||||
===================================
|
||||
|
||||
@ -450,6 +553,17 @@ Variable Queries
|
||||
<Boolean COMPILE_LANGUAGE Generator Expression>`
|
||||
``$<COMPILE_LANGUAGE:language>``
|
||||
for notes about the portability of this generator expression.
|
||||
``$<LINK_LANGUAGE>``
|
||||
The link language of target when evaluating link options.
|
||||
See :ref:`the related boolean expression
|
||||
<Boolean LINK_LANGUAGE Generator Expression>` ``$<LINK_LANGUAGE:language>``
|
||||
for notes about the portability of this generator expression.
|
||||
|
||||
.. note::
|
||||
|
||||
This generator expression is not supported by the link libraries
|
||||
properties to avoid side-effects due to the double evaluation of
|
||||
these properties.
|
||||
|
||||
Target-Dependent Queries
|
||||
------------------------
|
||||
|
5
Help/release/dev/genex-LINK_LANGUAGE.rst
Normal file
5
Help/release/dev/genex-LINK_LANGUAGE.rst
Normal file
@ -0,0 +1,5 @@
|
||||
genex-LINK_LANGUAGE
|
||||
===================
|
||||
|
||||
* The ``$<LINK_LANGUAGE:...>`` and ``$<LINK_LANG_AND_ID:...>``
|
||||
:manual:`generator expressions <cmake-generator-expressions(7)>` were added.
|
@ -103,6 +103,8 @@ const std::string& cmCompiledGeneratorExpression::EvaluateWithContext(
|
||||
if (!context.HadError) {
|
||||
this->HadContextSensitiveCondition = context.HadContextSensitiveCondition;
|
||||
this->HadHeadSensitiveCondition = context.HadHeadSensitiveCondition;
|
||||
this->HadLinkLanguageSensitiveCondition =
|
||||
context.HadLinkLanguageSensitiveCondition;
|
||||
this->SourceSensitiveTargets = context.SourceSensitiveTargets;
|
||||
}
|
||||
|
||||
@ -119,6 +121,7 @@ cmCompiledGeneratorExpression::cmCompiledGeneratorExpression(
|
||||
, Quiet(false)
|
||||
, HadContextSensitiveCondition(false)
|
||||
, HadHeadSensitiveCondition(false)
|
||||
, HadLinkLanguageSensitiveCondition(false)
|
||||
{
|
||||
cmGeneratorExpressionLexer l;
|
||||
std::vector<cmGeneratorExpressionToken> tokens = l.Tokenize(this->Input);
|
||||
|
@ -137,6 +137,10 @@ public:
|
||||
{
|
||||
return this->HadHeadSensitiveCondition;
|
||||
}
|
||||
bool GetHadLinkLanguageSensitiveCondition() const
|
||||
{
|
||||
return this->HadLinkLanguageSensitiveCondition;
|
||||
}
|
||||
std::set<cmGeneratorTarget const*> GetSourceSensitiveTargets() const
|
||||
{
|
||||
return this->SourceSensitiveTargets;
|
||||
@ -178,6 +182,7 @@ private:
|
||||
mutable std::string Output;
|
||||
mutable bool HadContextSensitiveCondition;
|
||||
mutable bool HadHeadSensitiveCondition;
|
||||
mutable bool HadLinkLanguageSensitiveCondition;
|
||||
mutable std::set<cmGeneratorTarget const*> SourceSensitiveTargets;
|
||||
};
|
||||
|
||||
|
@ -19,6 +19,7 @@ cmGeneratorExpressionContext::cmGeneratorExpressionContext(
|
||||
, HadError(false)
|
||||
, HadContextSensitiveCondition(false)
|
||||
, HadHeadSensitiveCondition(false)
|
||||
, HadLinkLanguageSensitiveCondition(false)
|
||||
, EvaluateForBuildsystem(evaluateForBuildsystem)
|
||||
{
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ struct cmGeneratorExpressionContext
|
||||
bool HadError;
|
||||
bool HadContextSensitiveCondition;
|
||||
bool HadHeadSensitiveCondition;
|
||||
bool HadLinkLanguageSensitiveCondition;
|
||||
bool EvaluateForBuildsystem;
|
||||
};
|
||||
|
||||
|
@ -6,6 +6,10 @@
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#include <cm/string_view>
|
||||
|
||||
#include "cm_static_string_view.hxx"
|
||||
|
||||
#include "cmGeneratorExpressionContext.h"
|
||||
#include "cmGeneratorExpressionEvaluator.h"
|
||||
#include "cmGeneratorTarget.h"
|
||||
@ -170,6 +174,21 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingPICExpression()
|
||||
return top->Property == "INTERFACE_POSITION_INDEPENDENT_CODE";
|
||||
}
|
||||
|
||||
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkExpression()
|
||||
{
|
||||
const cmGeneratorExpressionDAGChecker* top = this;
|
||||
const cmGeneratorExpressionDAGChecker* parent = this->Parent;
|
||||
while (parent) {
|
||||
top = parent;
|
||||
parent = parent->Parent;
|
||||
}
|
||||
|
||||
cm::string_view property(top->Property);
|
||||
|
||||
return property == "LINK_DIRECTORIES"_s || property == "LINK_OPTIONS"_s ||
|
||||
property == "LINK_DEPENDS"_s;
|
||||
}
|
||||
|
||||
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(
|
||||
cmGeneratorTarget const* tgt)
|
||||
{
|
||||
@ -180,18 +199,17 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(
|
||||
parent = parent->Parent;
|
||||
}
|
||||
|
||||
const char* prop = top->Property.c_str();
|
||||
cm::string_view prop(top->Property);
|
||||
|
||||
if (tgt) {
|
||||
return top->Target == tgt && strcmp(prop, "LINK_LIBRARIES") == 0;
|
||||
return top->Target == tgt && prop == "LINK_LIBRARIES"_s;
|
||||
}
|
||||
|
||||
return (strcmp(prop, "LINK_LIBRARIES") == 0 ||
|
||||
strcmp(prop, "LINK_INTERFACE_LIBRARIES") == 0 ||
|
||||
strcmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES") == 0 ||
|
||||
cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES_") ||
|
||||
cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_")) ||
|
||||
strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0;
|
||||
return prop == "LINK_LIBRARIES"_s || prop == "LINK_INTERFACE_LIBRARIES"_s ||
|
||||
prop == "IMPORTED_LINK_INTERFACE_LIBRARIES"_s ||
|
||||
cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES_") ||
|
||||
cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_") ||
|
||||
prop == "INTERFACE_LINK_LIBRARIES"_s;
|
||||
}
|
||||
|
||||
cmGeneratorTarget const* cmGeneratorExpressionDAGChecker::TopTarget() const
|
||||
|
@ -68,6 +68,7 @@ struct cmGeneratorExpressionDAGChecker
|
||||
|
||||
bool EvaluatingGenexExpression();
|
||||
bool EvaluatingPICExpression();
|
||||
bool EvaluatingLinkExpression();
|
||||
bool EvaluatingLinkLibraries(cmGeneratorTarget const* tgt = nullptr);
|
||||
|
||||
#define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const;
|
||||
|
@ -62,6 +62,9 @@ std::string cmGeneratorExpressionNode::EvaluateDependentExpression(
|
||||
if (cge->GetHadHeadSensitiveCondition()) {
|
||||
context->HadHeadSensitiveCondition = true;
|
||||
}
|
||||
if (cge->GetHadLinkLanguageSensitiveCondition()) {
|
||||
context->HadLinkLanguageSensitiveCondition = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1039,6 +1042,150 @@ static const struct CompileLanguageAndIdNode : public cmGeneratorExpressionNode
|
||||
}
|
||||
} languageAndIdNode;
|
||||
|
||||
static const struct LinkLanguageNode : public cmGeneratorExpressionNode
|
||||
{
|
||||
LinkLanguageNode() {} // NOLINT(modernize-use-equals-default)
|
||||
|
||||
int NumExpectedParameters() const override { return ZeroOrMoreParameters; }
|
||||
|
||||
std::string Evaluate(
|
||||
const std::vector<std::string>& parameters,
|
||||
cmGeneratorExpressionContext* context,
|
||||
const GeneratorExpressionContent* content,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker) const override
|
||||
{
|
||||
if (!context->HeadTarget || !dagChecker ||
|
||||
!(dagChecker->EvaluatingLinkExpression() ||
|
||||
dagChecker->EvaluatingLinkLibraries())) {
|
||||
reportError(context, content->GetOriginalExpression(),
|
||||
"$<LINK_LANGUAGE:...> may only be used with binary targets "
|
||||
"to specify link libraries, link directories, link options "
|
||||
"and link depends.");
|
||||
return std::string();
|
||||
}
|
||||
if (dagChecker->EvaluatingLinkLibraries() && parameters.empty()) {
|
||||
reportError(
|
||||
context, content->GetOriginalExpression(),
|
||||
"$<LINK_LANGUAGE> is not supported in link libraries expression.");
|
||||
return std::string();
|
||||
}
|
||||
|
||||
cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
|
||||
std::string genName = gg->GetName();
|
||||
if (genName.find("Makefiles") == std::string::npos &&
|
||||
genName.find("Ninja") == std::string::npos &&
|
||||
genName.find("Visual Studio") == std::string::npos &&
|
||||
genName.find("Xcode") == std::string::npos &&
|
||||
genName.find("Watcom WMake") == std::string::npos) {
|
||||
reportError(context, content->GetOriginalExpression(),
|
||||
"$<LINK_LANGUAGE:...> not supported for this generator.");
|
||||
return std::string();
|
||||
}
|
||||
|
||||
if (dagChecker->EvaluatingLinkLibraries()) {
|
||||
context->HadHeadSensitiveCondition = true;
|
||||
context->HadLinkLanguageSensitiveCondition = true;
|
||||
}
|
||||
|
||||
if (parameters.empty()) {
|
||||
return context->Language;
|
||||
}
|
||||
|
||||
for (auto& param : parameters) {
|
||||
if (context->Language == param) {
|
||||
return "1";
|
||||
}
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
} linkLanguageNode;
|
||||
|
||||
namespace {
|
||||
struct LinkerId
|
||||
{
|
||||
static std::string Evaluate(const std::vector<std::string>& parameters,
|
||||
cmGeneratorExpressionContext* context,
|
||||
const GeneratorExpressionContent* content,
|
||||
const std::string& lang)
|
||||
{
|
||||
std::string const& linkerId =
|
||||
context->LG->GetMakefile()->GetSafeDefinition("CMAKE_" + lang +
|
||||
"_COMPILER_ID");
|
||||
if (parameters.empty()) {
|
||||
return linkerId;
|
||||
}
|
||||
if (linkerId.empty()) {
|
||||
return parameters.front().empty() ? "1" : "0";
|
||||
}
|
||||
static cmsys::RegularExpression linkerIdValidator("^[A-Za-z0-9_]*$");
|
||||
|
||||
for (auto& param : parameters) {
|
||||
if (!linkerIdValidator.find(param)) {
|
||||
reportError(context, content->GetOriginalExpression(),
|
||||
"Expression syntax not recognized.");
|
||||
return std::string();
|
||||
}
|
||||
|
||||
if (param == linkerId) {
|
||||
return "1";
|
||||
}
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static const struct LinkLanguageAndIdNode : public cmGeneratorExpressionNode
|
||||
{
|
||||
LinkLanguageAndIdNode() {} // NOLINT(modernize-use-equals-default)
|
||||
|
||||
int NumExpectedParameters() const override { return TwoOrMoreParameters; }
|
||||
|
||||
std::string Evaluate(
|
||||
const std::vector<std::string>& parameters,
|
||||
cmGeneratorExpressionContext* context,
|
||||
const GeneratorExpressionContent* content,
|
||||
cmGeneratorExpressionDAGChecker* dagChecker) const override
|
||||
{
|
||||
if (!context->HeadTarget || !dagChecker ||
|
||||
!(dagChecker->EvaluatingLinkExpression() ||
|
||||
dagChecker->EvaluatingLinkLibraries())) {
|
||||
reportError(
|
||||
context, content->GetOriginalExpression(),
|
||||
"$<LINK_LANG_AND_ID:lang,id> may only be used with binary targets "
|
||||
"to specify link libraries, link directories, link options, and link "
|
||||
"depends.");
|
||||
return std::string();
|
||||
}
|
||||
|
||||
cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
|
||||
std::string genName = gg->GetName();
|
||||
if (genName.find("Makefiles") == std::string::npos &&
|
||||
genName.find("Ninja") == std::string::npos &&
|
||||
genName.find("Visual Studio") == std::string::npos &&
|
||||
genName.find("Xcode") == std::string::npos &&
|
||||
genName.find("Watcom WMake") == std::string::npos) {
|
||||
reportError(
|
||||
context, content->GetOriginalExpression(),
|
||||
"$<LINK_LANG_AND_ID:lang,id> not supported for this generator.");
|
||||
return std::string();
|
||||
}
|
||||
|
||||
if (dagChecker->EvaluatingLinkLibraries()) {
|
||||
context->HadHeadSensitiveCondition = true;
|
||||
context->HadLinkLanguageSensitiveCondition = true;
|
||||
}
|
||||
|
||||
const std::string& lang = context->Language;
|
||||
if (lang == parameters.front()) {
|
||||
std::vector<std::string> idParameter((parameters.cbegin() + 1),
|
||||
parameters.cend());
|
||||
return LinkerId::Evaluate(idParameter, context, content, lang);
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
} linkLanguageAndIdNode;
|
||||
|
||||
std::string getLinkedTargetsContent(
|
||||
cmGeneratorTarget const* target, std::string const& prop,
|
||||
cmGeneratorExpressionContext* context,
|
||||
@ -2314,6 +2461,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
|
||||
{ "LINK_ONLY", &linkOnlyNode },
|
||||
{ "COMPILE_LANG_AND_ID", &languageAndIdNode },
|
||||
{ "COMPILE_LANGUAGE", &languageNode },
|
||||
{ "LINK_LANG_AND_ID", &linkLanguageAndIdNode },
|
||||
{ "LINK_LANGUAGE", &linkLanguageNode },
|
||||
{ "SHELL_PATH", &shellPathNode }
|
||||
};
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include <cm/memory>
|
||||
#include <cm/string_view>
|
||||
#include <cmext/algorithm>
|
||||
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
|
||||
@ -308,6 +309,13 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
|
||||
this->SourceEntries, true);
|
||||
|
||||
this->PolicyMap = t->GetPolicyMap();
|
||||
|
||||
// Get hard-coded linker language
|
||||
if (this->Target->GetProperty("HAS_CXX")) {
|
||||
this->LinkerLanguage = "CXX";
|
||||
} else {
|
||||
this->LinkerLanguage = this->Target->GetSafeProperty("LINKER_LANGUAGE");
|
||||
}
|
||||
}
|
||||
|
||||
cmGeneratorTarget::~cmGeneratorTarget() = default;
|
||||
@ -2223,11 +2231,12 @@ public:
|
||||
cmTargetCollectLinkLanguages(cmGeneratorTarget const* target,
|
||||
std::string config,
|
||||
std::unordered_set<std::string>& languages,
|
||||
cmGeneratorTarget const* head)
|
||||
cmGeneratorTarget const* head, bool secondPass)
|
||||
: Config(std::move(config))
|
||||
, Languages(languages)
|
||||
, HeadTarget(head)
|
||||
, Target(target)
|
||||
, SecondPass(secondPass)
|
||||
{
|
||||
this->Visited.insert(target);
|
||||
}
|
||||
@ -2269,11 +2278,14 @@ public:
|
||||
if (!this->Visited.insert(item.Target).second) {
|
||||
return;
|
||||
}
|
||||
cmLinkInterface const* iface =
|
||||
item.Target->GetLinkInterface(this->Config, this->HeadTarget);
|
||||
cmLinkInterface const* iface = item.Target->GetLinkInterface(
|
||||
this->Config, this->HeadTarget, this->SecondPass);
|
||||
if (!iface) {
|
||||
return;
|
||||
}
|
||||
if (iface->HadLinkLanguageSensitiveCondition) {
|
||||
this->HadLinkLanguageSensitiveCondition = true;
|
||||
}
|
||||
|
||||
for (std::string const& language : iface->Languages) {
|
||||
this->Languages.insert(language);
|
||||
@ -2284,12 +2296,19 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool GetHadLinkLanguageSensitiveCondition()
|
||||
{
|
||||
return HadLinkLanguageSensitiveCondition;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string Config;
|
||||
std::unordered_set<std::string>& Languages;
|
||||
cmGeneratorTarget const* HeadTarget;
|
||||
const cmGeneratorTarget* Target;
|
||||
std::set<cmGeneratorTarget const*> Visited;
|
||||
bool SecondPass;
|
||||
bool HadLinkLanguageSensitiveCondition = false;
|
||||
};
|
||||
|
||||
cmGeneratorTarget::LinkClosure const* cmGeneratorTarget::GetLinkClosure(
|
||||
@ -2320,7 +2339,7 @@ public:
|
||||
{
|
||||
this->GG = this->Target->GetLocalGenerator()->GetGlobalGenerator();
|
||||
}
|
||||
void Consider(const char* lang)
|
||||
void Consider(const std::string& lang)
|
||||
{
|
||||
int preference = this->GG->GetLinkerPreference(lang);
|
||||
if (preference > this->Preference) {
|
||||
@ -2353,40 +2372,36 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
|
||||
LinkClosure& lc) const
|
||||
bool cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
|
||||
LinkClosure& lc,
|
||||
bool secondPass) const
|
||||
{
|
||||
// Get languages built in this target.
|
||||
std::unordered_set<std::string> languages;
|
||||
cmLinkImplementation const* impl = this->GetLinkImplementation(config);
|
||||
cmLinkImplementation const* impl =
|
||||
this->GetLinkImplementation(config, secondPass);
|
||||
assert(impl);
|
||||
for (std::string const& li : impl->Languages) {
|
||||
languages.insert(li);
|
||||
}
|
||||
languages.insert(impl->Languages.cbegin(), impl->Languages.cend());
|
||||
|
||||
// Add interface languages from linked targets.
|
||||
cmTargetCollectLinkLanguages cll(this, config, languages, this);
|
||||
// cmTargetCollectLinkLanguages cll(this, config, languages, this,
|
||||
// secondPass);
|
||||
cmTargetCollectLinkLanguages cll(this, config, languages, this, secondPass);
|
||||
for (cmLinkImplItem const& lib : impl->Libraries) {
|
||||
cll.Visit(lib);
|
||||
}
|
||||
|
||||
// Store the transitive closure of languages.
|
||||
for (std::string const& lang : languages) {
|
||||
lc.Languages.push_back(lang);
|
||||
}
|
||||
cm::append(lc.Languages, languages);
|
||||
|
||||
// Choose the language whose linker should be used.
|
||||
if (this->GetProperty("HAS_CXX")) {
|
||||
lc.LinkerLanguage = "CXX";
|
||||
} else if (const char* linkerLang = this->GetProperty("LINKER_LANGUAGE")) {
|
||||
lc.LinkerLanguage = linkerLang;
|
||||
} else {
|
||||
if (secondPass || lc.LinkerLanguage.empty()) {
|
||||
// Find the language with the highest preference value.
|
||||
cmTargetSelectLinker tsl(this);
|
||||
|
||||
// First select from the languages compiled directly in this target.
|
||||
for (std::string const& l : impl->Languages) {
|
||||
tsl.Consider(l.c_str());
|
||||
tsl.Consider(l);
|
||||
}
|
||||
|
||||
// Now consider languages that propagate from linked targets.
|
||||
@ -2394,12 +2409,50 @@ void cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
|
||||
std::string propagates =
|
||||
"CMAKE_" + lang + "_LINKER_PREFERENCE_PROPAGATES";
|
||||
if (this->Makefile->IsOn(propagates)) {
|
||||
tsl.Consider(lang.c_str());
|
||||
tsl.Consider(lang);
|
||||
}
|
||||
}
|
||||
|
||||
lc.LinkerLanguage = tsl.Choose();
|
||||
}
|
||||
|
||||
return impl->HadLinkLanguageSensitiveCondition ||
|
||||
cll.GetHadLinkLanguageSensitiveCondition();
|
||||
}
|
||||
|
||||
void cmGeneratorTarget::ComputeLinkClosure(const std::string& config,
|
||||
LinkClosure& lc) const
|
||||
{
|
||||
bool secondPass = false;
|
||||
|
||||
{
|
||||
LinkClosure linkClosure;
|
||||
linkClosure.LinkerLanguage = this->LinkerLanguage;
|
||||
|
||||
// Get languages built in this target.
|
||||
secondPass = this->ComputeLinkClosure(config, linkClosure, false);
|
||||
this->LinkerLanguage = linkClosure.LinkerLanguage;
|
||||
if (!secondPass) {
|
||||
lc = std::move(linkClosure);
|
||||
}
|
||||
}
|
||||
|
||||
if (secondPass) {
|
||||
LinkClosure linkClosure;
|
||||
|
||||
this->ComputeLinkClosure(config, linkClosure, secondPass);
|
||||
lc = std::move(linkClosure);
|
||||
|
||||
// linker language must not be changed between the two passes
|
||||
if (this->LinkerLanguage != lc.LinkerLanguage) {
|
||||
std::ostringstream e;
|
||||
e << "Evaluation of $<LINK_LANGUAGE:...> or $<LINK_LAND_AND_ID:...> "
|
||||
"changes\nthe linker language for target \""
|
||||
<< this->GetName() << "\" (from '" << this->LinkerLanguage << "' to '"
|
||||
<< lc.LinkerLanguage << "') which is invalid.";
|
||||
cmSystemTools::Error(e.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cmGeneratorTarget::GetFullNameComponents(
|
||||
@ -5492,7 +5545,8 @@ void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names,
|
||||
void cmGeneratorTarget::ExpandLinkItems(
|
||||
std::string const& prop, std::string const& value, std::string const& config,
|
||||
cmGeneratorTarget const* headTarget, bool usage_requirements_only,
|
||||
std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition) const
|
||||
std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition,
|
||||
bool& hadLinkLanguageSensitiveCondition) const
|
||||
{
|
||||
// Keep this logic in sync with ComputeLinkImplementationLibraries.
|
||||
cmGeneratorExpression ge;
|
||||
@ -5504,19 +5558,28 @@ void cmGeneratorTarget::ExpandLinkItems(
|
||||
}
|
||||
std::vector<std::string> libs;
|
||||
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
|
||||
cmExpandList(
|
||||
cge->Evaluate(this->LocalGenerator, config, headTarget, &dagChecker, this),
|
||||
libs);
|
||||
cmExpandList(cge->Evaluate(this->LocalGenerator, config, headTarget,
|
||||
&dagChecker, this, headTarget->LinkerLanguage),
|
||||
libs);
|
||||
this->LookupLinkItems(libs, cge->GetBacktrace(), items);
|
||||
hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition();
|
||||
hadLinkLanguageSensitiveCondition =
|
||||
cge->GetHadLinkLanguageSensitiveCondition();
|
||||
}
|
||||
|
||||
cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
|
||||
const std::string& config, cmGeneratorTarget const* head) const
|
||||
{
|
||||
return this->GetLinkInterface(config, head, false);
|
||||
}
|
||||
|
||||
cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
|
||||
const std::string& config, cmGeneratorTarget const* head,
|
||||
bool secondPass) const
|
||||
{
|
||||
// Imported targets have their own link interface.
|
||||
if (this->IsImported()) {
|
||||
return this->GetImportLinkInterface(config, head, false);
|
||||
return this->GetImportLinkInterface(config, head, false, secondPass);
|
||||
}
|
||||
|
||||
// Link interfaces are not supported for executables that do not
|
||||
@ -5529,6 +5592,10 @@ cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
|
||||
// Lookup any existing link interface for this configuration.
|
||||
cmHeadToLinkInterfaceMap& hm = this->GetHeadToLinkInterfaceMap(config);
|
||||
|
||||
if (secondPass) {
|
||||
hm.erase(head);
|
||||
}
|
||||
|
||||
// If the link interface does not depend on the head target
|
||||
// then return the one we computed first.
|
||||
if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
|
||||
@ -5543,7 +5610,7 @@ cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
|
||||
if (!iface.AllDone) {
|
||||
iface.AllDone = true;
|
||||
if (iface.Exists) {
|
||||
this->ComputeLinkInterface(config, iface, head);
|
||||
this->ComputeLinkInterface(config, iface, head, secondPass);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5553,6 +5620,13 @@ cmLinkInterface const* cmGeneratorTarget::GetLinkInterface(
|
||||
void cmGeneratorTarget::ComputeLinkInterface(
|
||||
const std::string& config, cmOptionalLinkInterface& iface,
|
||||
cmGeneratorTarget const* headTarget) const
|
||||
{
|
||||
this->ComputeLinkInterface(config, iface, headTarget, false);
|
||||
}
|
||||
|
||||
void cmGeneratorTarget::ComputeLinkInterface(
|
||||
const std::string& config, cmOptionalLinkInterface& iface,
|
||||
cmGeneratorTarget const* headTarget, bool secondPass) const
|
||||
{
|
||||
if (iface.Explicit) {
|
||||
if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
|
||||
@ -5565,7 +5639,8 @@ void cmGeneratorTarget::ComputeLinkInterface(
|
||||
emitted.insert(lib);
|
||||
}
|
||||
if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
|
||||
cmLinkImplementation const* impl = this->GetLinkImplementation(config);
|
||||
cmLinkImplementation const* impl =
|
||||
this->GetLinkImplementation(config, secondPass);
|
||||
for (cmLinkImplItem const& lib : impl->Libraries) {
|
||||
if (emitted.insert(lib).second) {
|
||||
if (lib.Target) {
|
||||
@ -5595,7 +5670,7 @@ void cmGeneratorTarget::ComputeLinkInterface(
|
||||
if (this->LinkLanguagePropagatesToDependents()) {
|
||||
// Targets using this archive need its language runtime libraries.
|
||||
if (cmLinkImplementation const* impl =
|
||||
this->GetLinkImplementation(config)) {
|
||||
this->GetLinkImplementation(config, secondPass)) {
|
||||
iface.Languages = impl->Languages;
|
||||
}
|
||||
}
|
||||
@ -5991,7 +6066,8 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
|
||||
// The interface libraries have been explicitly set.
|
||||
this->ExpandLinkItems(linkIfaceProp, explicitLibraries, config, headTarget,
|
||||
usage_requirements_only, iface.Libraries,
|
||||
iface.HadHeadSensitiveCondition);
|
||||
iface.HadHeadSensitiveCondition,
|
||||
iface.HadLinkLanguageSensitiveCondition);
|
||||
} else if (!cmp0022NEW)
|
||||
// If CMP0022 is NEW then the plain tll signature sets the
|
||||
// INTERFACE_LINK_LIBRARIES, so if we get here then the project
|
||||
@ -6011,9 +6087,11 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
|
||||
static const std::string newProp = "INTERFACE_LINK_LIBRARIES";
|
||||
if (const char* newExplicitLibraries = this->GetProperty(newProp)) {
|
||||
bool hadHeadSensitiveConditionDummy = false;
|
||||
bool hadLinkLanguageSensitiveConditionDummy = false;
|
||||
this->ExpandLinkItems(newProp, newExplicitLibraries, config,
|
||||
headTarget, usage_requirements_only, ifaceLibs,
|
||||
hadHeadSensitiveConditionDummy);
|
||||
hadHeadSensitiveConditionDummy,
|
||||
hadLinkLanguageSensitiveConditionDummy);
|
||||
}
|
||||
if (ifaceLibs != iface.Libraries) {
|
||||
std::string oldLibraries = cmJoin(impl->Libraries, ";");
|
||||
@ -6050,7 +6128,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
|
||||
|
||||
const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
|
||||
const std::string& config, cmGeneratorTarget const* headTarget,
|
||||
bool usage_requirements_only) const
|
||||
bool usage_requirements_only, bool secondPass) const
|
||||
{
|
||||
cmGeneratorTarget::ImportInfo const* info = this->GetImportInfo(config);
|
||||
if (!info) {
|
||||
@ -6063,6 +6141,10 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
|
||||
? this->GetHeadToLinkInterfaceUsageRequirementsMap(config)
|
||||
: this->GetHeadToLinkInterfaceMap(config));
|
||||
|
||||
if (secondPass) {
|
||||
hm.erase(headTarget);
|
||||
}
|
||||
|
||||
// If the link interface does not depend on the head target
|
||||
// then return the one we computed first.
|
||||
if (!hm.empty() && !hm.begin()->second.HadHeadSensitiveCondition) {
|
||||
@ -6076,7 +6158,8 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface(
|
||||
cmExpandList(info->Languages, iface.Languages);
|
||||
this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config,
|
||||
headTarget, usage_requirements_only, iface.Libraries,
|
||||
iface.HadHeadSensitiveCondition);
|
||||
iface.HadHeadSensitiveCondition,
|
||||
iface.HadLinkLanguageSensitiveCondition);
|
||||
std::vector<std::string> deps = cmExpandedList(info->SharedDeps);
|
||||
this->LookupLinkItems(deps, cmListFileBacktrace(), iface.SharedDeps);
|
||||
}
|
||||
@ -6280,6 +6363,12 @@ cmGeneratorTarget::GetHeadToLinkInterfaceUsageRequirementsMap(
|
||||
|
||||
const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
|
||||
const std::string& config) const
|
||||
{
|
||||
return this->GetLinkImplementation(config, false);
|
||||
}
|
||||
|
||||
const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
|
||||
const std::string& config, bool secondPass) const
|
||||
{
|
||||
// There is no link implementation for imported targets.
|
||||
if (this->IsImported()) {
|
||||
@ -6288,6 +6377,9 @@ const cmLinkImplementation* cmGeneratorTarget::GetLinkImplementation(
|
||||
|
||||
std::string CONFIG = cmSystemTools::UpperCase(config);
|
||||
cmOptionalLinkImplementation& impl = this->LinkImplMap[CONFIG][this];
|
||||
if (secondPass) {
|
||||
impl = cmOptionalLinkImplementation();
|
||||
}
|
||||
if (!impl.LibrariesDone) {
|
||||
impl.LibrariesDone = true;
|
||||
this->ComputeLinkImplementationLibraries(config, impl, this);
|
||||
@ -6585,11 +6677,15 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
|
||||
cmGeneratorExpression ge(*btIt);
|
||||
std::unique_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(*le);
|
||||
std::string const& evaluated =
|
||||
cge->Evaluate(this->LocalGenerator, config, head, &dagChecker);
|
||||
cge->Evaluate(this->LocalGenerator, config, head, &dagChecker, nullptr,
|
||||
this->LinkerLanguage);
|
||||
cmExpandList(evaluated, llibs);
|
||||
if (cge->GetHadHeadSensitiveCondition()) {
|
||||
impl.HadHeadSensitiveCondition = true;
|
||||
}
|
||||
if (cge->GetHadLinkLanguageSensitiveCondition()) {
|
||||
impl.HadLinkLanguageSensitiveCondition = true;
|
||||
}
|
||||
|
||||
for (std::string const& lib : llibs) {
|
||||
if (this->IsLinkLookupScope(lib, lg)) {
|
||||
|
@ -357,7 +357,6 @@ public:
|
||||
};
|
||||
|
||||
LinkClosure const* GetLinkClosure(const std::string& config) const;
|
||||
void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const;
|
||||
|
||||
cmLinkImplementation const* GetLinkImplementation(
|
||||
const std::string& config) const;
|
||||
@ -816,6 +815,7 @@ private:
|
||||
std::string& outPrefix, std::string& outBase,
|
||||
std::string& outSuffix) const;
|
||||
|
||||
mutable std::string LinkerLanguage;
|
||||
using LinkClosureMapType = std::map<std::string, LinkClosure>;
|
||||
mutable LinkClosureMapType LinkClosureMap;
|
||||
|
||||
@ -850,6 +850,10 @@ private:
|
||||
void CheckPropertyCompatibility(cmComputeLinkInformation& info,
|
||||
const std::string& config) const;
|
||||
|
||||
void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const;
|
||||
bool ComputeLinkClosure(const std::string& config, LinkClosure& lc,
|
||||
bool secondPass) const;
|
||||
|
||||
struct LinkImplClosure : public std::vector<cmGeneratorTarget const*>
|
||||
{
|
||||
bool Done = false;
|
||||
@ -868,6 +872,17 @@ private:
|
||||
std::string GetLinkInterfaceDependentStringAsBoolProperty(
|
||||
const std::string& p, const std::string& config) const;
|
||||
|
||||
friend class cmTargetCollectLinkLanguages;
|
||||
cmLinkInterface const* GetLinkInterface(const std::string& config,
|
||||
const cmGeneratorTarget* headTarget,
|
||||
bool secondPass) const;
|
||||
void ComputeLinkInterface(const std::string& config,
|
||||
cmOptionalLinkInterface& iface,
|
||||
const cmGeneratorTarget* head,
|
||||
bool secondPass) const;
|
||||
cmLinkImplementation const* GetLinkImplementation(const std::string& config,
|
||||
bool secondPass) const;
|
||||
|
||||
// Cache import information from properties for each configuration.
|
||||
struct ImportInfo
|
||||
{
|
||||
@ -894,9 +909,10 @@ private:
|
||||
the link dependencies of this target. */
|
||||
std::string CheckCMP0004(std::string const& item) const;
|
||||
|
||||
cmLinkInterface const* GetImportLinkInterface(
|
||||
const std::string& config, const cmGeneratorTarget* head,
|
||||
bool usage_requirements_only) const;
|
||||
cmLinkInterface const* GetImportLinkInterface(const std::string& config,
|
||||
const cmGeneratorTarget* head,
|
||||
bool usage_requirements_only,
|
||||
bool secondPass = false) const;
|
||||
|
||||
using KindedSourcesMapType = std::map<std::string, KindedSources>;
|
||||
mutable KindedSourcesMapType KindedSourcesMap;
|
||||
@ -940,7 +956,8 @@ private:
|
||||
const cmGeneratorTarget* headTarget,
|
||||
bool usage_requirements_only,
|
||||
std::vector<cmLinkItem>& items,
|
||||
bool& hadHeadSensitiveCondition) const;
|
||||
bool& hadHeadSensitiveCondition,
|
||||
bool& hadLinkLanguageSensitiveCondition) const;
|
||||
void LookupLinkItems(std::vector<std::string> const& names,
|
||||
cmListFileBacktrace const& bt,
|
||||
std::vector<cmLinkItem>& items) const;
|
||||
|
@ -81,6 +81,9 @@ struct cmLinkInterface : public cmLinkInterfaceLibraries
|
||||
std::vector<cmLinkItem> WrongConfigLibraries;
|
||||
|
||||
bool ImplementationIsInterface = false;
|
||||
|
||||
// Whether the list depends on a link language genex.
|
||||
bool HadLinkLanguageSensitiveCondition = false;
|
||||
};
|
||||
|
||||
struct cmOptionalLinkInterface : public cmLinkInterface
|
||||
@ -100,6 +103,9 @@ struct cmLinkImplementation : public cmLinkImplementationLibraries
|
||||
{
|
||||
// Languages whose runtime libraries must be linked.
|
||||
std::vector<std::string> Languages;
|
||||
|
||||
// Whether the list depends on a link language genex.
|
||||
bool HadLinkLanguageSensitiveCondition = false;
|
||||
};
|
||||
|
||||
// Cache link implementation computation from each configuration.
|
||||
|
@ -366,6 +366,28 @@ is not newer than dependency
|
||||
${linkdep2}
|
||||
is not newer than dependency
|
||||
${TEST_LINK_DEPENDS}
|
||||
")
|
||||
endif()
|
||||
|
||||
set(linkdep3 ${BuildDepends_BINARY_DIR}/Project/linkdep3${CMAKE_EXECUTABLE_SUFFIX})
|
||||
if(${linkdep3} IS_NEWER_THAN ${TEST_LINK_DEPENDS})
|
||||
message("$<LINK_LANGUAGE> in LINK_DEPENDS worked")
|
||||
else()
|
||||
message(SEND_ERROR "$<LINK_LANGUAGE> in LINK_DEPENDS failed. Executable
|
||||
${linkdep3}
|
||||
is not newer than dependency
|
||||
${TEST_LINK_DEPENDS}
|
||||
")
|
||||
endif()
|
||||
|
||||
set(linkdep4 ${BuildDepends_BINARY_DIR}/Project/linkdep4${CMAKE_EXECUTABLE_SUFFIX})
|
||||
if(${linkdep4} IS_NEWER_THAN ${TEST_LINK_DEPENDS})
|
||||
message("$<LINK_LANGUAGE> in INTERFACE_LINK_DEPENDS worked")
|
||||
else()
|
||||
message(SEND_ERROR "$<LINK_LANGUAGE> in INTERFACE_LINK_DEPENDS failed. Executable
|
||||
${linkdep4}
|
||||
is not newer than dependency
|
||||
${TEST_LINK_DEPENDS}
|
||||
")
|
||||
endif()
|
||||
endif()
|
||||
|
@ -118,6 +118,14 @@ if(TEST_LINK_DEPENDS)
|
||||
set_property(TARGET foo_interface PROPERTY INTERFACE_LINK_DEPENDS $<1:${TEST_LINK_DEPENDS}>)
|
||||
add_executable(linkdep2 linkdep.cxx)
|
||||
target_link_libraries(linkdep2 PRIVATE foo_interface)
|
||||
|
||||
add_executable(linkdep3 linkdep.cxx)
|
||||
set_property(TARGET linkdep3 PROPERTY LINK_DEPENDS $<$<LINK_LANGUAGE:CXX>:${TEST_LINK_DEPENDS}>)
|
||||
|
||||
add_library(foo_interface2 INTERFACE)
|
||||
set_property(TARGET foo_interface2 PROPERTY INTERFACE_LINK_DEPENDS $<$<LINK_LANGUAGE:CXX>:${TEST_LINK_DEPENDS}>)
|
||||
add_executable(linkdep4 linkdep.cxx)
|
||||
target_link_libraries(linkdep4 PRIVATE foo_interface2)
|
||||
endif()
|
||||
|
||||
add_library(link_depends_no_shared_lib SHARED link_depends_no_shared_lib.c
|
||||
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANGUAGE-add_custom_command.cmake:2 \(add_custom_command\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANGUAGE>
|
||||
|
||||
\$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
|
||||
libraries, link directories, link options and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,4 @@
|
||||
add_custom_target(drive)
|
||||
add_custom_command(TARGET drive PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo $<LINK_LANGUAGE>
|
||||
)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANGUAGE-add_custom_target.cmake:1 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANGUAGE>
|
||||
|
||||
\$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
|
||||
libraries, link directories, link options and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,3 @@
|
||||
add_custom_target(drive
|
||||
COMMAND ${CMAKE_COMMAND} -E echo $<LINK_LANGUAGE>
|
||||
)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANGUAGE-add_executable.cmake:1 \(add_executable\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANGUAGE>
|
||||
|
||||
\$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
|
||||
libraries, link directories, link options and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1 @@
|
||||
add_executable(empty empty.$<LINK_LANGUAGE>)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANGUAGE-add_library.cmake:1 \(add_library\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANGUAGE>
|
||||
|
||||
\$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
|
||||
libraries, link directories, link options and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1 @@
|
||||
add_library(empty empty.$<LINK_LANGUAGE>)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANGUAGE-add_test.cmake:5 \(add_test\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANGUAGE>
|
||||
|
||||
\$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
|
||||
libraries, link directories, link options and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,5 @@
|
||||
|
||||
include(CTest)
|
||||
enable_testing()
|
||||
|
||||
add_test(NAME dummy COMMAND ${CMAKE_COMMAND} -E echo $<LINK_LANGUAGE>)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANGUAGE-file_generate.cmake:3 \(file\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANGUAGE>
|
||||
|
||||
\$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
|
||||
libraries, link directories, link options and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,6 @@
|
||||
enable_language(CXX C)
|
||||
|
||||
file(GENERATE
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/output.txt
|
||||
CONTENT "LANG_IS_$<LINK_LANGUAGE>\n"
|
||||
)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,10 @@
|
||||
CMake Error:
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANGUAGE>
|
||||
|
||||
\$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
|
||||
libraries, link directories, link options and link depends.
|
||||
|
||||
|
||||
CMake Generate step failed. Build files cannot be regenerated correctly.
|
@ -0,0 +1,5 @@
|
||||
|
||||
install(FILES
|
||||
empty.$<LINK_LANGUAGE>
|
||||
DESTINATION src
|
||||
)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANGUAGE-target_sources.cmake:2 \(target_sources\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANGUAGE>
|
||||
|
||||
\$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
|
||||
libraries, link directories, link options and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,2 @@
|
||||
add_library(empty)
|
||||
target_sources(empty PRIVATE empty.$<LINK_LANGUAGE>)
|
@ -0,0 +1,4 @@
|
||||
|
||||
enable_language(C)
|
||||
add_executable(empty empty.c)
|
||||
target_link_options(empty PRIVATE $<$<LINK_LANGUAGE:CXX>:$<TARGET_EXISTS:too,many,parameters>>)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANGUAGE-wrong-usage1.cmake:4 \(target_compile_definitions\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANGUAGE:C>
|
||||
|
||||
\$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
|
||||
libraries, link directories, link options and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,4 @@
|
||||
|
||||
enable_language(C)
|
||||
add_executable(empty empty.c)
|
||||
target_compile_definitions(empty PRIVATE $<$<LINK_LANGUAGE:C>:DEF>)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANGUAGE-wrong-usage2.cmake:4 \(target_compile_options\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANGUAGE:C>
|
||||
|
||||
\$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
|
||||
libraries, link directories, link options and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,4 @@
|
||||
|
||||
enable_language(C)
|
||||
add_executable(empty empty.c)
|
||||
target_compile_options(empty PRIVATE $<$<LINK_LANGUAGE:C>:-OPT>)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANGUAGE-wrong-usage3.cmake:4 \(target_include_directories\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANGUAGE:C>
|
||||
|
||||
\$<LINK_LANGUAGE:...> may only be used with binary targets to specify link
|
||||
libraries, link directories, link options and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,4 @@
|
||||
|
||||
enable_language(C)
|
||||
add_executable(empty empty.c)
|
||||
target_include_directories(empty PRIVATE $<$<LINK_LANGUAGE:C>:/DIR>)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,8 @@
|
||||
CMake Error at LINK_LANGUAGE-wrong-usage4.cmake:7 \(target_link_libraries\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANGUAGE>
|
||||
|
||||
\$<LINK_LANGUAGE> is not supported in link libraries expression.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,7 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
add_library(libC empty.c)
|
||||
|
||||
add_executable(empty empty.c)
|
||||
target_link_libraries(empty PRIVATE lib$<LINK_LANGUAGE>)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANG_AND_ID-add_custom_command.cmake:2 \(add_custom_command\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANG_AND_ID:LANG,ID>
|
||||
|
||||
\$<LINK_LANG_AND_ID:lang,id> may only be used with binary targets to specify
|
||||
link libraries, link directories, link options, and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,4 @@
|
||||
add_custom_target(drive)
|
||||
add_custom_command(TARGET drive PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo $<LINK_LANG_AND_ID:LANG,ID>
|
||||
)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANG_AND_ID-add_custom_target.cmake:2 \(add_custom_target\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANG_AND_ID:LANG,ID>
|
||||
|
||||
\$<LINK_LANG_AND_ID:lang,id> may only be used with binary targets to specify
|
||||
link libraries, link directories, link options, and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,4 @@
|
||||
|
||||
add_custom_target(drive
|
||||
COMMAND ${CMAKE_COMMAND} -E echo $<LINK_LANG_AND_ID:LANG,ID>
|
||||
)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANG_AND_ID-add_executable.cmake:1 \(add_executable\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANG_AND_ID:C,MSVC>
|
||||
|
||||
\$<LINK_LANG_AND_ID:lang,id> may only be used with binary targets to specify
|
||||
link libraries, link directories, link options, and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,5 @@
|
||||
add_executable(empty main.c
|
||||
$<$<LINK_LANG_AND_ID:C,MSVC>:empty.c>
|
||||
$<$<LINK_LANG_AND_ID:C,GNU>:empty2.c>
|
||||
$<$<LINK_LANG_AND_ID:C,Clang>:empty3.c>
|
||||
)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANG_AND_ID-add_library.cmake:2 \(add_library\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANG_AND_ID:C,MSVC>
|
||||
|
||||
\$<LINK_LANG_AND_ID:lang,id> may only be used with binary targets to specify
|
||||
link libraries, link directories, link options, and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,2 @@
|
||||
|
||||
add_library(empty empty.$<LINK_LANG_AND_ID:C,MSVC>)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANG_AND_ID-add_test.cmake:5 \(add_test\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANG_AND_ID:CXX,GNU>
|
||||
|
||||
\$<LINK_LANG_AND_ID:lang,id> may only be used with binary targets to specify
|
||||
link libraries, link directories, link options, and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,5 @@
|
||||
|
||||
include(CTest)
|
||||
enable_testing()
|
||||
|
||||
add_test(NAME dummy COMMAND ${CMAKE_COMMAND} -E echo $<LINK_LANG_AND_ID:CXX,GNU>)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANG_AND_ID-file_generate.cmake:3 \(file\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANG_AND_ID:C,GNU>
|
||||
|
||||
\$<LINK_LANG_AND_ID:lang,id> may only be used with binary targets to specify
|
||||
link libraries, link directories, link options, and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,6 @@
|
||||
enable_language(CXX C)
|
||||
|
||||
file(GENERATE
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/output.txt
|
||||
CONTENT "LANG_IS_$<$<LINK_LANG_AND_ID:C,GNU>:C>\n"
|
||||
)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,10 @@
|
||||
CMake Error:
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANG_AND_ID:C,MSVC>
|
||||
|
||||
\$<LINK_LANG_AND_ID:lang,id> may only be used with binary targets to specify
|
||||
link libraries, link directories, link options, and link depends.
|
||||
|
||||
|
||||
CMake Generate step failed. Build files cannot be regenerated correctly.
|
@ -0,0 +1,5 @@
|
||||
|
||||
install(FILES
|
||||
empty.$<LINK_LANG_AND_ID:C,MSVC>
|
||||
DESTINATION src
|
||||
)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,8 @@
|
||||
CMake Error at LINK_LANG_AND_ID-target_sources.cmake:2 \(target_sources\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANG_AND_ID>
|
||||
|
||||
\$<LINK_LANG_AND_ID> expression requires at least two parameters.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,2 @@
|
||||
add_library(empty)
|
||||
target_sources(empty PRIVATE empty.$<LINK_LANG_AND_ID>)
|
@ -0,0 +1,4 @@
|
||||
|
||||
enable_language(C)
|
||||
add_executable(empty empty.c)
|
||||
target_link_options(empty PRIVATE $<$<LINK_LANG_AND_ID:CXX,GNU>:$<TARGET_EXISTS:too,many,parameters>>)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANG_AND_ID-wrong-usage1.cmake:4 \(target_compile_definitions\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANG_AND_ID:C,GNU>
|
||||
|
||||
\$<LINK_LANG_AND_ID:lang,id> may only be used with binary targets to specify
|
||||
link libraries, link directories, link options, and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,4 @@
|
||||
|
||||
enable_language(C)
|
||||
add_executable(empty empty.c)
|
||||
target_compile_definitions(empty PRIVATE $<$<LINK_LANG_AND_ID:C,GNU>:DEF>)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANG_AND_ID-wrong-usage2.cmake:4 \(target_compile_options\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANG_AND_ID:C,GNU>
|
||||
|
||||
\$<LINK_LANG_AND_ID:lang,id> may only be used with binary targets to specify
|
||||
link libraries, link directories, link options, and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,4 @@
|
||||
|
||||
enable_language(C)
|
||||
add_executable(empty empty.c)
|
||||
target_compile_options(empty PRIVATE $<$<LINK_LANG_AND_ID:C,GNU>:-OPT>)
|
@ -0,0 +1 @@
|
||||
1
|
@ -0,0 +1,9 @@
|
||||
CMake Error at LINK_LANG_AND_ID-wrong-usage3.cmake:4 \(target_include_directories\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<LINK_LANG_AND_ID:C,GNU>
|
||||
|
||||
\$<LINK_LANG_AND_ID:lang,id> may only be used with binary targets to specify
|
||||
link libraries, link directories, link options, and link depends.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
@ -0,0 +1,4 @@
|
||||
|
||||
enable_language(C)
|
||||
add_executable(empty empty.c)
|
||||
target_include_directories(empty PRIVATE $<$<LINK_LANG_AND_ID:C,GNU>:/DIR>)
|
@ -39,6 +39,31 @@ run_cmake(COMPILE_LANG_AND_ID-add_executable)
|
||||
run_cmake(COMPILE_LANG_AND_ID-add_library)
|
||||
run_cmake(COMPILE_LANG_AND_ID-add_test)
|
||||
run_cmake(COMPILE_LANG_AND_ID-unknown-lang)
|
||||
run_cmake(LINK_LANGUAGE-add_custom_target)
|
||||
run_cmake(LINK_LANGUAGE-add_custom_command)
|
||||
run_cmake(LINK_LANGUAGE-install)
|
||||
run_cmake(LINK_LANGUAGE-target_sources)
|
||||
run_cmake(LINK_LANGUAGE-add_executable)
|
||||
run_cmake(LINK_LANGUAGE-add_library)
|
||||
run_cmake(LINK_LANGUAGE-add_test)
|
||||
run_cmake(LINK_LANGUAGE-unknown-lang)
|
||||
run_cmake(LINK_LANGUAGE-wrong-usage1)
|
||||
run_cmake(LINK_LANGUAGE-wrong-usage2)
|
||||
run_cmake(LINK_LANGUAGE-wrong-usage3)
|
||||
run_cmake(LINK_LANGUAGE-wrong-usage4)
|
||||
run_cmake(LINK_LANGUAGE-file_generate)
|
||||
run_cmake(LINK_LANG_AND_ID-add_custom_target)
|
||||
run_cmake(LINK_LANG_AND_ID-add_custom_command)
|
||||
run_cmake(LINK_LANG_AND_ID-install)
|
||||
run_cmake(LINK_LANG_AND_ID-target_sources)
|
||||
run_cmake(LINK_LANG_AND_ID-add_executable)
|
||||
run_cmake(LINK_LANG_AND_ID-add_library)
|
||||
run_cmake(LINK_LANG_AND_ID-add_test)
|
||||
run_cmake(LINK_LANG_AND_ID-unknown-lang)
|
||||
run_cmake(LINK_LANG_AND_ID-wrong-usage1)
|
||||
run_cmake(LINK_LANG_AND_ID-wrong-usage2)
|
||||
run_cmake(LINK_LANG_AND_ID-wrong-usage3)
|
||||
run_cmake(LINK_LANG_AND_ID-file_generate)
|
||||
run_cmake(TARGET_FILE-recursion)
|
||||
run_cmake(OUTPUT_NAME-recursion)
|
||||
run_cmake(TARGET_FILE_PREFIX)
|
||||
|
@ -0,0 +1 @@
|
||||
1
|
@ -1,4 +1,4 @@
|
||||
CMake Error at LINK_LANGUAGE-genex.cmake:[0-9]+ \(target_link_libraries\):
|
||||
CMake Error at LINKER_LANGUAGE-genex.cmake:[0-9]+ \(target_link_libraries\):
|
||||
Error evaluating generator expression:
|
||||
|
||||
\$<TARGET_PROPERTY:LINKER_LANGUAGE>
|
@ -1,7 +1,7 @@
|
||||
include(RunCMake)
|
||||
|
||||
run_cmake(NoLangSHARED)
|
||||
run_cmake(LINK_LANGUAGE-genex)
|
||||
run_cmake(LINKER_LANGUAGE-genex)
|
||||
run_cmake(link-libraries-TARGET_FILE-genex)
|
||||
run_cmake(link-libraries-TARGET_FILE-genex-ok)
|
||||
|
||||
|
16
Tests/RunCMake/add_link_options/GENEX_LINK_LANG.cmake
Normal file
16
Tests/RunCMake/add_link_options/GENEX_LINK_LANG.cmake
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
set(obj "${CMAKE_C_OUTPUT_EXTENSION}")
|
||||
if(BORLAND)
|
||||
set(pre -)
|
||||
endif()
|
||||
|
||||
add_link_options ($<$<LINK_LANGUAGE:C>:${pre}BADFLAG_LANG_C${obj}>
|
||||
$<$<LINK_LANGUAGE:CXX>:${pre}BADFLAG_LANG_CXX${obj}>)
|
||||
|
||||
add_library(LinkOptions_shared SHARED LinkOptionsLib.c)
|
||||
|
||||
add_library(LinkOptions_mod MODULE LinkOptionsLib.c)
|
||||
|
||||
add_executable(LinkOptions_exe LinkOptionsExe.c)
|
@ -11,5 +11,8 @@ endif()
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/LINKER.txt" linker_flag)
|
||||
|
||||
if (NOT actual_stdout MATCHES "${linker_flag}")
|
||||
set (RunCMake_TEST_FAILED "LINKER: was not expanded correctly.")
|
||||
if (RunCMake_TEST_FAILED)
|
||||
string (APPEND RunCMake_TEST_FAILED "\n")
|
||||
endif()
|
||||
string (APPEND RunCMake_TEST_FAILED "LINKER: was not expanded correctly.")
|
||||
endif()
|
||||
|
@ -3,5 +3,8 @@ if (NOT actual_stdout MATCHES "BADFLAG_EXECUTABLE_RELEASE")
|
||||
set (RunCMake_TEST_FAILED "Not found expected 'BADFLAG_EXECUTABLE_RELEASE'.")
|
||||
endif()
|
||||
if (actual_stdout MATCHES "BADFLAG_(SHARED|MODULE)_RELEASE")
|
||||
set (RunCMake_TEST_FAILED "Found unexpected 'BADFLAG_(SHARED|MODULE)_RELEASE'.")
|
||||
if (RunCMake_TEST_FAILED)
|
||||
string (APPEND RunCMake_TEST_FAILED "\n")
|
||||
endif()
|
||||
string (APPEND RunCMake_TEST_FAILED "Found unexpected 'BADFLAG_(SHARED|MODULE)_RELEASE'.")
|
||||
endif()
|
||||
|
@ -3,5 +3,8 @@ if (NOT actual_stdout MATCHES "BADFLAG_MODULE_RELEASE")
|
||||
set (RunCMake_TEST_FAILED "Not found expected 'BADFLAG_MODULE_RELEASE'.")
|
||||
endif()
|
||||
if (actual_stdout MATCHES "BADFLAG_(SHARED|EXECUTABLE)_RELEASE")
|
||||
set (RunCMake_TEST_FAILED "Found unexpected 'BADFLAG_(SHARED|EXECUTABLE)_RELEASE'.")
|
||||
if (RunCMake_TEST_FAILED)
|
||||
string (APPEND RunCMake_TEST_FAILED "\n")
|
||||
endif()
|
||||
string (APPEND RunCMake_TEST_FAILED "Found unexpected 'BADFLAG_(SHARED|EXECUTABLE)_RELEASE'.")
|
||||
endif()
|
||||
|
@ -3,5 +3,8 @@ if (NOT actual_stdout MATCHES "BADFLAG_SHARED_RELEASE")
|
||||
set (RunCMake_TEST_FAILED "Not found expected 'BADFLAG_SHARED_RELEASE'.")
|
||||
endif()
|
||||
if (actual_stdout MATCHES "BADFLAG_(MODULE|EXECUTABLE)_RELEASE")
|
||||
set (RunCMake_TEST_FAILED "Found unexpected 'BADFLAG_(MODULE|EXECUTABLE)_RELEASE'.")
|
||||
if (RunCMake_TEST_FAILED)
|
||||
string (APPEND RunCMake_TEST_FAILED "\n")
|
||||
endif()
|
||||
string (APPEND RunCMake_TEST_FAILED "Found unexpected 'BADFLAG_(MODULE|EXECUTABLE)_RELEASE'.")
|
||||
endif()
|
||||
|
7
Tests/RunCMake/add_link_options/LinkOptionsLib.cxx
Normal file
7
Tests/RunCMake/add_link_options/LinkOptionsLib.cxx
Normal file
@ -0,0 +1,7 @@
|
||||
#if defined(_WIN32)
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int flags_lib(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -23,6 +23,21 @@ if (NOT CMAKE_C_COMPILER_ID STREQUAL "Intel")
|
||||
run_cmake_target(LINK_OPTIONS mod LinkOptions_mod --config Release)
|
||||
run_cmake_target(LINK_OPTIONS exe LinkOptions_exe --config Release)
|
||||
|
||||
|
||||
run_cmake(genex_LINK_LANGUAGE)
|
||||
|
||||
run_cmake_target(genex_LINK_LANGUAGE shared_c LinkOptions_shared_c --config Release)
|
||||
run_cmake_target(genex_LINK_LANGUAGE shared_cxx LinkOptions_shared_cxx --config Release)
|
||||
run_cmake_target(genex_LINK_LANGUAGE mod LinkOptions_mod --config Release)
|
||||
run_cmake_target(genex_LINK_LANGUAGE exe LinkOptions_exe --config Release)
|
||||
|
||||
run_cmake(genex_LINK_LANG_AND_ID)
|
||||
|
||||
run_cmake_target(genex_LINK_LANG_AND_ID shared_c LinkOptions_shared_c --config Release)
|
||||
run_cmake_target(genex_LINK_LANG_AND_ID shared_cxx LinkOptions_shared_cxx --config Release)
|
||||
run_cmake_target(genex_LINK_LANG_AND_ID mod LinkOptions_mod --config Release)
|
||||
run_cmake_target(genex_LINK_LANG_AND_ID exe LinkOptions_exe --config Release)
|
||||
|
||||
unset(RunCMake_TEST_OPTIONS)
|
||||
unset(RunCMake_TEST_OUTPUT_MERGE)
|
||||
endif()
|
||||
|
@ -0,0 +1,2 @@
|
||||
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/genex_LINK_LANGUAGE-validation.cmake")
|
@ -0,0 +1 @@
|
||||
.*
|
@ -0,0 +1,2 @@
|
||||
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/genex_LINK_LANGUAGE-validation.cmake")
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user