Genex: Enable use of COMPILE_LANGUAGE for compile options.
Follow-ups will allow the use of the generator expression for compile definitions and include directories for non-IDE generators.
This commit is contained in:
parent
e387ce7d68
commit
5c559f1113
|
@ -93,6 +93,32 @@ Available logical expressions are:
|
||||||
for the 'head' target, an error is reported. See the
|
for the 'head' target, an error is reported. See the
|
||||||
:manual:`cmake-compile-features(7)` manual for information on
|
:manual:`cmake-compile-features(7)` manual for information on
|
||||||
compile features.
|
compile features.
|
||||||
|
``$<COMPILE_LANGUAGE:lang>``
|
||||||
|
``1`` when the language used for compilation unit matches ``lang``,
|
||||||
|
otherwise ``0``. This expression used to specify compile options for
|
||||||
|
source files of a particular language in a target. For example, to specify
|
||||||
|
the use of the ``-fno-exceptions`` compile option (compiler id checks
|
||||||
|
elided):
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
add_executable(myapp main.cpp foo.c bar.cpp)
|
||||||
|
target_compile_options(myapp
|
||||||
|
PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>
|
||||||
|
)
|
||||||
|
|
||||||
|
This generator expression has limited use because it is not possible to
|
||||||
|
use it with the Visual Studio generators. Portable buildsystems would
|
||||||
|
not use this expression, and would create separate libraries for each
|
||||||
|
source file language instead:
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
add_library(myapp_c foo.c)
|
||||||
|
add_library(myapp_cxx foo.c)
|
||||||
|
target_compile_options(myapp_cxx PUBLIC -fno-exceptions)
|
||||||
|
add_executable(myapp main.cpp)
|
||||||
|
target_link_libraries(myapp myapp_c myapp_cxx)
|
||||||
|
|
||||||
Informational Expressions
|
Informational Expressions
|
||||||
=========================
|
=========================
|
||||||
|
@ -174,6 +200,10 @@ Available informational expressions are:
|
||||||
``$<INSTALL_PREFIX>``
|
``$<INSTALL_PREFIX>``
|
||||||
Content of the install prefix when the target is exported via
|
Content of the install prefix when the target is exported via
|
||||||
:command:`install(EXPORT)` and empty otherwise.
|
:command:`install(EXPORT)` and empty otherwise.
|
||||||
|
``$<COMPILE_LANGUAGE>``
|
||||||
|
The compile language of source files when evaluating compile options. See
|
||||||
|
the unary version for notes about portability of this generator
|
||||||
|
expression.
|
||||||
|
|
||||||
Output Expressions
|
Output Expressions
|
||||||
==================
|
==================
|
||||||
|
|
|
@ -827,6 +827,40 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode
|
||||||
"components of the file(GENERATE) command.");
|
"components of the file(GENERATE) command.");
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> enabledLanguages;
|
||||||
|
cmGlobalGenerator* gg
|
||||||
|
= context->Makefile->GetLocalGenerator()->GetGlobalGenerator();
|
||||||
|
gg->GetEnabledLanguages(enabledLanguages);
|
||||||
|
if (!parameters.empty() &&
|
||||||
|
std::find(enabledLanguages.begin(), enabledLanguages.end(),
|
||||||
|
parameters.front()) == enabledLanguages.end())
|
||||||
|
{
|
||||||
|
reportError(context, content->GetOriginalExpression(),
|
||||||
|
"$<COMPILE_LANGUAGE:...> Unknown language.");
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string genName = gg->GetName();
|
||||||
|
if (genName.find("Visual Studio") != std::string::npos)
|
||||||
|
{
|
||||||
|
reportError(context, content->GetOriginalExpression(),
|
||||||
|
"$<COMPILE_LANGUAGE:...> may not be used with Visual Studio "
|
||||||
|
"generators.");
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(genName.find("Makefiles") == std::string::npos &&
|
||||||
|
genName.find("Ninja") == std::string::npos &&
|
||||||
|
genName.find("Watcom WMake") == std::string::npos &&
|
||||||
|
genName.find("Xcode") == std::string::npos)
|
||||||
|
{
|
||||||
|
reportError(context, content->GetOriginalExpression(),
|
||||||
|
"$<COMPILE_LANGUAGE:...> not supported for this generator.");
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (parameters.empty())
|
if (parameters.empty())
|
||||||
{
|
{
|
||||||
return context->Language;
|
return context->Language;
|
||||||
|
|
|
@ -1453,7 +1453,7 @@ void cmLocalGenerator::AddCompileOptions(
|
||||||
{
|
{
|
||||||
cmSystemTools::ParseWindowsCommandLine(targetFlags, opts);
|
cmSystemTools::ParseWindowsCommandLine(targetFlags, opts);
|
||||||
}
|
}
|
||||||
target->GetCompileOptions(opts, config);
|
target->GetCompileOptions(opts, config, lang);
|
||||||
for(std::vector<std::string>::const_iterator i = opts.begin();
|
for(std::vector<std::string>::const_iterator i = opts.begin();
|
||||||
i != opts.end(); ++i)
|
i != opts.end(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -1474,7 +1474,7 @@ void cmLocalGenerator::AddCompileOptions(
|
||||||
this->AppendFlags(flags, targetFlags);
|
this->AppendFlags(flags, targetFlags);
|
||||||
}
|
}
|
||||||
std::vector<std::string> opts;
|
std::vector<std::string> opts;
|
||||||
target->GetCompileOptions(opts, config);
|
target->GetCompileOptions(opts, config, lang);
|
||||||
for(std::vector<std::string>::const_iterator i = opts.begin();
|
for(std::vector<std::string>::const_iterator i = opts.begin();
|
||||||
i != opts.end(); ++i)
|
i != opts.end(); ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2192,7 +2192,8 @@ static void processCompileOptionsInternal(cmTarget const* tgt,
|
||||||
std::vector<std::string> &options,
|
std::vector<std::string> &options,
|
||||||
UNORDERED_SET<std::string> &uniqueOptions,
|
UNORDERED_SET<std::string> &uniqueOptions,
|
||||||
cmGeneratorExpressionDAGChecker *dagChecker,
|
cmGeneratorExpressionDAGChecker *dagChecker,
|
||||||
const std::string& config, bool debugOptions, const char *logName)
|
const std::string& config, bool debugOptions, const char *logName,
|
||||||
|
std::string const& language)
|
||||||
{
|
{
|
||||||
cmMakefile *mf = tgt->GetMakefile();
|
cmMakefile *mf = tgt->GetMakefile();
|
||||||
|
|
||||||
|
@ -2204,7 +2205,8 @@ static void processCompileOptionsInternal(cmTarget const* tgt,
|
||||||
config,
|
config,
|
||||||
false,
|
false,
|
||||||
tgt,
|
tgt,
|
||||||
dagChecker),
|
dagChecker,
|
||||||
|
language),
|
||||||
entryOptions);
|
entryOptions);
|
||||||
std::string usedOptions;
|
std::string usedOptions;
|
||||||
for(std::vector<std::string>::iterator
|
for(std::vector<std::string>::iterator
|
||||||
|
@ -2238,10 +2240,12 @@ static void processCompileOptions(cmTarget const* tgt,
|
||||||
std::vector<std::string> &options,
|
std::vector<std::string> &options,
|
||||||
UNORDERED_SET<std::string> &uniqueOptions,
|
UNORDERED_SET<std::string> &uniqueOptions,
|
||||||
cmGeneratorExpressionDAGChecker *dagChecker,
|
cmGeneratorExpressionDAGChecker *dagChecker,
|
||||||
const std::string& config, bool debugOptions)
|
const std::string& config, bool debugOptions,
|
||||||
|
std::string const& language)
|
||||||
{
|
{
|
||||||
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
|
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
|
||||||
dagChecker, config, debugOptions, "options");
|
dagChecker, config, debugOptions, "options",
|
||||||
|
language);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
@ -2271,7 +2275,8 @@ void cmTarget::GetAutoUicOptions(std::vector<std::string> &result,
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void cmTarget::GetCompileOptions(std::vector<std::string> &result,
|
void cmTarget::GetCompileOptions(std::vector<std::string> &result,
|
||||||
const std::string& config) const
|
const std::string& config,
|
||||||
|
const std::string& language) const
|
||||||
{
|
{
|
||||||
UNORDERED_SET<std::string> uniqueOptions;
|
UNORDERED_SET<std::string> uniqueOptions;
|
||||||
|
|
||||||
|
@ -2303,7 +2308,8 @@ void cmTarget::GetCompileOptions(std::vector<std::string> &result,
|
||||||
uniqueOptions,
|
uniqueOptions,
|
||||||
&dagChecker,
|
&dagChecker,
|
||||||
config,
|
config,
|
||||||
debugOptions);
|
debugOptions,
|
||||||
|
language);
|
||||||
|
|
||||||
std::vector<cmTargetInternals::TargetPropertyEntry*>
|
std::vector<cmTargetInternals::TargetPropertyEntry*>
|
||||||
linkInterfaceCompileOptionsEntries;
|
linkInterfaceCompileOptionsEntries;
|
||||||
|
@ -2318,7 +2324,8 @@ void cmTarget::GetCompileOptions(std::vector<std::string> &result,
|
||||||
uniqueOptions,
|
uniqueOptions,
|
||||||
&dagChecker,
|
&dagChecker,
|
||||||
config,
|
config,
|
||||||
debugOptions);
|
debugOptions,
|
||||||
|
language);
|
||||||
|
|
||||||
deleteAndClear(linkInterfaceCompileOptionsEntries);
|
deleteAndClear(linkInterfaceCompileOptionsEntries);
|
||||||
}
|
}
|
||||||
|
@ -2333,7 +2340,7 @@ static void processCompileDefinitions(cmTarget const* tgt,
|
||||||
{
|
{
|
||||||
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
|
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
|
||||||
dagChecker, config, debugOptions,
|
dagChecker, config, debugOptions,
|
||||||
"definitions");
|
"definitions", std::string());
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
@ -2431,7 +2438,8 @@ static void processCompileFeatures(cmTarget const* tgt,
|
||||||
const std::string& config, bool debugOptions)
|
const std::string& config, bool debugOptions)
|
||||||
{
|
{
|
||||||
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
|
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
|
||||||
dagChecker, config, debugOptions, "features");
|
dagChecker, config, debugOptions, "features",
|
||||||
|
std::string());
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
|
@ -577,7 +577,8 @@ public:
|
||||||
void AppendBuildInterfaceIncludes();
|
void AppendBuildInterfaceIncludes();
|
||||||
|
|
||||||
void GetCompileOptions(std::vector<std::string> &result,
|
void GetCompileOptions(std::vector<std::string> &result,
|
||||||
const std::string& config) const;
|
const std::string& config,
|
||||||
|
const std::string& language) const;
|
||||||
void GetAutoUicOptions(std::vector<std::string> &result,
|
void GetAutoUicOptions(std::vector<std::string> &result,
|
||||||
const std::string& config) const;
|
const std::string& config) const;
|
||||||
void GetCompileFeatures(std::vector<std::string> &features,
|
void GetCompileFeatures(std::vector<std::string> &features,
|
||||||
|
|
|
@ -23,6 +23,21 @@ add_executable(consumer
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (NOT CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||||
|
target_sources(consumer PRIVATE
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/consumer.c"
|
||||||
|
)
|
||||||
|
target_compile_options(consumer
|
||||||
|
PRIVATE
|
||||||
|
-DCONSUMER_LANG_$<COMPILE_LANGUAGE>
|
||||||
|
-DLANG_IS_CXX=$<COMPILE_LANGUAGE:CXX>
|
||||||
|
-DLANG_IS_C=$<COMPILE_LANGUAGE:C>
|
||||||
|
)
|
||||||
|
target_compile_definitions(consumer
|
||||||
|
PRIVATE -DTEST_LANG_DEFINES
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_compile_options(consumer
|
target_compile_options(consumer
|
||||||
PRIVATE $<$<CXX_COMPILER_ID:GNU>:$<TARGET_PROPERTY:target_compile_options,INTERFACE_COMPILE_OPTIONS>>
|
PRIVATE $<$<CXX_COMPILER_ID:GNU>:$<TARGET_PROPERTY:target_compile_options,INTERFACE_COMPILE_OPTIONS>>
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
#ifdef TEST_LANG_DEFINES
|
||||||
|
#ifdef CONSUMER_LANG_CXX
|
||||||
|
#error Unexpected CONSUMER_LANG_CXX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONSUMER_LANG_C
|
||||||
|
#error Expected CONSUMER_LANG_C
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !LANG_IS_C
|
||||||
|
#error Expected LANG_IS_C
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LANG_IS_CXX
|
||||||
|
#error Unexpected LANG_IS_CXX
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void consumer_c()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -15,4 +15,22 @@
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef TEST_LANG_DEFINES
|
||||||
|
#ifndef CONSUMER_LANG_CXX
|
||||||
|
#error Expected CONSUMER_LANG_CXX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONSUMER_LANG_C
|
||||||
|
#error Unexpected CONSUMER_LANG_C
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !LANG_IS_CXX
|
||||||
|
#error Expected LANG_IS_CXX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LANG_IS_C
|
||||||
|
#error Unexpected LANG_IS_C
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
int main() { return 0; }
|
int main() { return 0; }
|
||||||
|
|
|
@ -208,3 +208,5 @@ add_RunCMake_test(IfacePaths_SOURCES TEST_DIR IfacePaths)
|
||||||
if(RPMBUILD_EXECUTABLE)
|
if(RPMBUILD_EXECUTABLE)
|
||||||
add_RunCMake_test(CPackRPM)
|
add_RunCMake_test(CPackRPM)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_RunCMake_test(COMPILE_LANGUAGE-genex)
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
cmake_minimum_required(VERSION 3.1)
|
||||||
|
project(${RunCMake_TEST} NONE)
|
||||||
|
include(${RunCMake_TEST}.cmake)
|
|
@ -0,0 +1 @@
|
||||||
|
1
|
|
@ -0,0 +1,8 @@
|
||||||
|
CMake Error at CompileOptions.cmake:5 \(target_compile_options\):
|
||||||
|
Error evaluating generator expression:
|
||||||
|
|
||||||
|
\$<COMPILE_LANGUAGE:CXX>
|
||||||
|
|
||||||
|
\$<COMPILE_LANGUAGE:...> may not be used with Visual Studio generators.
|
||||||
|
Call Stack \(most recent call first\):
|
||||||
|
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
enable_language(CXX)
|
||||||
|
|
||||||
|
add_executable(main main.cpp)
|
||||||
|
target_compile_options(main PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-DANYTHING>)
|
|
@ -0,0 +1,6 @@
|
||||||
|
include(RunCMake)
|
||||||
|
|
||||||
|
if (RunCMake_GENERATOR MATCHES "Visual Studio")
|
||||||
|
set(RunCMake-stderr-file CompileOptions-stderr-VS.txt)
|
||||||
|
run_cmake(CompileOptions)
|
||||||
|
endif()
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
1
|
|
@ -0,0 +1,8 @@
|
||||||
|
CMake Error at COMPILE_LANGUAGE-unknown-lang.cmake:4 \(target_compile_options\):
|
||||||
|
Error evaluating generator expression:
|
||||||
|
|
||||||
|
\$<COMPILE_LANGUAGE:CXX>
|
||||||
|
|
||||||
|
\$<COMPILE_LANGUAGE:...> Unknown language.
|
||||||
|
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 $<$<COMPILE_LANGUAGE:CXX>:-Wall>)
|
|
@ -23,6 +23,7 @@ run_cmake(COMPILE_LANGUAGE-target_sources)
|
||||||
run_cmake(COMPILE_LANGUAGE-add_executable)
|
run_cmake(COMPILE_LANGUAGE-add_executable)
|
||||||
run_cmake(COMPILE_LANGUAGE-add_library)
|
run_cmake(COMPILE_LANGUAGE-add_library)
|
||||||
run_cmake(COMPILE_LANGUAGE-add_test)
|
run_cmake(COMPILE_LANGUAGE-add_test)
|
||||||
|
run_cmake(COMPILE_LANGUAGE-unknown-lang)
|
||||||
|
|
||||||
if(LINKER_SUPPORTS_PDB)
|
if(LINKER_SUPPORTS_PDB)
|
||||||
run_cmake(NonValidTarget-TARGET_PDB_FILE)
|
run_cmake(NonValidTarget-TARGET_PDB_FILE)
|
||||||
|
|
Loading…
Reference in New Issue