From ce0b9832163624291db04d38984c6aa7ea8ca7d7 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 12 Mar 2018 09:10:57 -0400 Subject: target_compile_options: Add syntax to specify shell strings Options specified via `COMPILE_OPTIONS` and `INTERFACE_COMPILE_OPTIONS` are deduplicated, but individual options can legitimately be duplicated when grouped with other options, e.g. -D A -D B After deduplication that becomes `-D A B`. Therefore we need a way to treat groups of options as units during deduplication. A simple approach is to specify each group as one option, e.g. "-D A" "-D B" However, that conflicts with options that legitimately have spaces. To break this ambiguity, add a `SHELL:` prefix syntax to specify that an option should be parsed like shell command line arguments after deduplication, e.g. "SHELL:-D A" "SHELL:-D B" These will survive deduplication intact, and then be parsed to produce `-D A -D B` on the final command line. Fixes: #15826 --- Help/command/COMPILE_OPTIONS_SHELL.txt | 9 +++++++++ Help/command/add_compile_options.rst | 2 ++ Help/command/target_compile_options.rst | 2 ++ Help/release/dev/compile-options-shell.rst | 6 ++++++ Source/cmGeneratorTarget.cxx | 22 +++++++++++++++++----- Tests/CompileOptions/CMakeLists.txt | 12 ++++++++++++ Tests/CompileOptions/main.cpp | 25 +++++++++++++++++++++++++ 7 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 Help/command/COMPILE_OPTIONS_SHELL.txt create mode 100644 Help/release/dev/compile-options-shell.rst diff --git a/Help/command/COMPILE_OPTIONS_SHELL.txt b/Help/command/COMPILE_OPTIONS_SHELL.txt new file mode 100644 index 0000000..a1316c8 --- /dev/null +++ b/Help/command/COMPILE_OPTIONS_SHELL.txt @@ -0,0 +1,9 @@ +The final set of compile options used for a target is constructed by +accumulating options from the current target and the usage requirements of +it dependencies. The set of options is de-duplicated to avoid repetition. +While beneficial for individual options, the de-duplication step can break +up option groups. For example, ``-D A -D B`` becomes ``-D A B``. One may +specify a group of options using shell-like quoting along with a ``SHELL:`` +prefix. The ``SHELL:`` prefix is dropped and the rest of the option string +is parsed using the :command:`separate_arguments` ``UNIX_COMMAND`` mode. +For example, ``"SHELL:-D A" "SHELL:-D B"`` becomes ``-D A -D B``. diff --git a/Help/command/add_compile_options.rst b/Help/command/add_compile_options.rst index 3fe2a33..44924e6 100644 --- a/Help/command/add_compile_options.rst +++ b/Help/command/add_compile_options.rst @@ -21,3 +21,5 @@ Arguments to ``add_compile_options`` may use "generator expressions" with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual for available expressions. See the :manual:`cmake-buildsystem(7)` manual for more on defining buildsystem properties. + +.. include:: COMPILE_OPTIONS_SHELL.txt diff --git a/Help/command/target_compile_options.rst b/Help/command/target_compile_options.rst index 3e7dc47..b7b4dc1 100644 --- a/Help/command/target_compile_options.rst +++ b/Help/command/target_compile_options.rst @@ -38,3 +38,5 @@ Arguments to ``target_compile_options`` may use "generator expressions" with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual for available expressions. See the :manual:`cmake-buildsystem(7)` manual for more on defining buildsystem properties. + +.. include:: COMPILE_OPTIONS_SHELL.txt diff --git a/Help/release/dev/compile-options-shell.rst b/Help/release/dev/compile-options-shell.rst new file mode 100644 index 0000000..3f83e0c --- /dev/null +++ b/Help/release/dev/compile-options-shell.rst @@ -0,0 +1,6 @@ +compile-options-shell +--------------------- + +* :command:`target_compile_options` and :command:`add_compile_options` + commands gained a ``SHELL:`` prefix to specify a group of related + options using shell-like quoting. diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 8cdba93..c3872c1 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -2622,13 +2622,20 @@ std::vector cmGeneratorTarget::GetIncludeDirectories( return includes; } +enum class OptionsParse +{ + None, + Shell +}; + static void processCompileOptionsInternal( cmGeneratorTarget const* tgt, const std::vector& entries, std::vector& options, std::unordered_set& uniqueOptions, cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - bool debugOptions, const char* logName, std::string const& language) + bool debugOptions, const char* logName, std::string const& language, + OptionsParse parse) { for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) { std::vector entryOptions; @@ -2639,7 +2646,12 @@ static void processCompileOptionsInternal( std::string usedOptions; for (std::string const& opt : entryOptions) { if (uniqueOptions.insert(opt).second) { - options.push_back(opt); + if (parse == OptionsParse::Shell && + cmHasLiteralPrefix(opt, "SHELL:")) { + cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, options); + } else { + options.push_back(opt); + } if (debugOptions) { usedOptions += " * " + opt + "\n"; } @@ -2664,7 +2676,7 @@ static void processCompileOptions( { processCompileOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, config, debugOptions, "options", - language); + language, OptionsParse::Shell); } void cmGeneratorTarget::GetCompileOptions(std::vector& result, @@ -2718,7 +2730,7 @@ static void processCompileFeatures( { processCompileOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, config, debugOptions, "features", - std::string()); + std::string(), OptionsParse::None); } void cmGeneratorTarget::GetCompileFeatures(std::vector& result, @@ -2768,7 +2780,7 @@ static void processCompileDefinitions( { processCompileOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, config, debugOptions, - "definitions", language); + "definitions", language, OptionsParse::None); } void cmGeneratorTarget::GetCompileDefinitions( diff --git a/Tests/CompileOptions/CMakeLists.txt b/Tests/CompileOptions/CMakeLists.txt index 692e0de..c9f1710 100644 --- a/Tests/CompileOptions/CMakeLists.txt +++ b/Tests/CompileOptions/CMakeLists.txt @@ -18,9 +18,21 @@ set_property(TARGET CompileOptions PROPERTY COMPILE_OPTIONS "-DTEST_DEFINE" "-DNEEDS_ESCAPE=\"E$CAPE\"" "$<$:-DTEST_DEFINE_GNU>" + "SHELL:" # produces no options ${c_tests} ${cxx_tests} ) +if(BORLAND OR WATCOM) + # these compilers do not support separate -D flags + target_compile_definitions(CompileOptions PRIVATE NO_DEF_TESTS) +else() + set_property(TARGET CompileOptions APPEND PROPERTY COMPILE_OPTIONS + "SHELL:-D DEF_A" + "$<1:SHELL:-D DEF_B>" + "SHELL:-D 'DEF_C' -D \"DEF_D\"" + [[SHELL:-D "DEF_STR=\"string with spaces\""]] + ) +endif() if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|Borland|Embarcadero") set_property(TARGET CompileOptions APPEND PROPERTY COMPILE_OPTIONS diff --git a/Tests/CompileOptions/main.cpp b/Tests/CompileOptions/main.cpp index 63a0480..4779b88 100644 --- a/Tests/CompileOptions/main.cpp +++ b/Tests/CompileOptions/main.cpp @@ -12,6 +12,28 @@ #endif #endif +#ifndef NO_DEF_TESTS +#ifndef DEF_A +#error Expected definition DEF_A +#endif + +#ifndef DEF_B +#error Expected definition DEF_B +#endif + +#ifndef DEF_C +#error Expected definition DEF_C +#endif + +#ifndef DEF_D +#error Expected definition DEF_D +#endif + +#ifndef DEF_STR +#error Expected definition DEF_STR +#endif +#endif + #include int main() @@ -20,6 +42,9 @@ int main() #ifdef TEST_OCTOTHORPE && strcmp(TEST_OCTOTHORPE, "#") == 0 #endif +#ifndef NO_DEF_TESTS + && strcmp(DEF_STR, "string with spaces") == 0 +#endif && strcmp(EXPECTED_C_COMPILER_VERSION, TEST_C_COMPILER_VERSION) == 0 && strcmp(EXPECTED_CXX_COMPILER_VERSION, TEST_CXX_COMPILER_VERSION) == -- cgit v0.12