diff options
author | Craig Scott <craig.scott@crascit.com> | 2024-08-25 04:41:41 (GMT) |
---|---|---|
committer | Craig Scott <craig.scott@crascit.com> | 2024-09-09 22:19:09 (GMT) |
commit | ec519f3e975467443a8286b4ddc1904d964f851f (patch) | |
tree | 064d01a870e69a69f19c3fe2b5f7b33e3e69d9ca | |
parent | 8dc8be08849acb75446a53fe763eee5b3296d739 (diff) | |
download | CMake-ec519f3e975467443a8286b4ddc1904d964f851f.zip CMake-ec519f3e975467443a8286b4ddc1904d964f851f.tar.gz CMake-ec519f3e975467443a8286b4ddc1904d964f851f.tar.bz2 |
add_custom_command: Validate arguments more rigorously
Add a new CMP0175 policy to preserve backward compatibility
for projects that were using unsupported keywords or arguments.
Fixes: #26096, #21089, #18976
-rw-r--r-- | Help/command/add_custom_command.rst | 69 | ||||
-rw-r--r-- | Help/manual/cmake-policies.7.rst | 1 | ||||
-rw-r--r-- | Help/policy/CMP0175.rst | 40 | ||||
-rw-r--r-- | Source/cmAddCustomCommandCommand.cxx | 203 | ||||
-rw-r--r-- | Source/cmPolicies.h | 2 | ||||
-rw-r--r-- | Tests/RunCMake/add_custom_command/CMP0175-NEW-result.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/add_custom_command/CMP0175-NEW-stderr.txt | 29 | ||||
-rw-r--r-- | Tests/RunCMake/add_custom_command/CMP0175-NEW.cmake | 2 | ||||
-rw-r--r-- | Tests/RunCMake/add_custom_command/CMP0175-OLD.cmake | 2 | ||||
-rw-r--r-- | Tests/RunCMake/add_custom_command/CMP0175-WARN-stderr.txt | 72 | ||||
-rw-r--r-- | Tests/RunCMake/add_custom_command/CMP0175-WARN.cmake | 1 | ||||
-rw-r--r-- | Tests/RunCMake/add_custom_command/CMP0175.cmake | 65 | ||||
-rw-r--r-- | Tests/RunCMake/add_custom_command/RunCMakeTest.cmake | 3 |
13 files changed, 481 insertions, 9 deletions
diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index a69c8dc..122bb4e 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -5,6 +5,8 @@ Add a custom build rule to the generated build system. There are two main signatures for ``add_custom_command``. +.. _`add_custom_command(OUTPUT)`: + Generating Files ^^^^^^^^^^^^^^^^ @@ -54,7 +56,7 @@ The options are: the appended commands and dependencies apply to all configurations. The ``COMMENT``, ``MAIN_DEPENDENCY``, and ``WORKING_DIRECTORY`` - options are currently ignored when APPEND is given, but may be + options are currently ignored when ``APPEND`` is given, but may be used in the future. ``BYPRODUCTS`` @@ -82,6 +84,10 @@ The options are: The :ref:`Makefile Generators` will remove ``BYPRODUCTS`` and other :prop_sf:`GENERATED` files during ``make clean``. + This keyword cannot be used with ``APPEND`` (see policy :policy:`CMP0175`). + All byproducts must be set in the first call to + ``add_custom_command(OUTPUT...)`` for the output files. + .. versionadded:: 3.20 Arguments to ``BYPRODUCTS`` may use a restricted set of :manual:`generator expressions <cmake-generator-expressions(7)>`. @@ -95,11 +101,15 @@ The options are: ``COMMAND`` Specify the command-line(s) to execute at build time. - If more than one ``COMMAND`` is specified they will be executed in order, + At least one ``COMMAND`` would normally be given, but certain patterns + may omit it, such as adding commands in separate calls using `APPEND`. + + If more than one ``COMMAND`` is specified, they will be executed in order, but *not* necessarily composed into a stateful shell or batch script. - (To run a full script, use the :command:`configure_file` command or the + To run a full script, use the :command:`configure_file` command or the :command:`file(GENERATE)` command to create it, and then specify - a ``COMMAND`` to launch it.) + a ``COMMAND`` to launch it. + The optional ``ARGS`` argument is for backward compatibility and will be ignored. @@ -144,7 +154,8 @@ The options are: ``COMMENT`` Display the given message before the commands are executed at - build time. + build time. This will be ignored if ``APPEND`` is given, although a future + version may use it. .. versionadded:: 3.26 Arguments to ``COMMENT`` may use @@ -204,6 +215,10 @@ The options are: ``${CC} "-I$<JOIN:$<TARGET_PROPERTY:foo,INCLUDE_DIRECTORIES>,;-I>" foo.cc`` to be properly expanded. + This keyword cannot be used with ``APPEND`` (see policy :policy:`CMP0175`). + If the appended commands need this option to be set, it must be set on the + first call to ``add_custom_command(OUTPUT...)`` for the output files. + ``CODEGEN`` .. versionadded:: 3.31 @@ -216,6 +231,10 @@ The options are: Furthermore, this option is allowed only if policy :policy:`CMP0171` is set to ``NEW``. + This keyword cannot be used with ``APPEND`` (see policy :policy:`CMP0175`). + It can only be set on the first call to ``add_custom_command(OUTPUT...)`` + for the output files. + ``IMPLICIT_DEPENDS`` Request scanning of implicit dependencies of an input file. The language given specifies the programming language whose @@ -240,6 +259,10 @@ The options are: Using a pool that is not defined by :prop_gbl:`JOB_POOLS` causes an error by ninja at build time. + This keyword cannot be used with ``APPEND`` (see policy :policy:`CMP0175`). + Job pools can only be specified in the first call to + ``add_custom_command(OUTPUT...)`` for the output files. + ``JOB_SERVER_AWARE`` .. versionadded:: 3.28 @@ -251,6 +274,10 @@ The options are: This option is silently ignored by other generators. + This keyword cannot be used with ``APPEND`` (see policy :policy:`CMP0175`). + Job server awareness can only be specified in the first call to + ``add_custom_command(OUTPUT...)`` for the output files. + .. _`GNU Make Documentation`: https://www.gnu.org/software/make/manual/html_node/MAKE-Variable.html ``MAIN_DEPENDENCY`` @@ -262,6 +289,9 @@ The options are: library or an executable) counts as an implicit main dependency which gets silently overwritten by a custom command specification. + This option is currently ignored if ``APPEND`` is given, but a future + version may use it. + ``OUTPUT`` Specify the output files the command is expected to produce. Each output file will be marked with the :prop_sf:`GENERATED` @@ -306,6 +336,10 @@ The options are: With the :generator:`Ninja` generator, this places the command in the ``console`` :prop_gbl:`pool <JOB_POOLS>`. + This keyword cannot be used with ``APPEND`` (see policy :policy:`CMP0175`). + If the appended commands need access to the terminal, it must be set on + the first call to ``add_custom_command(OUTPUT...)`` for the output files. + ``VERBATIM`` All arguments to the commands will be escaped properly for the build tool so that the invoked command receives each argument @@ -316,11 +350,18 @@ The options are: is platform specific because there is no protection of tool-specific special characters. + This keyword cannot be used with ``APPEND`` (see policy :policy:`CMP0175`). + If the appended commands need to be treated as ``VERBATIM``, it must be set + on the first call to ``add_custom_command(OUTPUT...)`` for the output files. + ``WORKING_DIRECTORY`` Execute the command with the given current working directory. - If it is a relative path it will be interpreted relative to the + If it is a relative path, it will be interpreted relative to the build tree directory corresponding to the current source directory. + This option is currently ignored if ``APPEND`` is given, but a future + version may use it. + .. versionadded:: 3.13 Arguments to ``WORKING_DIRECTORY`` may use :manual:`generator expressions <cmake-generator-expressions(7)>`. @@ -406,6 +447,10 @@ The options are: :ref:`Makefile Generators`, :ref:`Visual Studio Generators`, and the :generator:`Xcode` generator. + This keyword cannot be used with ``APPEND`` (see policy :policy:`CMP0175`). + Depfiles can only be set on the first call to + ``add_custom_command(OUTPUT...)`` for the output files. + ``DEPENDS_EXPLICIT_ONLY`` .. versionadded:: 3.27 @@ -421,6 +466,10 @@ The options are: This option can be enabled on all custom commands by setting :variable:`CMAKE_ADD_CUSTOM_COMMAND_DEPENDS_EXPLICIT_ONLY` to ``ON``. + This keyword cannot be used with ``APPEND`` (see policy :policy:`CMP0175`). + It can only be set on the first call to ``add_custom_command(OUTPUT...)`` + for the output files. + Only the :ref:`Ninja Generators` actually use this information to remove unnecessary implicit dependencies. @@ -575,9 +624,11 @@ of the following is specified: Run after all other rules within the target have been executed. Projects should always specify one of the above three keywords when using -the ``TARGET`` form. For backward compatibility reasons, ``POST_BUILD`` is -assumed if no such keyword is given, but projects should explicitly provide -one of the keywords to make clear the behavior they expect. +the ``TARGET`` form. See policy :policy:`CMP0175`. + +All other keywords shown in the signature above have the same meaning as they +do for the :command:`add_custom_command(OUTPUT)` form of the command. +At least one ``COMMAND`` must be given, see policy :policy:`CMP0175`. .. note:: Because generator expressions can be used in custom commands, diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index e257c36..e5284e9 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,6 +57,7 @@ Policies Introduced by CMake 3.31 .. toctree:: :maxdepth: 1 + CMP0175: add_custom_command() rejects invalid arguments. </policy/CMP0175> CMP0174: cmake_parse_arguments(PARSE_ARGV) defines a variable for an empty string after a single-value keyword. </policy/CMP0174> CMP0173: The CMakeFindFrameworks module is removed. </policy/CMP0173> CMP0172: The CPack module enables per-machine installation by default in the CPack WIX Generator. </policy/CMP0172> diff --git a/Help/policy/CMP0175.rst b/Help/policy/CMP0175.rst new file mode 100644 index 0000000..f2c372d --- /dev/null +++ b/Help/policy/CMP0175.rst @@ -0,0 +1,40 @@ +CMP0175 +------- + +.. versionadded:: 3.31 + +:command:`add_custom_command` rejects invalid arguments. + +CMake 3.30 and earlier silently ignored unsupported keywords and missing or +invalid arguments for the different forms of the :command:`add_custom_command` +command. CMake 3.31 implements more rigorous argument checking and will flag +invalid or missing arguments as errors. + +The ``OLD`` behavior of this policy will accept the same invalid keywords or +arguments as CMake 3.30 and earlier. The ``NEW`` behavior will flag the +following as errors that previously went unreported: + +* The ``OUTPUT`` form does not accept ``PRE_BUILD``, ``PRE_LINK``, or + ``POST_BUILD`` keywords. +* When the ``APPEND`` keyword is given, the ``OUTPUT`` form also does not + accept ``BYPRODUCTS``, ``COMMAND_EXPAND_LISTS``, ``DEPENDS_EXPLICIT_ONLY``, + ``DEPFILE``, ``JOB_POOL``, ``JOB_SERVER_AWARE``, ``USES_TERMINAL``, or + ``VERBATIM`` keywords. +* The ``TARGET`` form requires exactly one of ``PRE_BUILD``, ``PRE_LINK``, or + ``POST_BUILD`` to be given. Previously, if none were given, ``POST_BUILD`` + was assumed, or if multiple keywords were given, the last one was used. +* The ``TARGET`` form does not accept ``DEPENDS``, ``DEPENDS_EXPLICIT_ONLY``, + ``DEPFILE``, ``IMPLICIT_DEPENDS``, ``MAIN_DEPENDENCY``, ``JOB_POOL``, + ``JOB_SERVER_AWARE``, or ``USES_TERMINAL`` keywords. +* The ``TARGET`` form now requires at least one ``COMMAND`` to be given. +* If a keyword expects a value to be given after it, but no value is provided, + that was previously treated as though the keyword was not given at all. +* The ``COMMENT`` keyword expects exactly one value after it. If multiple + values are given, or if the ``COMMENT`` keyword is given more than once, + this is an error. + +.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 3.31 +.. |WARNS_OR_DOES_NOT_WARN| replace:: warns +.. include:: STANDARD_ADVICE.txt + +.. include:: DEPRECATED.txt diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx index d5adba7..885094d 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -2,11 +2,15 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAddCustomCommandCommand.h" +#include <algorithm> +#include <iterator> +#include <set> #include <sstream> #include <unordered_set> #include <utility> #include <cm/memory> +#include <cmext/string_view> #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" @@ -140,11 +144,82 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args, keyDEPENDS_EXPLICIT_ONLY, keyCODEGEN }; + /* clang-format off */ + static std::set<std::string> const supportedTargetKeywords{ + keyARGS, + keyBYPRODUCTS, + keyCOMMAND, + keyCOMMAND_EXPAND_LISTS, + keyCOMMENT, + keyPOST_BUILD, + keyPRE_BUILD, + keyPRE_LINK, + keyTARGET, + keyVERBATIM, + keyWORKING_DIRECTORY + }; + /* clang-format on */ + static std::set<std::string> const supportedOutputKeywords{ + keyAPPEND, + keyARGS, + keyBYPRODUCTS, + keyCODEGEN, + keyCOMMAND, + keyCOMMAND_EXPAND_LISTS, + keyCOMMENT, + keyDEPENDS, + keyDEPENDS_EXPLICIT_ONLY, + keyDEPFILE, + keyIMPLICIT_DEPENDS, + keyJOB_POOL, + keyJOB_SERVER_AWARE, + keyMAIN_DEPENDENCY, + keyOUTPUT, + keyUSES_TERMINAL, + keyVERBATIM, + keyWORKING_DIRECTORY + }; + /* clang-format off */ + static std::set<std::string> const supportedAppendKeywords{ + keyAPPEND, + keyARGS, + keyCOMMAND, + keyCOMMENT, // Allowed but ignored + keyDEPENDS, + keyIMPLICIT_DEPENDS, + keyMAIN_DEPENDENCY, // Allowed but ignored + keyOUTPUT, + keyWORKING_DIRECTORY // Allowed but ignored + }; + /* clang-format on */ + std::set<std::string> keywordsSeen; + std::string const* keywordExpectingValue = nullptr; + auto const cmp0175 = mf.GetPolicyStatus(cmPolicies::CMP0175); for (std::string const& copy : args) { if (keywords.count(copy)) { + // Check if a preceding keyword expected a value but there wasn't one + if (keywordExpectingValue) { + std::string const msg = + cmStrCat("Keyword ", *keywordExpectingValue, + " requires a value, but none was given."); + if (cmp0175 == cmPolicies::NEW) { + mf.IssueMessage(MessageType::FATAL_ERROR, msg); + return false; + } + if (cmp0175 == cmPolicies::WARN) { + mf.IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat(msg, '\n', + cmPolicies::GetPolicyWarning(cmPolicies::CMP0175))); + } + } + keywordExpectingValue = nullptr; + keywordsSeen.insert(copy); + if (copy == keySOURCE) { doing = doing_source; + keywordExpectingValue = &keySOURCE; } else if (copy == keyCOMMAND) { doing = doing_command; @@ -173,6 +248,7 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args, codegen = true; } else if (copy == keyTARGET) { doing = doing_target; + keywordExpectingValue = &keyTARGET; } else if (copy == keyARGS) { // Ignore this old keyword. } else if (copy == keyDEPENDS) { @@ -181,16 +257,20 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args, doing = doing_outputs; } else if (copy == keyOUTPUT) { doing = doing_output; + keywordExpectingValue = &keyOUTPUT; } else if (copy == keyBYPRODUCTS) { doing = doing_byproducts; } else if (copy == keyWORKING_DIRECTORY) { doing = doing_working_directory; + keywordExpectingValue = &keyWORKING_DIRECTORY; } else if (copy == keyMAIN_DEPENDENCY) { doing = doing_main_dependency; + keywordExpectingValue = &keyMAIN_DEPENDENCY; } else if (copy == keyIMPLICIT_DEPENDS) { doing = doing_implicit_depends_lang; } else if (copy == keyCOMMENT) { doing = doing_comment; + keywordExpectingValue = &keyCOMMENT; } else if (copy == keyDEPFILE) { doing = doing_depfile; if (!mf.GetGlobalGenerator()->SupportsCustomCommandDepfile()) { @@ -198,12 +278,16 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args, mf.GetGlobalGenerator()->GetName())); return false; } + keywordExpectingValue = &keyDEPFILE; } else if (copy == keyJOB_POOL) { doing = doing_job_pool; + keywordExpectingValue = &keyJOB_POOL; } else if (copy == keyJOB_SERVER_AWARE) { doing = doing_job_server_aware; + keywordExpectingValue = &keyJOB_SERVER_AWARE; } } else { + keywordExpectingValue = nullptr; // Value is being processed now std::string filename; switch (doing) { case doing_output: @@ -288,6 +372,21 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args, byproducts.push_back(filename); break; case doing_comment: + if (!comment_buffer.empty()) { + std::string const msg = + "COMMENT requires exactly one argument, but multiple values " + "or COMMENT keywords have been given."; + if (cmp0175 == cmPolicies::NEW) { + mf.IssueMessage(MessageType::FATAL_ERROR, msg); + return false; + } + if (cmp0175 == cmPolicies::WARN) { + mf.IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat(msg, '\n', + cmPolicies::GetPolicyWarning(cmPolicies::CMP0175))); + } + } comment_buffer = copy; comment = comment_buffer.c_str(); break; @@ -351,6 +450,27 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args, // Check for an append request. if (append) { + std::vector<std::string> unsupportedKeywordsUsed; + std::set_difference(keywordsSeen.begin(), keywordsSeen.end(), + supportedAppendKeywords.begin(), + supportedAppendKeywords.end(), + std::back_inserter(unsupportedKeywordsUsed)); + if (!unsupportedKeywordsUsed.empty()) { + std::string const msg = + cmJoin(unsupportedKeywordsUsed, ", "_s, + "The following keywords are not supported when using " + "APPEND with add_custom_command(OUTPUT): "_s); + if (cmp0175 == cmPolicies::NEW) { + mf.IssueMessage(MessageType::FATAL_ERROR, msg); + return false; + } + if (cmp0175 == cmPolicies::WARN) { + mf.IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat(msg, ".\n", + cmPolicies::GetPolicyWarning(cmPolicies::CMP0175))); + } + } mf.AppendCustomCommandToOutput(output[0], depends, implicit_depends, commandLines); return true; @@ -376,9 +496,92 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args, cc->SetDependsExplicitOnly(depends_explicit_only); if (source.empty() && output.empty()) { // Source is empty, use the target. + if (commandLines.empty()) { + std::string const msg = "At least one COMMAND must be given."; + if (cmp0175 == cmPolicies::NEW) { + mf.IssueMessage(MessageType::FATAL_ERROR, msg); + return false; + } + if (cmp0175 == cmPolicies::WARN) { + mf.IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat(msg, '\n', + cmPolicies::GetPolicyWarning(cmPolicies::CMP0175))); + } + } + + std::vector<std::string> unsupportedKeywordsUsed; + std::set_difference(keywordsSeen.begin(), keywordsSeen.end(), + supportedTargetKeywords.begin(), + supportedTargetKeywords.end(), + std::back_inserter(unsupportedKeywordsUsed)); + if (!unsupportedKeywordsUsed.empty()) { + std::string const msg = + cmJoin(unsupportedKeywordsUsed, ", "_s, + "The following keywords are not supported when using " + "add_custom_command(TARGET): "_s); + if (cmp0175 == cmPolicies::NEW) { + mf.IssueMessage(MessageType::FATAL_ERROR, msg); + return false; + } + if (cmp0175 == cmPolicies::WARN) { + mf.IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat(msg, ".\n", + cmPolicies::GetPolicyWarning(cmPolicies::CMP0175))); + } + } + auto const prePostCount = keywordsSeen.count(keyPRE_BUILD) + + keywordsSeen.count(keyPRE_LINK) + keywordsSeen.count(keyPOST_BUILD); + if (prePostCount != 1) { + std::string msg = + "Exactly one of PRE_BUILD, PRE_LINK, or POST_BUILD must be given."; + if (cmp0175 == cmPolicies::NEW) { + mf.IssueMessage(MessageType::FATAL_ERROR, msg); + return false; + } + if (cmp0175 == cmPolicies::WARN) { + msg += " Assuming "; + switch (cctype) { + case cmCustomCommandType::PRE_BUILD: + msg += "PRE_BUILD"; + break; + case cmCustomCommandType::PRE_LINK: + msg += "PRE_LINK"; + break; + case cmCustomCommandType::POST_BUILD: + msg += "POST_BUILD"; + } + mf.IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat(msg, " to preserve backward compatibility.\n", + cmPolicies::GetPolicyWarning(cmPolicies::CMP0175))); + } + } mf.AddCustomCommandToTarget(target, cctype, std::move(cc)); } else if (target.empty()) { // Target is empty, use the output. + std::vector<std::string> unsupportedKeywordsUsed; + std::set_difference(keywordsSeen.begin(), keywordsSeen.end(), + supportedOutputKeywords.begin(), + supportedOutputKeywords.end(), + std::back_inserter(unsupportedKeywordsUsed)); + if (!unsupportedKeywordsUsed.empty()) { + std::string const msg = + cmJoin(unsupportedKeywordsUsed, ", "_s, + "The following keywords are not supported when using " + "add_custom_command(OUTPUT): "_s); + if (cmp0175 == cmPolicies::NEW) { + mf.IssueMessage(MessageType::FATAL_ERROR, msg); + return false; + } + if (cmp0175 == cmPolicies::WARN) { + mf.IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat(msg, ".\n", + cmPolicies::GetPolicyWarning(cmPolicies::CMP0175))); + } + } cc->SetOutputs(output); cc->SetMainDependency(main_dependency); cc->SetDepends(depends); diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 7b056ae..644cb9e 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -537,6 +537,8 @@ class cmMakefile; SELECT(POLICY, CMP0174, \ "cmake_parse_arguments(PARSE_ARGV) defines a variable for an empty " \ "string after a single-value keyword.", \ + 3, 31, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0175, "add_custom_command() rejects invalid arguments.", \ 3, 31, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) diff --git a/Tests/RunCMake/add_custom_command/CMP0175-NEW-result.txt b/Tests/RunCMake/add_custom_command/CMP0175-NEW-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/add_custom_command/CMP0175-NEW-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/add_custom_command/CMP0175-NEW-stderr.txt b/Tests/RunCMake/add_custom_command/CMP0175-NEW-stderr.txt new file mode 100644 index 0000000..c356971 --- /dev/null +++ b/Tests/RunCMake/add_custom_command/CMP0175-NEW-stderr.txt @@ -0,0 +1,29 @@ +CMake Error at CMP0175\.cmake:[0-9]+ \(add_custom_command\): + The following keywords are not supported when using + add_custom_command\(TARGET\): DEPENDS, DEPENDS_EXPLICIT_ONLY, DEPFILE, + JOB_POOL, MAIN_DEPENDENCY +Call Stack \(most recent call first\): + CMP0175-NEW\.cmake:2 \(include\) + CMakeLists\.txt:3 \(include\) + + +CMake Error at CMP0175\.cmake:[0-9]+ \(add_custom_command\): + The following keywords are not supported when using + add_custom_command\(TARGET\): IMPLICIT_DEPENDS, USES_TERMINAL +Call Stack \(most recent call first\): + CMP0175-NEW\.cmake:2 \(include\) + CMakeLists\.txt:3 \(include\) + + +CMake Error at CMP0175\.cmake:[0-9]+ \(add_custom_command\): + Exactly one of PRE_BUILD, PRE_LINK, or POST_BUILD must be given\. +Call Stack \(most recent call first\): + CMP0175-NEW\.cmake:2 \(include\) + CMakeLists\.txt:3 \(include\) + + +CMake Error at CMP0175\.cmake:[0-9]+ \(add_custom_command\): + Exactly one of PRE_BUILD, PRE_LINK, or POST_BUILD must be given\. +Call Stack \(most recent call first\): + CMP0175-NEW\.cmake:2 \(include\) + CMakeLists\.txt:3 \(include\) diff --git a/Tests/RunCMake/add_custom_command/CMP0175-NEW.cmake b/Tests/RunCMake/add_custom_command/CMP0175-NEW.cmake new file mode 100644 index 0000000..d8cb4fb --- /dev/null +++ b/Tests/RunCMake/add_custom_command/CMP0175-NEW.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0175 NEW) +include(CMP0175.cmake) diff --git a/Tests/RunCMake/add_custom_command/CMP0175-OLD.cmake b/Tests/RunCMake/add_custom_command/CMP0175-OLD.cmake new file mode 100644 index 0000000..a66c02d --- /dev/null +++ b/Tests/RunCMake/add_custom_command/CMP0175-OLD.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0175 OLD) +include(CMP0175.cmake) diff --git a/Tests/RunCMake/add_custom_command/CMP0175-WARN-stderr.txt b/Tests/RunCMake/add_custom_command/CMP0175-WARN-stderr.txt new file mode 100644 index 0000000..f49dd73 --- /dev/null +++ b/Tests/RunCMake/add_custom_command/CMP0175-WARN-stderr.txt @@ -0,0 +1,72 @@ +CMake Warning \(dev\) at CMP0175\.cmake:[0-9]+ \(add_custom_command\): + The following keywords are not supported when using + add_custom_command\(TARGET\): DEPENDS, DEPENDS_EXPLICIT_ONLY, DEPFILE, + JOB_POOL, MAIN_DEPENDENCY\. + + Policy CMP0175 is not set: add_custom_command\(\) rejects invalid arguments\. + Run "cmake --help-policy CMP0175" for policy details\. Use the cmake_policy + command to set the policy and suppress this warning\. +Call Stack \(most recent call first\): + CMP0175-WARN\.cmake:1 \(include\) + CMakeLists.txt:3 \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\. + +CMake Warning \(dev\) at CMP0175\.cmake:[0-9]+ \(add_custom_command\): + The following keywords are not supported when using + add_custom_command\(TARGET\): IMPLICIT_DEPENDS, USES_TERMINAL\. + + Policy CMP0175 is not set: add_custom_command\(\) rejects invalid arguments\. + Run "cmake --help-policy CMP0175" for policy details\. Use the cmake_policy + command to set the policy and suppress this warning\. +Call Stack \(most recent call first\): + CMP0175-WARN\.cmake:1 \(include\) + CMakeLists\.txt:3 \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\. + +CMake Warning \(dev\) at CMP0175\.cmake:[0-9]+ \(add_custom_command\): + Exactly one of PRE_BUILD, PRE_LINK, or POST_BUILD must be given\. Assuming + POST_BUILD to preserve backward compatibility\. + + Policy CMP0175 is not set: add_custom_command\(\) rejects invalid arguments\. + Run "cmake --help-policy CMP0175" for policy details\. Use the cmake_policy + command to set the policy and suppress this warning\. +Call Stack \(most recent call first\): + CMP0175-WARN\.cmake:1 \(include\) + CMakeLists\.txt:3 \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\. + +CMake Warning \(dev\) at CMP0175\.cmake:[0-9]+ \(add_custom_command\): + Exactly one of PRE_BUILD, PRE_LINK, or POST_BUILD must be given\. Assuming + POST_BUILD to preserve backward compatibility\. + + Policy CMP0175 is not set: add_custom_command\(\) rejects invalid arguments\. + Run "cmake --help-policy CMP0175" for policy details\. Use the cmake_policy + command to set the policy and suppress this warning\. +Call Stack \(most recent call first\): + CMP0175-WARN\.cmake:1 \(include\) + CMakeLists\.txt:3 \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\. + +CMake Warning \(dev\) at CMP0175\.cmake:[0-9]+ \(add_custom_command\): + At least one COMMAND must be given\. + + Policy CMP0175 is not set: add_custom_command\(\) rejects invalid arguments\. + Run "cmake --help-policy CMP0175" for policy details\. Use the cmake_policy + command to set the policy and suppress this warning\. +Call Stack \(most recent call first\): + CMP0175-WARN\.cmake:1 \(include\) + CMakeLists\.txt:3 \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\. + +CMake Warning \(dev\) at CMP0175\.cmake:[0-9]+ \(add_custom_command\): + The following keywords are not supported when using + add_custom_command\(OUTPUT\): OUTPUTS, POST_BUILD, PRE_BUILD, PRE_LINK, + SOURCE\. + + Policy CMP0175 is not set: add_custom_command\(\) rejects invalid arguments\. + Run "cmake --help-policy CMP0175" for policy details\. Use the cmake_policy + command to set the policy and suppress this warning\. +Call Stack \(most recent call first\): + CMP0175-WARN\.cmake:1 \(include\) + CMakeLists\.txt:3 \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\. diff --git a/Tests/RunCMake/add_custom_command/CMP0175-WARN.cmake b/Tests/RunCMake/add_custom_command/CMP0175-WARN.cmake new file mode 100644 index 0000000..cd89b53 --- /dev/null +++ b/Tests/RunCMake/add_custom_command/CMP0175-WARN.cmake @@ -0,0 +1 @@ +include(CMP0175.cmake) diff --git a/Tests/RunCMake/add_custom_command/CMP0175.cmake b/Tests/RunCMake/add_custom_command/CMP0175.cmake new file mode 100644 index 0000000..0c20f4e --- /dev/null +++ b/Tests/RunCMake/add_custom_command/CMP0175.cmake @@ -0,0 +1,65 @@ +enable_language(CXX) +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/main.cpp "int main() {}") +add_executable(main ${CMAKE_CURRENT_BINARY_DIR}/main.cpp) + +#============================================================================ +# add_custom_command(TARGET) +#============================================================================ + +# Unsupported keywords. Need to test them in batches to avoid other checks. +add_custom_command(TARGET main + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E true + + # None of the following are allowed for the TARGET form + + #APPEND # Has its own check requiring OUTPUT to be set + #CODEGEN # Other checks will fail before the CMP0175 check + DEPENDS valueDoesNotMatterHere + DEPENDS_EXPLICIT_ONLY YES + DEPFILE valueDoesNotMatterHere + #IMPLICIT_DEPENDS # Earlier check fails when DEPFILE is present + JOB_POOL valueDoesNotMatterHere + MAIN_DEPENDENCY valueDoesNotMatterHere + #OUTPUT # Other checks will fail before the CMP0175 check + #OUTPUTS # Special case, not a documented keyword (used for deprecated form) + #SOURCE # Old signature, special handling makes it hard to check + #USES_TERMINAL +) +add_custom_command(TARGET main + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E true + # Has to be tested separately due to separate check for clash with DEPFILE + IMPLICIT_DEPENDS valueDoesNotMatterHere + # Has to be tested separately due to separate check for clash with JOB_POOL + USES_TERMINAL NO +) + +# Missing any PRE_BUILD, PRE_LINK, or POST_BUILD +add_custom_command(TARGET main + COMMAND ${CMAKE_COMMAND} -E true +) + +# More than one of PRE_BUILD, PRE_LINK, or POST_BUILD +add_custom_command(TARGET main + PRE_BUILD PRE_LINK POST_BUILD + COMMAND ${CMAKE_COMMAND} -E true +) + +# Missing COMMAND +add_custom_command(TARGET main + POST_BUILD + COMMENT "Need at least 4 arguments, so added this comment" +) + +#============================================================================ +# add_custom_command(OUTPUT) +#============================================================================ + +add_custom_command(OUTPUT blah.txt + OUTPUTS + POST_BUILD + PRE_BUILD + PRE_LINK + SOURCE +) diff --git a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake index 46e7bae..820591c 100644 --- a/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake +++ b/Tests/RunCMake/add_custom_command/RunCMakeTest.cmake @@ -1,5 +1,8 @@ include(RunCMake) +run_cmake(CMP0175-OLD) +run_cmake(CMP0175-WARN) +run_cmake(CMP0175-NEW) run_cmake(AppendLiteralQuotes) run_cmake(AppendNoOutput) run_cmake(AppendNotOutput) |