GenEx: Add expressions to specify build- or install-only values
This is for specifying INCLUDE_DIRECTORIES relevant to the build-location or the install location for example: set_property(TARGET foo PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}>" "$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include>" ) A 'bar' target can then use: set_property(TARGET bar PROPERTY INCLUDE_DIRECTORIES "$<TARGET_PROPERTY:foo,INTERFACE_INCLUDE_DIRECTORIES>" ) and it will work whether foo is in the same project, or an imported target from an installation location, or an imported target from a build location generated by the export() command. Because the generator expressions are only evaluated at build-time, these new expressions are equivalent to the ZeroNode and OneNode. The GeneratorExpression test is split into parts. Some shells can't run the custom command as it is getting too long.
This commit is contained in:
parent
95b74cafed
commit
b2f1700bc7
|
@ -26,6 +26,12 @@
|
||||||
"strings which contain a '>' for example.\n" \
|
"strings which contain a '>' for example.\n" \
|
||||||
" $<COMMA> = A literal ','. Used to compare " \
|
" $<COMMA> = A literal ','. Used to compare " \
|
||||||
"strings which contain a ',' for example.\n" \
|
"strings which contain a ',' for example.\n" \
|
||||||
|
" $<INSTALL_INTERFACE:...> = content of \"...\" when the property " \
|
||||||
|
"is exported using install(EXPORT), and empty otherwise.\n" \
|
||||||
|
" $<BUILD_INTERFACE:...> = content of \"...\" when the property " \
|
||||||
|
"is exported using export(), or when the target is used by another " \
|
||||||
|
"target in the same buildsystem. Expands to the empty string " \
|
||||||
|
"otherwise.\n" \
|
||||||
" $<TARGET_FILE:tgt> = main file (.exe, .so.1.2, .a)\n" \
|
" $<TARGET_FILE:tgt> = main file (.exe, .so.1.2, .a)\n" \
|
||||||
" $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n" \
|
" $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n" \
|
||||||
" $<TARGET_SONAME_FILE:tgt> = file with soname (.so.3)\n" \
|
" $<TARGET_SONAME_FILE:tgt> = file with soname (.so.3)\n" \
|
||||||
|
|
|
@ -123,15 +123,9 @@ cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string cmGeneratorExpression::Preprocess(const std::string &input,
|
//----------------------------------------------------------------------------
|
||||||
PreprocessContext context)
|
static std::string stripAllGeneratorExpressions(const std::string &input)
|
||||||
{
|
{
|
||||||
if (context != StripAllGeneratorExpressions)
|
|
||||||
{
|
|
||||||
assert(!"cmGeneratorExpression::Preprocess called with invalid args");
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string result;
|
std::string result;
|
||||||
std::string::size_type pos = 0;
|
std::string::size_type pos = 0;
|
||||||
std::string::size_type lastPos = pos;
|
std::string::size_type lastPos = pos;
|
||||||
|
@ -170,3 +164,81 @@ std::string cmGeneratorExpression::Preprocess(const std::string &input,
|
||||||
result += input.substr(lastPos);
|
result += input.substr(lastPos);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
static std::string stripExportInterface(const std::string &input,
|
||||||
|
cmGeneratorExpression::PreprocessContext context)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
std::string::size_type pos = 0;
|
||||||
|
std::string::size_type lastPos = pos;
|
||||||
|
while((pos = input.find("$<BUILD_INTERFACE:", lastPos)) != input.npos
|
||||||
|
|| (pos = input.find("$<INSTALL_INTERFACE:", lastPos)) != input.npos)
|
||||||
|
{
|
||||||
|
result += input.substr(lastPos, pos - lastPos);
|
||||||
|
const bool gotInstallInterface = input[pos + 2] == 'I';
|
||||||
|
pos += gotInstallInterface ? sizeof("$<INSTALL_INTERFACE:") - 1
|
||||||
|
: sizeof("$<BUILD_INTERFACE:") - 1;
|
||||||
|
int nestingLevel = 1;
|
||||||
|
const char *c = input.c_str() + pos;
|
||||||
|
const char * const cStart = c;
|
||||||
|
for ( ; *c; ++c)
|
||||||
|
{
|
||||||
|
if(c[0] == '$' && c[1] == '<')
|
||||||
|
{
|
||||||
|
++nestingLevel;
|
||||||
|
++c;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(c[0] == '>')
|
||||||
|
{
|
||||||
|
--nestingLevel;
|
||||||
|
if (nestingLevel != 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(context == cmGeneratorExpression::BuildInterface
|
||||||
|
&& !gotInstallInterface)
|
||||||
|
{
|
||||||
|
result += input.substr(pos, c - cStart);
|
||||||
|
}
|
||||||
|
else if(context == cmGeneratorExpression::InstallInterface
|
||||||
|
&& gotInstallInterface)
|
||||||
|
{
|
||||||
|
result += input.substr(pos, c - cStart);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const std::string::size_type traversed = (c - cStart) + 1;
|
||||||
|
if (!*c)
|
||||||
|
{
|
||||||
|
result += std::string(gotInstallInterface ? "$<INSTALL_INTERFACE:"
|
||||||
|
: "$<BUILD_INTERFACE:")
|
||||||
|
+ input.substr(pos, traversed);
|
||||||
|
}
|
||||||
|
pos += traversed;
|
||||||
|
lastPos = pos;
|
||||||
|
}
|
||||||
|
result += input.substr(lastPos);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
std::string cmGeneratorExpression::Preprocess(const std::string &input,
|
||||||
|
PreprocessContext context)
|
||||||
|
{
|
||||||
|
if (context == StripAllGeneratorExpressions)
|
||||||
|
{
|
||||||
|
return stripAllGeneratorExpressions(input);
|
||||||
|
}
|
||||||
|
else if (context == BuildInterface || context == InstallInterface)
|
||||||
|
{
|
||||||
|
return stripExportInterface(input, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(!"cmGeneratorExpression::Preprocess called with invalid args");
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
|
@ -51,7 +51,9 @@ public:
|
||||||
cmsys::auto_ptr<cmCompiledGeneratorExpression> Parse(const char* input);
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> Parse(const char* input);
|
||||||
|
|
||||||
enum PreprocessContext {
|
enum PreprocessContext {
|
||||||
StripAllGeneratorExpressions
|
StripAllGeneratorExpressions,
|
||||||
|
BuildInterface,
|
||||||
|
InstallInterface
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::string Preprocess(const std::string &input,
|
static std::string Preprocess(const std::string &input,
|
||||||
|
|
|
@ -95,6 +95,12 @@ static const struct OneNode : public cmGeneratorExpressionNode
|
||||||
}
|
}
|
||||||
} oneNode;
|
} oneNode;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
static const struct OneNode buildInterfaceNode;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
static const struct ZeroNode installInterfaceNode;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
#define BOOLEAN_OP_NODE(OPNAME, OP, SUCCESS_VALUE, FAILURE_VALUE) \
|
#define BOOLEAN_OP_NODE(OPNAME, OP, SUCCESS_VALUE, FAILURE_VALUE) \
|
||||||
static const struct OP ## Node : public cmGeneratorExpressionNode \
|
static const struct OP ## Node : public cmGeneratorExpressionNode \
|
||||||
|
@ -593,6 +599,10 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
|
||||||
return &commaNode;
|
return &commaNode;
|
||||||
else if (identifier == "TARGET_PROPERTY")
|
else if (identifier == "TARGET_PROPERTY")
|
||||||
return &targetPropertyNode;
|
return &targetPropertyNode;
|
||||||
|
else if (identifier == "BUILD_INTERFACE")
|
||||||
|
return &buildInterfaceNode;
|
||||||
|
else if (identifier == "INSTALL_INTERFACE")
|
||||||
|
return &installInterfaceNode;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
cmake_minimum_required (VERSION 2.8.8)
|
cmake_minimum_required (VERSION 2.8.8)
|
||||||
project(GeneratorExpression NONE)
|
project(GeneratorExpression NONE)
|
||||||
|
|
||||||
add_custom_target(check ALL
|
add_custom_target(check-part1 ALL
|
||||||
COMMAND ${CMAKE_COMMAND}
|
COMMAND ${CMAKE_COMMAND}
|
||||||
-Dtest_0=$<0:nothing>
|
-Dtest_0=$<0:nothing>
|
||||||
-Dtest_0_with_comma=$<0:-Wl,--no-undefined>
|
-Dtest_0_with_comma=$<0:-Wl,--no-undefined>
|
||||||
|
@ -57,6 +57,13 @@ add_custom_target(check ALL
|
||||||
-Dtest_colons_3=$<1:Qt5::Core>
|
-Dtest_colons_3=$<1:Qt5::Core>
|
||||||
-Dtest_colons_4=$<1:C:\\CMake>
|
-Dtest_colons_4=$<1:C:\\CMake>
|
||||||
-Dtest_colons_5=$<1:C:/CMake>
|
-Dtest_colons_5=$<1:C:/CMake>
|
||||||
|
-P ${CMAKE_CURRENT_SOURCE_DIR}/check-part1.cmake
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo "check done (part 1 of 2)"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(check-part2 ALL
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
-Dtest_incomplete_1=$<
|
-Dtest_incomplete_1=$<
|
||||||
-Dtest_incomplete_2=$<something
|
-Dtest_incomplete_2=$<something
|
||||||
-Dtest_incomplete_3=$<something:
|
-Dtest_incomplete_3=$<something:
|
||||||
|
@ -78,7 +85,9 @@ add_custom_target(check ALL
|
||||||
-Dtest_incomplete_19=$<1:some,thing$<ANGLE-R>
|
-Dtest_incomplete_19=$<1:some,thing$<ANGLE-R>
|
||||||
-Dtest_incomplete_20=$<CONFIGURATION$<ANGLE-R>
|
-Dtest_incomplete_20=$<CONFIGURATION$<ANGLE-R>
|
||||||
-Dtest_incomplete_21=$<BOOL:something$<ANGLE-R>
|
-Dtest_incomplete_21=$<BOOL:something$<ANGLE-R>
|
||||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake
|
-Dtest_build_interface=$<BUILD_INTERFACE:build>
|
||||||
COMMAND ${CMAKE_COMMAND} -E echo "check done"
|
-Dtest_install_interface=$<INSTALL_INTERFACE:install>
|
||||||
|
-P ${CMAKE_CURRENT_SOURCE_DIR}/check-part2.cmake
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo "check done (part 2 of 2)"
|
||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
macro(check var val)
|
||||||
|
if(NOT "${${var}}" STREQUAL "${val}")
|
||||||
|
message(SEND_ERROR "${var} is \"${${var}}\", not \"${val}\"")
|
||||||
|
endif()
|
||||||
|
endmacro()
|
|
@ -1,8 +1,5 @@
|
||||||
macro(check var val)
|
|
||||||
if(NOT "${${var}}" STREQUAL "${val}")
|
include(${CMAKE_CURRENT_LIST_DIR}/check-common.cmake)
|
||||||
message(SEND_ERROR "${var} is \"${${var}}\", not \"${val}\"")
|
|
||||||
endif()
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
message(STATUS "config=[${config}]")
|
message(STATUS "config=[${config}]")
|
||||||
check(test_0 "")
|
check(test_0 "")
|
||||||
|
@ -57,24 +54,3 @@ check(test_colons_2 "::")
|
||||||
check(test_colons_3 "Qt5::Core")
|
check(test_colons_3 "Qt5::Core")
|
||||||
check(test_colons_4 "C:\\\\CMake")
|
check(test_colons_4 "C:\\\\CMake")
|
||||||
check(test_colons_5 "C:/CMake")
|
check(test_colons_5 "C:/CMake")
|
||||||
check(test_incomplete_1 "$<")
|
|
||||||
check(test_incomplete_2 "$<something")
|
|
||||||
check(test_incomplete_3 "$<something:")
|
|
||||||
check(test_incomplete_4 "$<something:,")
|
|
||||||
check(test_incomplete_5 "$something:,>")
|
|
||||||
check(test_incomplete_6 "<something:,>")
|
|
||||||
check(test_incomplete_7 "$<something::")
|
|
||||||
check(test_incomplete_8 "$<something:,")
|
|
||||||
check(test_incomplete_9 "$<something:,,")
|
|
||||||
check(test_incomplete_10 "$<something:,:")
|
|
||||||
check(test_incomplete_11 "$<something,,")
|
|
||||||
check(test_incomplete_12 "$<,,")
|
|
||||||
check(test_incomplete_13 "$<somespecialthing")
|
|
||||||
check(test_incomplete_14 "$<>")
|
|
||||||
check(test_incomplete_15 "$<some$<thing")
|
|
||||||
check(test_incomplete_16 "$<BOOL:something")
|
|
||||||
check(test_incomplete_17 "some$thing")
|
|
||||||
check(test_incomplete_18 "$<1:some,thing")
|
|
||||||
check(test_incomplete_19 "$<1:some,thing>")
|
|
||||||
check(test_incomplete_20 "$<CONFIGURATION>")
|
|
||||||
check(test_incomplete_21 "$<BOOL:something>")
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/check-common.cmake)
|
||||||
|
|
||||||
|
check(test_incomplete_1 "$<")
|
||||||
|
check(test_incomplete_2 "$<something")
|
||||||
|
check(test_incomplete_3 "$<something:")
|
||||||
|
check(test_incomplete_4 "$<something:,")
|
||||||
|
check(test_incomplete_5 "$something:,>")
|
||||||
|
check(test_incomplete_6 "<something:,>")
|
||||||
|
check(test_incomplete_7 "$<something::")
|
||||||
|
check(test_incomplete_8 "$<something:,")
|
||||||
|
check(test_incomplete_9 "$<something:,,")
|
||||||
|
check(test_incomplete_10 "$<something:,:")
|
||||||
|
check(test_incomplete_11 "$<something,,")
|
||||||
|
check(test_incomplete_12 "$<,,")
|
||||||
|
check(test_incomplete_13 "$<somespecialthing")
|
||||||
|
check(test_incomplete_14 "$<>")
|
||||||
|
check(test_incomplete_15 "$<some$<thing")
|
||||||
|
check(test_incomplete_16 "$<BOOL:something")
|
||||||
|
check(test_incomplete_17 "some$thing")
|
||||||
|
check(test_incomplete_18 "$<1:some,thing")
|
||||||
|
check(test_incomplete_19 "$<1:some,thing>")
|
||||||
|
check(test_incomplete_20 "$<CONFIGURATION>")
|
||||||
|
check(test_incomplete_21 "$<BOOL:something>")
|
||||||
|
check(test_build_interface "build")
|
||||||
|
check(test_install_interface "")
|
Loading…
Reference in New Issue