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
|
||||
:manual:`cmake-compile-features(7)` manual for information on
|
||||
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
|
||||
=========================
|
||||
|
@ -174,6 +200,10 @@ Available informational expressions are:
|
|||
``$<INSTALL_PREFIX>``
|
||||
Content of the install prefix when the target is exported via
|
||||
: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
|
||||
==================
|
||||
|
|
|
@ -827,6 +827,40 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode
|
|||
"components of the file(GENERATE) command.");
|
||||
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())
|
||||
{
|
||||
return context->Language;
|
||||
|
|
|
@ -1453,7 +1453,7 @@ void cmLocalGenerator::AddCompileOptions(
|
|||
{
|
||||
cmSystemTools::ParseWindowsCommandLine(targetFlags, opts);
|
||||
}
|
||||
target->GetCompileOptions(opts, config);
|
||||
target->GetCompileOptions(opts, config, lang);
|
||||
for(std::vector<std::string>::const_iterator i = opts.begin();
|
||||
i != opts.end(); ++i)
|
||||
{
|
||||
|
@ -1474,7 +1474,7 @@ void cmLocalGenerator::AddCompileOptions(
|
|||
this->AppendFlags(flags, targetFlags);
|
||||
}
|
||||
std::vector<std::string> opts;
|
||||
target->GetCompileOptions(opts, config);
|
||||
target->GetCompileOptions(opts, config, lang);
|
||||
for(std::vector<std::string>::const_iterator i = opts.begin();
|
||||
i != opts.end(); ++i)
|
||||
{
|
||||
|
|
|
@ -2192,7 +2192,8 @@ static void processCompileOptionsInternal(cmTarget const* tgt,
|
|||
std::vector<std::string> &options,
|
||||
UNORDERED_SET<std::string> &uniqueOptions,
|
||||
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();
|
||||
|
||||
|
@ -2204,7 +2205,8 @@ static void processCompileOptionsInternal(cmTarget const* tgt,
|
|||
config,
|
||||
false,
|
||||
tgt,
|
||||
dagChecker),
|
||||
dagChecker,
|
||||
language),
|
||||
entryOptions);
|
||||
std::string usedOptions;
|
||||
for(std::vector<std::string>::iterator
|
||||
|
@ -2238,10 +2240,12 @@ static void processCompileOptions(cmTarget const* tgt,
|
|||
std::vector<std::string> &options,
|
||||
UNORDERED_SET<std::string> &uniqueOptions,
|
||||
cmGeneratorExpressionDAGChecker *dagChecker,
|
||||
const std::string& config, bool debugOptions)
|
||||
const std::string& config, bool debugOptions,
|
||||
std::string const& language)
|
||||
{
|
||||
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,
|
||||
const std::string& config) const
|
||||
const std::string& config,
|
||||
const std::string& language) const
|
||||
{
|
||||
UNORDERED_SET<std::string> uniqueOptions;
|
||||
|
||||
|
@ -2303,7 +2308,8 @@ void cmTarget::GetCompileOptions(std::vector<std::string> &result,
|
|||
uniqueOptions,
|
||||
&dagChecker,
|
||||
config,
|
||||
debugOptions);
|
||||
debugOptions,
|
||||
language);
|
||||
|
||||
std::vector<cmTargetInternals::TargetPropertyEntry*>
|
||||
linkInterfaceCompileOptionsEntries;
|
||||
|
@ -2318,7 +2324,8 @@ void cmTarget::GetCompileOptions(std::vector<std::string> &result,
|
|||
uniqueOptions,
|
||||
&dagChecker,
|
||||
config,
|
||||
debugOptions);
|
||||
debugOptions,
|
||||
language);
|
||||
|
||||
deleteAndClear(linkInterfaceCompileOptionsEntries);
|
||||
}
|
||||
|
@ -2333,7 +2340,7 @@ static void processCompileDefinitions(cmTarget const* tgt,
|
|||
{
|
||||
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
|
||||
dagChecker, config, debugOptions,
|
||||
"definitions");
|
||||
"definitions", std::string());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -2431,7 +2438,8 @@ static void processCompileFeatures(cmTarget const* tgt,
|
|||
const std::string& config, bool debugOptions)
|
||||
{
|
||||
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
|
||||
dagChecker, config, debugOptions, "features");
|
||||
dagChecker, config, debugOptions, "features",
|
||||
std::string());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
|
@ -577,7 +577,8 @@ public:
|
|||
void AppendBuildInterfaceIncludes();
|
||||
|
||||
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,
|
||||
const std::string& config) const;
|
||||
void GetCompileFeatures(std::vector<std::string> &features,
|
||||
|
|
|
@ -23,6 +23,21 @@ add_executable(consumer
|
|||
"${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
|
||||
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
|
||||
|
||||
#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; }
|
||||
|
|
|
@ -208,3 +208,5 @@ add_RunCMake_test(IfacePaths_SOURCES TEST_DIR IfacePaths)
|
|||
if(RPMBUILD_EXECUTABLE)
|
||||
add_RunCMake_test(CPackRPM)
|
||||
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_library)
|
||||
run_cmake(COMPILE_LANGUAGE-add_test)
|
||||
run_cmake(COMPILE_LANGUAGE-unknown-lang)
|
||||
|
||||
if(LINKER_SUPPORTS_PDB)
|
||||
run_cmake(NonValidTarget-TARGET_PDB_FILE)
|
||||
|
|
Loading…
Reference in New Issue