Add generator expressions for compiler versions.

New generator expressions allow retrieval of the version per language,
as well as equality comparison.
This commit is contained in:
Stephen Kelly 2013-06-11 10:48:47 +02:00
parent d221eac812
commit 47a8db5bcd
4 changed files with 130 additions and 1 deletions

View File

@ -54,6 +54,13 @@
"else '0'.\n" \
" $<VERSION_EQUAL:v1,v2> = '1' if v1 is the same version as v2, " \
"else '0'.\n" \
" $<C_COMPILER_VERSION> = The version of the C compiler used.\n" \
" $<C_COMPILER_VERSION:ver> = '1' if the version of the C " \
"compiler matches ver, otherwise '0'.\n" \
" $<CXX_COMPILER_VERSION> = The version of the CXX compiler " \
"used.\n" \
" $<CXX_COMPILER_VERSION:ver> = '1' if the version of the CXX " \
"compiler matches ver, otherwise '0'.\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_SONAME_FILE:tgt> = file with soname (.so.3)\n" \

View File

@ -341,6 +341,102 @@ static const struct CXXCompilerIdNode : public CompilerIdNode
}
} cxxCompilerIdNode;
//----------------------------------------------------------------------------
struct CompilerVersionNode : public cmGeneratorExpressionNode
{
CompilerVersionNode() {}
virtual int NumExpectedParameters() const { return ZeroOrMoreParameters; }
std::string EvaluateWithLanguage(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context,
const GeneratorExpressionContent *content,
cmGeneratorExpressionDAGChecker *,
const std::string &lang) const
{
const char *compilerVersion = context->Makefile ?
context->Makefile->GetSafeDefinition((
"CMAKE_" + lang + "_COMPILER_VERSION").c_str()) : "";
if (parameters.size() == 0)
{
return compilerVersion ? compilerVersion : "";
}
cmsys::RegularExpression compilerIdValidator;
compilerIdValidator.compile("^[0-9\\.]*$");
if (!compilerIdValidator.find(parameters.begin()->c_str()))
{
reportError(context, content->GetOriginalExpression(),
"Expression syntax not recognized.");
return std::string();
}
if (!compilerVersion)
{
return parameters.front().empty() ? "1" : "0";
}
return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
parameters.begin()->c_str(),
compilerVersion) ? "1" : "0";
}
};
//----------------------------------------------------------------------------
static const struct CCompilerVersionNode : public CompilerVersionNode
{
CCompilerVersionNode() {}
std::string Evaluate(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context,
const GeneratorExpressionContent *content,
cmGeneratorExpressionDAGChecker *dagChecker) const
{
if (parameters.size() != 0 && parameters.size() != 1)
{
reportError(context, content->GetOriginalExpression(),
"$<C_COMPILER_VERSION> expression requires one or two parameters");
return std::string();
}
if (!context->HeadTarget)
{
reportError(context, content->GetOriginalExpression(),
"$<C_COMPILER_VERSION> may only be used with targets. It may not "
"be used with add_custom_command.");
}
return this->EvaluateWithLanguage(parameters, context, content,
dagChecker, "C");
}
} cCompilerVersionNode;
//----------------------------------------------------------------------------
static const struct CxxCompilerVersionNode : public CompilerVersionNode
{
CxxCompilerVersionNode() {}
std::string Evaluate(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context,
const GeneratorExpressionContent *content,
cmGeneratorExpressionDAGChecker *dagChecker) const
{
if (parameters.size() != 0 && parameters.size() != 1)
{
reportError(context, content->GetOriginalExpression(),
"$<CXX_COMPILER_VERSION> expression requires one or two "
"parameters");
return std::string();
}
if (!context->HeadTarget)
{
reportError(context, content->GetOriginalExpression(),
"$<CXX_COMPILER_VERSION> may only be used with targets. It may "
"not be used with add_custom_command.");
}
return this->EvaluateWithLanguage(parameters, context, content,
dagChecker, "CXX");
}
} cxxCompilerVersionNode;
//----------------------------------------------------------------------------
static const struct VersionGreaterNode : public cmGeneratorExpressionNode
{
@ -1247,6 +1343,10 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
return &versionLessNode;
else if (identifier == "VERSION_EQUAL")
return &versionEqualNode;
else if (identifier == "C_COMPILER_VERSION")
return &cCompilerVersionNode;
else if (identifier == "CXX_COMPILER_VERSION")
return &cxxCompilerVersionNode;
else if (identifier == "CONFIGURATION")
return &configurationNode;
else if (identifier == "CONFIG")

View File

@ -5,11 +5,23 @@ project(CompileOptions)
add_library(testlib other.cpp)
add_executable(CompileOptions main.cpp)
macro(get_compiler_test_genex lst lang)
list(APPEND ${lst} -DTEST_${lang}_COMPILER_VERSION="$<${lang}_COMPILER_VERSION>")
list(APPEND ${lst} -DTEST_${lang}_COMPILER_VERSION_EQUALITY=$<${lang}_COMPILER_VERSION:${CMAKE_${lang}_COMPILER_VERSION}>)
endmacro()
get_compiler_test_genex(c_tests C)
get_compiler_test_genex(cxx_tests CXX)
set_property(TARGET CompileOptions PROPERTY COMPILE_OPTIONS
"-DTEST_DEFINE"
"-DNEEDS_ESCAPE=\"E$CAPE\""
"$<$<CXX_COMPILER_ID:GNU>:-DTEST_DEFINE_GNU>"
${c_tests}
${cxx_tests}
)
target_link_libraries(CompileOptions testlib)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
@ -18,3 +30,9 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
"DO_GNU_TESTS"
)
endif()
target_compile_definitions(CompileOptions
PRIVATE
"EXPECTED_C_COMPILER_VERSION=\"${CMAKE_C_COMPILER_VERSION}\""
"EXPECTED_CXX_COMPILER_VERSION=\"${CMAKE_CXX_COMPILER_VERSION}\""
)

View File

@ -16,5 +16,9 @@
int main()
{
return strcmp(NEEDS_ESCAPE, "E$CAPE") == 0 ? 0 : 1;
return (strcmp(NEEDS_ESCAPE, "E$CAPE") == 0
&& strcmp(EXPECTED_C_COMPILER_VERSION, TEST_C_COMPILER_VERSION) == 0
&& strcmp(EXPECTED_CXX_COMPILER_VERSION, TEST_CXX_COMPILER_VERSION) == 0
&& TEST_C_COMPILER_VERSION_EQUALITY == 1
&& TEST_CXX_COMPILER_VERSION_EQUALITY == 1) ? 0 : 1;
}