mirror of
https://github.com/reactos/CMake.git
synced 2024-12-01 07:20:22 +00:00
Add $<LINK_LANGUAGE> generator expression
They can't be used when evaluating link libraries, but they can be used for include directories and compile definitions. Later they can be used for compile options.
This commit is contained in:
parent
a7ba4520c7
commit
32410140a7
@ -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.");
|
||||||
|
@ -277,6 +277,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
|
||||||
@ -605,7 +606,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,
|
||||||
@ -802,7 +804,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,
|
||||||
@ -813,7 +816,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
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
Tests/CompileDefinitions/compiletest.c
Normal file
19
Tests/CompileDefinitions/compiletest.c
Normal file
@ -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
|
||||||
|
|
||||||
|
19
Tests/CompileDefinitions/compiletest_mixed_c.c
Normal file
19
Tests/CompileDefinitions/compiletest_mixed_c.c
Normal file
@ -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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
19
Tests/CompileDefinitions/compiletest_mixed_cxx.cpp
Normal file
19
Tests/CompileDefinitions/compiletest_mixed_cxx.cpp
Normal file
@ -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/>"
|
||||||
|
)
|
||||||
|
7
Tests/IncludeDirectories/TargetIncludeDirectories/main.c
Normal file
7
Tests/IncludeDirectories/TargetIncludeDirectories/main.c
Normal file
@ -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
Block a user