Commit 78b1c2e0 authored by Marc Chevrier's avatar Marc Chevrier
Browse files

sourceFile properties: add property COMPILE_OPTIONS

Add the support of per-source property COMPILE_OPTIONS,
including generator expressions support.

Related: #17507
parent 3f935e69
......@@ -370,6 +370,7 @@ Properties on Source Files
/prop_sf/AUTORCC_OPTIONS
/prop_sf/COMPILE_DEFINITIONS
/prop_sf/COMPILE_FLAGS
/prop_sf/COMPILE_OPTIONS
/prop_sf/EXTERNAL_OBJECT
/prop_sf/Fortran_FORMAT
/prop_sf/GENERATED
......
COMPILE_OPTIONS
---------------
List of additional options to pass to the compiler.
This property holds a :ref:`;-list <CMake Language Lists>` of options
and will be added to the list of compile flags when this
source file builds. Use :prop_sf:`COMPILE_DEFINITIONS` to pass
additional preprocessor definitions.
Contents of ``COMPILE_OPTIONS`` may use "generator expressions" with the
syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual
for available expressions. However, :generator:`Xcode`
does not support per-config per-source settings, so expressions
that depend on the build configuration are not allowed with that
generator.
sourceFile-new-properties
-------------------------
* The source files learn new property :prop_sf:`COMPILE_OPTIONS`.
......@@ -361,13 +361,20 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject(
}
// Add source file specific flags.
cmGeneratorExpressionInterpreter genexInterpreter(lg, gtgt, config,
gtgt->GetName(), language);
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) {
cmGeneratorExpressionInterpreter genexInterpreter(
lg, gtgt, config, gtgt->GetName(), language);
lg->AppendFlags(flags, genexInterpreter.Evaluate(cflags, COMPILE_FLAGS));
}
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
if (const char* coptions = source->GetProperty(COMPILE_OPTIONS)) {
lg->AppendCompileOptions(
flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
}
return flags;
}
......
......@@ -743,6 +743,11 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
if (const char* cflags = sf->GetProperty(COMPILE_FLAGS)) {
lg->AppendFlags(flags, genexInterpreter.Evaluate(cflags, COMPILE_FLAGS));
}
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
if (const char* coptions = sf->GetProperty(COMPILE_OPTIONS)) {
lg->AppendCompileOptions(
flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
}
// Add per-source definitions.
BuildObjectListOrString flagsBuild(this, false);
......
......@@ -1494,6 +1494,12 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
fc.CompileFlags = genexInterpreter.Evaluate(cflags, COMPILE_FLAGS);
needfc = true;
}
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
if (const char* coptions = sf.GetProperty(COMPILE_OPTIONS)) {
lg->AppendCompileOptions(
fc.CompileFlags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
needfc = true;
}
if (lg->FortranProject) {
switch (cmOutputConverter::GetFortranFormat(
sf.GetProperty("Fortran_FORMAT"))) {
......
......@@ -445,6 +445,16 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
<< "\n";
}
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
if (const char* coptions = source.GetProperty(COMPILE_OPTIONS)) {
const char* evaluatedOptions =
genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS);
this->LocalGenerator->AppendCompileOptions(flags, evaluatedOptions);
*this->FlagFileStream << "# Custom options: " << relativeObj
<< "_OPTIONS = " << evaluatedOptions << "\n"
<< "\n";
}
// Add language-specific defines.
std::set<std::string> defines;
......
......@@ -135,16 +135,23 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
}
// Add source file specific flags.
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, this->GeneratorTarget,
this->LocalGenerator->GetConfigName(), this->GeneratorTarget->GetName(),
language);
const std::string COMPILE_FLAGS("COMPILE_FLAGS");
if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) {
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, this->GeneratorTarget,
this->LocalGenerator->GetConfigName(), this->GeneratorTarget->GetName(),
language);
this->LocalGenerator->AppendFlags(
flags, genexInterpreter.Evaluate(cflags, COMPILE_FLAGS));
}
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
if (const char* coptions = source->GetProperty(COMPILE_OPTIONS)) {
this->LocalGenerator->AppendCompileOptions(
flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
}
return flags;
}
......
......@@ -708,6 +708,11 @@ static Json::Value DumpSourceFilesList(
lg->AppendFlags(compileFlags,
genexInterpreter.Evaluate(cflags, COMPILE_FLAGS));
}
const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
if (const char* coptions = file->GetProperty(COMPILE_OPTIONS)) {
lg->AppendCompileOptions(
compileFlags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
}
fileData.Flags = compileFlags;
fileData.IncludePathList = ld.IncludePathList;
......
......@@ -2036,6 +2036,8 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
}
std::string flags;
bool configDependentFlags = false;
std::string options;
bool configDependentOptions = false;
std::string defines;
bool configDependentDefines = false;
if (const char* cflags = sf.GetProperty("COMPILE_FLAGS")) {
......@@ -2043,6 +2045,11 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
cmGeneratorExpression::Find(cflags) != std::string::npos;
flags += cflags;
}
if (const char* coptions = sf.GetProperty("COMPILE_OPTIONS")) {
configDependentOptions =
cmGeneratorExpression::Find(coptions) != std::string::npos;
options += coptions;
}
if (const char* cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) {
configDependentDefines =
cmGeneratorExpression::Find(cdefs) != std::string::npos;
......@@ -2099,7 +2106,8 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
}
// if we have flags or defines for this config then
// use them
if (!flags.empty() || !configDefines.empty() || compileAs || noWinRT) {
if (!flags.empty() || !options.empty() || !configDefines.empty() ||
compileAs || noWinRT) {
(*this->BuildFileStream) << firstString;
firstString = ""; // only do firstString once
hasFlags = true;
......@@ -2137,6 +2145,17 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
} else {
clOptions.Parse(flags.c_str());
}
if (!options.empty()) {
std::string expandedOptions;
if (configDependentOptions) {
this->LocalGenerator->AppendCompileOptions(
expandedOptions,
genexInterpreter.Evaluate(options, "COMPILE_OPTIONS"));
} else {
this->LocalGenerator->AppendCompileOptions(expandedOptions, options);
}
clOptions.Parse(expandedOptions.c_str());
}
if (clOptions.HasFlag("AdditionalIncludeDirectories")) {
clOptions.AppendFlag("AdditionalIncludeDirectories",
"%(AdditionalIncludeDirectories)");
......
......@@ -260,17 +260,33 @@ add_custom_target(check-part4 ALL
#-----------------------------------------------------------------------------
# Cover source file properties with generator expressions.
add_executable(srcgenex_flags srcgenex_flags.c)
set_property(SOURCE srcgenex_flags.c PROPERTY COMPILE_FLAGS "-DNAME=$<TARGET_PROPERTY:NAME>")
add_executable(srcgenex_flags_COMPILE_LANGUAGE srcgenex_flags_COMPILE_LANGUAGE.c)
set_property(SOURCE srcgenex_flags_COMPILE_LANGUAGE.c PROPERTY COMPILE_FLAGS "$<$<COMPILE_LANGUAGE:C>:-DNAME=$<TARGET_PROPERTY:NAME>>")
add_executable(srcgenex_defs srcgenex_defs.c)
set_property(SOURCE srcgenex_defs.c PROPERTY COMPILE_DEFINITIONS NAME=$<TARGET_PROPERTY:NAME>)
add_executable(srcgenex_defs_COMPILE_LANGUAGE srcgenex_defs_COMPILE_LANGUAGE.c)
set_property(SOURCE srcgenex_defs_COMPILE_LANGUAGE.c PROPERTY COMPILE_DEFINITIONS $<$<COMPILE_LANGUAGE:C>:NAME=$<TARGET_PROPERTY:NAME>>)
## generate various source files
foreach (item IN ITEMS flags flags_COMPILE_LANGUAGE
options options_COMPILE_LANGUAGE
defs defs_COMPILE_LANGUAGE)
set(TARGET_NAME srcgenex_${item})
configure_file(srcgenex.c.in ${TARGET_NAME}.c @ONLY)
endforeach()
add_executable(srcgenex_flags "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_flags.c")
set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_flags.c"
PROPERTY COMPILE_FLAGS "-DNAME=$<TARGET_PROPERTY:NAME>")
add_executable(srcgenex_flags_COMPILE_LANGUAGE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_flags_COMPILE_LANGUAGE.c")
set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_flags_COMPILE_LANGUAGE.c"
PROPERTY COMPILE_FLAGS "$<$<COMPILE_LANGUAGE:C>:-DNAME=$<TARGET_PROPERTY:NAME>>")
add_executable(srcgenex_options "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_options.c")
set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_options.c"
PROPERTY COMPILE_OPTIONS -DUNUSED -DNAME=$<TARGET_PROPERTY:NAME>)
add_executable(srcgenex_options_COMPILE_LANGUAGE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_options_COMPILE_LANGUAGE.c")
set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_options_COMPILE_LANGUAGE.c"
PROPERTY COMPILE_OPTIONS $<$<COMPILE_LANGUAGE:C>:-DNAME=$<TARGET_PROPERTY:NAME>>)
add_executable(srcgenex_defs "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_defs.c")
set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_defs.c"
PROPERTY COMPILE_DEFINITIONS NAME=$<TARGET_PROPERTY:NAME>)
add_executable(srcgenex_defs_COMPILE_LANGUAGE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_defs_COMPILE_LANGUAGE.c")
set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/srcgenex_defs_COMPILE_LANGUAGE.c"
PROPERTY COMPILE_DEFINITIONS $<$<COMPILE_LANGUAGE:C>:NAME=$<TARGET_PROPERTY:NAME>>)
#-----------------------------------------------------------------------------
# Cover test properties with generator expressions.
......
int srcgenex_defs_COMPILE_LANGUAGE(void)
{
return 0;
}
int main(int argc, char* argv[])
{
#ifndef NAME
#error NAME not defined
#endif
return NAME();
}
int srcgenex_flags(void)
{
return 0;
}
int main(int argc, char* argv[])
{
#ifndef NAME
#error NAME not defined
#endif
return NAME();
}
int srcgenex_flags_COMPILE_LANGUAGE(void)
{
return 0;
}
int main(int argc, char* argv[])
{
#ifndef NAME
#error NAME not defined
#endif
return NAME();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment