Merge topic 'language-generator-expressions'
3241014
Add $<LINK_LANGUAGE> generator expression
This commit is contained in:
commit
14d90d81de
|
@ -74,4 +74,12 @@
|
||||||
"the target on which the generator expression is evaluated.\n" \
|
"the target on which the generator expression is evaluated.\n" \
|
||||||
""
|
""
|
||||||
|
|
||||||
|
#define CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS \
|
||||||
|
"Language related expressions:\n" \
|
||||||
|
" $<LINK_LANGUAGE> = The link language of the target " \
|
||||||
|
"being generated.\n" \
|
||||||
|
" $<LINK_LANGUAGE:lang> = '1' if the link language of the " \
|
||||||
|
"target being generated matches lang, else '0'.\n" \
|
||||||
|
""
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -45,6 +45,11 @@ void reportError(cmGeneratorExpressionContext *context,
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
struct cmGeneratorExpressionNode
|
struct cmGeneratorExpressionNode
|
||||||
{
|
{
|
||||||
|
enum {
|
||||||
|
DynamicParameters = 0,
|
||||||
|
OneOrMoreParameters = -1,
|
||||||
|
ZeroOrMoreParameters = -2
|
||||||
|
};
|
||||||
virtual ~cmGeneratorExpressionNode() {}
|
virtual ~cmGeneratorExpressionNode() {}
|
||||||
|
|
||||||
virtual bool GeneratesContent() const { return true; }
|
virtual bool GeneratesContent() const { return true; }
|
||||||
|
@ -110,8 +115,7 @@ static const struct ZeroNode installInterfaceNode;
|
||||||
static const struct OP ## Node : public cmGeneratorExpressionNode \
|
static const struct OP ## Node : public cmGeneratorExpressionNode \
|
||||||
{ \
|
{ \
|
||||||
OP ## Node () {} \
|
OP ## Node () {} \
|
||||||
/* We let -1 carry the meaning 'at least one' */ \
|
virtual int NumExpectedParameters() const { return OneOrMoreParameters; } \
|
||||||
virtual int NumExpectedParameters() const { return -1; } \
|
|
||||||
\
|
\
|
||||||
std::string Evaluate(const std::vector<std::string> ¶meters, \
|
std::string Evaluate(const std::vector<std::string> ¶meters, \
|
||||||
cmGeneratorExpressionContext *context, \
|
cmGeneratorExpressionContext *context, \
|
||||||
|
@ -306,6 +310,60 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
|
||||||
}
|
}
|
||||||
} configurationTestNode;
|
} configurationTestNode;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
static const struct LinkLanguageNode : public cmGeneratorExpressionNode
|
||||||
|
{
|
||||||
|
LinkLanguageNode() {}
|
||||||
|
|
||||||
|
virtual int NumExpectedParameters() const { return ZeroOrMoreParameters; }
|
||||||
|
|
||||||
|
std::string Evaluate(const std::vector<std::string> ¶meters,
|
||||||
|
cmGeneratorExpressionContext *context,
|
||||||
|
const GeneratorExpressionContent *content,
|
||||||
|
cmGeneratorExpressionDAGChecker *) const
|
||||||
|
{
|
||||||
|
if (parameters.size() != 0 && parameters.size() != 1)
|
||||||
|
{
|
||||||
|
reportError(context, content->GetOriginalExpression(),
|
||||||
|
"$<LINK_LANGUAGE> expression requires one or two parameters");
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
cmTarget* target = context->HeadTarget;
|
||||||
|
if (!target)
|
||||||
|
{
|
||||||
|
reportError(context, content->GetOriginalExpression(),
|
||||||
|
"$<LINK_LANGUAGE> may only be used with targets. It may not "
|
||||||
|
"be used with add_custom_command.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *lang = target->GetLinkerLanguage(context->Config);
|
||||||
|
if (parameters.size() == 0)
|
||||||
|
{
|
||||||
|
return lang ? lang : "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmsys::RegularExpression langValidator;
|
||||||
|
langValidator.compile("^[A-Za-z0-9_]*$");
|
||||||
|
if (!langValidator.find(parameters.begin()->c_str()))
|
||||||
|
{
|
||||||
|
reportError(context, content->GetOriginalExpression(),
|
||||||
|
"Expression syntax not recognized.");
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
if (!lang)
|
||||||
|
{
|
||||||
|
return parameters.front().empty() ? "1" : "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(parameters.begin()->c_str(), lang) == 0)
|
||||||
|
{
|
||||||
|
return "1";
|
||||||
|
}
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} linkLanguageNode;
|
||||||
|
|
||||||
static const struct JoinNode : public cmGeneratorExpressionNode
|
static const struct JoinNode : public cmGeneratorExpressionNode
|
||||||
{
|
{
|
||||||
|
@ -347,7 +405,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
||||||
TargetPropertyNode() {}
|
TargetPropertyNode() {}
|
||||||
|
|
||||||
// This node handles errors on parameter count itself.
|
// This node handles errors on parameter count itself.
|
||||||
virtual int NumExpectedParameters() const { return -1; }
|
virtual int NumExpectedParameters() const { return OneOrMoreParameters; }
|
||||||
|
|
||||||
std::string Evaluate(const std::vector<std::string> ¶meters,
|
std::string Evaluate(const std::vector<std::string> ¶meters,
|
||||||
cmGeneratorExpressionContext *context,
|
cmGeneratorExpressionContext *context,
|
||||||
|
@ -961,6 +1019,8 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
|
||||||
return &configurationNode;
|
return &configurationNode;
|
||||||
else if (identifier == "CONFIG")
|
else if (identifier == "CONFIG")
|
||||||
return &configurationTestNode;
|
return &configurationTestNode;
|
||||||
|
else if (identifier == "LINK_LANGUAGE")
|
||||||
|
return &linkLanguageNode;
|
||||||
else if (identifier == "TARGET_FILE")
|
else if (identifier == "TARGET_FILE")
|
||||||
return &targetFileNode;
|
return &targetFileNode;
|
||||||
else if (identifier == "TARGET_LINKER_FILE")
|
else if (identifier == "TARGET_LINKER_FILE")
|
||||||
|
@ -1188,7 +1248,8 @@ std::string GeneratorExpressionContent::EvaluateParameters(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((numExpected != -1 && (unsigned int)numExpected != parameters.size()))
|
if ((numExpected > cmGeneratorExpressionNode::DynamicParameters
|
||||||
|
&& (unsigned int)numExpected != parameters.size()))
|
||||||
{
|
{
|
||||||
if (numExpected == 0)
|
if (numExpected == 0)
|
||||||
{
|
{
|
||||||
|
@ -1213,7 +1274,8 @@ std::string GeneratorExpressionContent::EvaluateParameters(
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numExpected == -1 && parameters.empty())
|
if (numExpected == cmGeneratorExpressionNode::OneOrMoreParameters
|
||||||
|
&& parameters.empty())
|
||||||
{
|
{
|
||||||
reportError(context, this->GetOriginalExpression(), "$<" + identifier
|
reportError(context, this->GetOriginalExpression(), "$<" + identifier
|
||||||
+ "> expression requires at least one parameter.");
|
+ "> expression requires at least one parameter.");
|
||||||
|
|
|
@ -278,6 +278,7 @@ void cmTarget::DefineProperties(cmake *cm)
|
||||||
"Contents of COMPILE_DEFINITIONS may use \"generator expressions\" with "
|
"Contents of COMPILE_DEFINITIONS may use \"generator expressions\" with "
|
||||||
"the syntax \"$<...>\". "
|
"the syntax \"$<...>\". "
|
||||||
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
|
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
|
||||||
|
CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS
|
||||||
CM_DOCUMENT_COMPILE_DEFINITIONS_DISCLAIMER);
|
CM_DOCUMENT_COMPILE_DEFINITIONS_DISCLAIMER);
|
||||||
|
|
||||||
cm->DefineProperty
|
cm->DefineProperty
|
||||||
|
@ -606,7 +607,8 @@ void cmTarget::DefineProperties(cmake *cm)
|
||||||
"See also the include_directories command.\n"
|
"See also the include_directories command.\n"
|
||||||
"Contents of INCLUDE_DIRECTORIES may use \"generator expressions\" with "
|
"Contents of INCLUDE_DIRECTORIES may use \"generator expressions\" with "
|
||||||
"the syntax \"$<...>\". "
|
"the syntax \"$<...>\". "
|
||||||
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
|
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
|
||||||
|
CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS);
|
||||||
|
|
||||||
cm->DefineProperty
|
cm->DefineProperty
|
||||||
("INSTALL_NAME_DIR", cmProperty::TARGET,
|
("INSTALL_NAME_DIR", cmProperty::TARGET,
|
||||||
|
@ -803,7 +805,8 @@ void cmTarget::DefineProperties(cmake *cm)
|
||||||
"as $<TARGET_PROPERTY:foo,INTERFACE_INCLUDE_DIRECTORIES> to use the "
|
"as $<TARGET_PROPERTY:foo,INTERFACE_INCLUDE_DIRECTORIES> to use the "
|
||||||
"include directories specified in the interface of 'foo'."
|
"include directories specified in the interface of 'foo'."
|
||||||
"\n"
|
"\n"
|
||||||
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
|
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
|
||||||
|
CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS);
|
||||||
|
|
||||||
cm->DefineProperty
|
cm->DefineProperty
|
||||||
("INTERFACE_COMPILE_DEFINITIONS", cmProperty::TARGET,
|
("INTERFACE_COMPILE_DEFINITIONS", cmProperty::TARGET,
|
||||||
|
@ -814,7 +817,8 @@ void cmTarget::DefineProperties(cmake *cm)
|
||||||
"as $<TARGET_PROPERTY:foo,INTERFACE_COMPILE_DEFINITIONS> to use the "
|
"as $<TARGET_PROPERTY:foo,INTERFACE_COMPILE_DEFINITIONS> to use the "
|
||||||
"compile definitions specified in the interface of 'foo'."
|
"compile definitions specified in the interface of 'foo'."
|
||||||
"\n"
|
"\n"
|
||||||
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
|
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
|
||||||
|
CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS);
|
||||||
|
|
||||||
cm->DefineProperty
|
cm->DefineProperty
|
||||||
("LINK_INTERFACE_MULTIPLICITY", cmProperty::TARGET,
|
("LINK_INTERFACE_MULTIPLICITY", cmProperty::TARGET,
|
||||||
|
|
|
@ -70,6 +70,7 @@ public:
|
||||||
"Arguments to target_compile_definitions may use \"generator "
|
"Arguments to target_compile_definitions may use \"generator "
|
||||||
"expressions\" with the syntax \"$<...>\". "
|
"expressions\" with the syntax \"$<...>\". "
|
||||||
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
|
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
|
||||||
|
CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,7 @@ public:
|
||||||
"Arguments to target_include_directories may use \"generator "
|
"Arguments to target_include_directories may use \"generator "
|
||||||
"expressions\" with the syntax \"$<...>\". "
|
"expressions\" with the syntax \"$<...>\". "
|
||||||
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
|
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
|
||||||
|
CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
#ifndef LINK_C_DEFINE
|
||||||
|
#error Expected LINK_C_DEFINE
|
||||||
|
#endif
|
||||||
|
#ifndef LINK_LANGUAGE_IS_C
|
||||||
|
#error Expected LINK_LANGUAGE_IS_C
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LINK_CXX_DEFINE
|
||||||
|
#error Unexpected LINK_CXX_DEFINE
|
||||||
|
#endif
|
||||||
|
#ifdef LINK_LANGUAGE_IS_CXX
|
||||||
|
#error Unexpected LINK_LANGUAGE_IS_CXX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -56,6 +56,21 @@ enum {
|
||||||
#error Expect PREFIX_DEF2
|
#error Expect PREFIX_DEF2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef LINK_CXX_DEFINE
|
||||||
|
#error Expected LINK_CXX_DEFINE
|
||||||
|
#endif
|
||||||
|
#ifndef LINK_LANGUAGE_IS_CXX
|
||||||
|
#error Expected LINK_LANGUAGE_IS_CXX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LINK_C_DEFINE
|
||||||
|
#error Unexpected LINK_C_DEFINE
|
||||||
|
#endif
|
||||||
|
#ifdef LINK_LANGUAGE_IS_C
|
||||||
|
#error Unexpected LINK_LANGUAGE_IS_C
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// TEST_GENERATOR_EXPRESSIONS
|
// TEST_GENERATOR_EXPRESSIONS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
#ifndef LINK_CXX_DEFINE
|
||||||
|
#error Expected LINK_CXX_DEFINE
|
||||||
|
#endif
|
||||||
|
#ifndef LINK_LANGUAGE_IS_CXX
|
||||||
|
#error Expected LINK_LANGUAGE_IS_CXX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LINK_C_DEFINE
|
||||||
|
#error Unexpected LINK_C_DEFINE
|
||||||
|
#endif
|
||||||
|
#ifdef LINK_LANGUAGE_IS_C
|
||||||
|
#error Unexpected LINK_LANGUAGE_IS_C
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void someFunc(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
#ifndef LINK_CXX_DEFINE
|
||||||
|
#error Expected LINK_CXX_DEFINE
|
||||||
|
#endif
|
||||||
|
#ifndef LINK_LANGUAGE_IS_CXX
|
||||||
|
#error Expected LINK_LANGUAGE_IS_CXX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LINK_C_DEFINE
|
||||||
|
#error Unexpected LINK_C_DEFINE
|
||||||
|
#endif
|
||||||
|
#ifdef LINK_LANGUAGE_IS_C
|
||||||
|
#error Unexpected LINK_LANGUAGE_IS_C
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -19,9 +19,29 @@ set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS
|
||||||
LETTER_LIST3=\"$<JOIN:A;B;C;D,,->\"
|
LETTER_LIST3=\"$<JOIN:A;B;C;D,,->\"
|
||||||
LETTER_LIST4=\"$<JOIN:A;B;C;D,-,->\"
|
LETTER_LIST4=\"$<JOIN:A;B;C;D,-,->\"
|
||||||
LETTER_LIST5=\"$<JOIN:A;B;C;D,-,>\"
|
LETTER_LIST5=\"$<JOIN:A;B;C;D,-,>\"
|
||||||
|
"$<$<LINK_LANGUAGE:CXX>:LINK_CXX_DEFINE>"
|
||||||
|
"$<$<LINK_LANGUAGE:C>:LINK_C_DEFINE>"
|
||||||
|
"LINK_LANGUAGE_IS_$<LINK_LANGUAGE>"
|
||||||
)
|
)
|
||||||
|
|
||||||
set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS
|
set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS
|
||||||
BUILD_IS_DEBUG=$<CONFIG:Debug>
|
BUILD_IS_DEBUG=$<CONFIG:Debug>
|
||||||
BUILD_IS_NOT_DEBUG=$<NOT:$<CONFIG:Debug>>
|
BUILD_IS_NOT_DEBUG=$<NOT:$<CONFIG:Debug>>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_executable(target_prop_c_executable ../compiletest.c)
|
||||||
|
|
||||||
|
set_property(TARGET target_prop_c_executable APPEND PROPERTY COMPILE_DEFINITIONS
|
||||||
|
"$<$<LINK_LANGUAGE:CXX>:LINK_CXX_DEFINE>"
|
||||||
|
"$<$<LINK_LANGUAGE:C>:LINK_C_DEFINE>"
|
||||||
|
"LINK_LANGUAGE_IS_$<LINK_LANGUAGE>"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Resulting link language will be CXX
|
||||||
|
add_executable(target_prop_mixed_executable ../compiletest_mixed_c.c ../compiletest_mixed_cxx.cpp)
|
||||||
|
|
||||||
|
set_property(TARGET target_prop_mixed_executable APPEND PROPERTY COMPILE_DEFINITIONS
|
||||||
|
"$<$<LINK_LANGUAGE:CXX>:LINK_CXX_DEFINE>"
|
||||||
|
"$<$<LINK_LANGUAGE:C>:LINK_C_DEFINE>"
|
||||||
|
"LINK_LANGUAGE_IS_$<LINK_LANGUAGE>"
|
||||||
|
)
|
||||||
|
|
|
@ -128,3 +128,19 @@ file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/prefix_foo/prefix_bar/prefix_ba
|
||||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/prefix_foo/prefix_bar/prefix_bat/prefix_foo_bar_bat.h" "// prefix_foo_bar_bat.h\n")
|
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/prefix_foo/prefix_bar/prefix_bat/prefix_foo_bar_bat.h" "// prefix_foo_bar_bat.h\n")
|
||||||
|
|
||||||
target_include_directories(TargetIncludeDirectories PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/prefix_$<JOIN:foo;bar;bat,/prefix_>")
|
target_include_directories(TargetIncludeDirectories PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/prefix_$<JOIN:foo;bar;bat,/prefix_>")
|
||||||
|
|
||||||
|
# Test that the language generator expressions work
|
||||||
|
set_property(TARGET TargetIncludeDirectories
|
||||||
|
APPEND PROPERTY INCLUDE_DIRECTORIES
|
||||||
|
"$<$<LINK_LANGUAGE:C>:${CMAKE_CURRENT_BINARY_DIR}/bad>"
|
||||||
|
"$<$<LINK_LANGUAGE:CXX>:${CMAKE_CURRENT_BINARY_DIR}/good>"
|
||||||
|
"$<$<STREQUAL:$<LINK_LANGUAGE>,CXX>:${CMAKE_CURRENT_BINARY_DIR}/othergood/>"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(TargetIncludeDirectories_C main.c)
|
||||||
|
set_property(TARGET TargetIncludeDirectories_C
|
||||||
|
APPEND PROPERTY INCLUDE_DIRECTORIES
|
||||||
|
"$<$<LINK_LANGUAGE:CXX>:${CMAKE_CURRENT_BINARY_DIR}/bad>"
|
||||||
|
"$<$<LINK_LANGUAGE:C>:${CMAKE_CURRENT_BINARY_DIR}/good>"
|
||||||
|
"$<$<STREQUAL:$<LINK_LANGUAGE>,C>:${CMAKE_CURRENT_BINARY_DIR}/othergood/>"
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -11,6 +11,7 @@
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "prefix_foo_bar_bat.h"
|
#include "prefix_foo_bar_bat.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
int main(int, char**)
|
int main(int, char**)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue