diff options
27 files changed, 561 insertions, 425 deletions
diff --git a/Help/command/message.rst b/Help/command/message.rst index 5dca6b4..3002842 100644 --- a/Help/command/message.rst +++ b/Help/command/message.rst @@ -60,6 +60,11 @@ messages one at a time on a status line and other messages in an interactive pop-up box. The ``--loglevel`` command-line option to each of these tools can be used to control which messages will be shown. +Messages of log levels ``NOTICE`` and below will also have each line preceded +by the content of the :variable:`CMAKE_MESSAGE_INDENT` variable (converted to +a single string by concatenating its list items). For ``STATUS`` to ``TRACE`` +messages, this indenting content will be inserted after the hyphens. + CMake Warning and Error message text displays using a simple markup language. Non-indented text is formatted in line-wrapped paragraphs delimited by newlines. Indented text is considered pre-formatted. diff --git a/Help/command/string.rst b/Help/command/string.rst index 2e89d7b..81a2061 100644 --- a/Help/command/string.rst +++ b/Help/command/string.rst @@ -22,8 +22,8 @@ Synopsis string(`PREPEND`_ <string-var> [<input>...]) string(`CONCAT`_ <out-var> [<input>...]) string(`JOIN`_ <glue> <out-var> [<input>...]) - string(`TOLOWER`_ <string1> <out-var>) - string(`TOUPPER`_ <string1> <out-var>) + string(`TOLOWER`_ <string> <out-var>) + string(`TOUPPER`_ <string> <out-var>) string(`LENGTH`_ <string> <out-var>) string(`SUBSTRING`_ <string> <begin> <length> <out-var>) string(`STRIP`_ <string> <out-var>) @@ -38,7 +38,7 @@ Synopsis `Generation`_ string(`ASCII`_ <number>... <out-var>) - string(`CONFIGURE`_ <string1> <out-var> [...]) + string(`CONFIGURE`_ <string> <out-var> [...]) string(`MAKE_C_IDENTIFIER`_ <string> <out-var>) string(`RANDOM`_ [<option>...] <out-var>) string(`TIMESTAMP`_ <out-var> [<format string>] [UTC]) @@ -51,23 +51,28 @@ Search and Replace .. code-block:: cmake - string(FIND <string> <substring> <output variable> [REVERSE]) + string(FIND <string> <substring> <output_variable> [REVERSE]) -Return the position where the given substring was found in -the supplied string. If the ``REVERSE`` flag was used, the command will +Return the position where the given ``<substring>`` was found in +the supplied ``<string>``. If the ``REVERSE`` flag was used, the command will search for the position of the last occurrence of the specified -substring. If the substring is not found, a position of -1 is returned. +``<substring>``. If the ``<substring>`` is not found, a position of -1 is +returned. + +The ``string(FIND)`` subcommand treats all strings as ASCII-only characters. +The index stored in ``<output_variable>`` will also be counted in bytes, +so strings containing multi-byte characters may lead to unexpected results. .. _REPLACE: .. code-block:: cmake string(REPLACE <match_string> - <replace_string> <output variable> + <replace_string> <output_variable> <input> [<input>...]) -Replace all occurrences of ``match_string`` in the input -with ``replace_string`` and store the result in the output. +Replace all occurrences of ``<match_string>`` in the ``<input>`` +with ``<replace_string>`` and store the result in the ``<output_variable>``. Regular Expressions ^^^^^^^^^^^^^^^^^^^ @@ -77,9 +82,10 @@ Regular Expressions .. code-block:: cmake string(REGEX MATCH <regular_expression> - <output variable> <input> [<input>...]) + <output_variable> <input> [<input>...]) -Match the regular expression once and store the match in the output variable. +Match the ``<regular_expression>`` once and store the match in the +``<output_variable>``. All ``<input>`` arguments are concatenated before matching. .. _`REGEX MATCHALL`: @@ -87,10 +93,10 @@ All ``<input>`` arguments are concatenated before matching. .. code-block:: cmake string(REGEX MATCHALL <regular_expression> - <output variable> <input> [<input>...]) + <output_variable> <input> [<input>...]) -Match the regular expression as many times as possible and store the matches -in the output variable as a list. +Match the ``<regular_expression>`` as many times as possible and store the +matches in the ``<output_variable>`` as a list. All ``<input>`` arguments are concatenated before matching. .. _`REGEX REPLACE`: @@ -98,16 +104,17 @@ All ``<input>`` arguments are concatenated before matching. .. code-block:: cmake string(REGEX REPLACE <regular_expression> - <replace_expression> <output variable> + <replacement_expression> <output_variable> <input> [<input>...]) -Match the regular expression as many times as possible and substitute the -replacement expression for the match in the output. +Match the ``<regular_expression>`` as many times as possible and substitute +the ``<replacement_expression>`` for the match in the output. All ``<input>`` arguments are concatenated before matching. -The replace expression may refer to paren-delimited subexpressions of the -match using ``\1``, ``\2``, ..., ``\9``. Note that two backslashes (``\\1``) -are required in CMake code to get a backslash through argument parsing. +The ``<replacement_expression>`` may refer to parenthesis-delimited +subexpressions of the match using ``\1``, ``\2``, ..., ``\9``. Note that +two backslashes (``\\1``) are required in CMake code to get a backslash +through argument parsing. .. _`Regex Specification`: @@ -180,103 +187,109 @@ Manipulation .. code-block:: cmake - string(APPEND <string variable> [<input>...]) + string(APPEND <string_variable> [<input>...]) -Append all the input arguments to the string. +Append all the ``<input>`` arguments to the string. .. _PREPEND: .. code-block:: cmake - string(PREPEND <string variable> [<input>...]) + string(PREPEND <string_variable> [<input>...]) -Prepend all the input arguments to the string. +Prepend all the ``<input>`` arguments to the string. .. _CONCAT: .. code-block:: cmake - string(CONCAT <output variable> [<input>...]) + string(CONCAT <output_variable> [<input>...]) -Concatenate all the input arguments together and store -the result in the named output variable. +Concatenate all the ``<input>`` arguments together and store +the result in the named ``<output_variable>``. .. _JOIN: .. code-block:: cmake - string(JOIN <glue> <output variable> [<input>...]) + string(JOIN <glue> <output_variable> [<input>...]) -Join all the input arguments together using the glue -string and store the result in the named output variable. +Join all the ``<input>`` arguments together using the ``<glue>`` +string and store the result in the named ``<output_variable>``. -To join list's elements, use preferably the ``JOIN`` operator -from :command:`list` command. This allows for the elements to have +To join a list's elements, prefer to use the ``JOIN`` operator +from the :command:`list` command. This allows for the elements to have special characters like ``;`` in them. .. _TOLOWER: .. code-block:: cmake - string(TOLOWER <string1> <output variable>) + string(TOLOWER <string> <output_variable>) -Convert string to lower characters. +Convert ``<string>`` to lower characters. .. _TOUPPER: .. code-block:: cmake - string(TOUPPER <string1> <output variable>) + string(TOUPPER <string> <output_variable>) -Convert string to upper characters. +Convert ``<string>`` to upper characters. .. _LENGTH: .. code-block:: cmake - string(LENGTH <string> <output variable>) + string(LENGTH <string> <output_variable>) -Store in an output variable a given string's length. +Store in an ``<output_variable>`` a given string's length in bytes. +Note that this means if ``<string>`` contains multi-byte characters, the +result stored in ``<output_variable>`` will *not* be the number of characters. .. _SUBSTRING: .. code-block:: cmake - string(SUBSTRING <string> <begin> <length> <output variable>) + string(SUBSTRING <string> <begin> <length> <output_variable>) + +Store in an ``<output_variable>`` a substring of a given ``<string>``. If +``<length>`` is ``-1`` the remainder of the string starting at ``<begin>`` +will be returned. If ``<string>`` is shorter than ``<length>`` then the +end of the string is used instead. -Store in an output variable a substring of a given string. If length is -``-1`` the remainder of the string starting at begin will be returned. -If string is shorter than length then end of string is used instead. +Both ``<begin>`` and ``<length>`` are counted in bytes, so care must +be exercised if ``<string>`` could contain multi-byte characters. .. note:: - CMake 3.1 and below reported an error if length pointed past - the end of string. + CMake 3.1 and below reported an error if ``<length>`` pointed past + the end of ``<string>``. .. _STRIP: .. code-block:: cmake - string(STRIP <string> <output variable>) + string(STRIP <string> <output_variable>) -Store in an output variable a substring of a given string with leading and -trailing spaces removed. +Store in an ``<output_variable>`` a substring of a given ``<string>`` with +leading and trailing spaces removed. .. _GENEX_STRIP: .. code-block:: cmake - string(GENEX_STRIP <input string> <output variable>) + string(GENEX_STRIP <string> <output_variable>) Strip any :manual:`generator expressions <cmake-generator-expressions(7)>` -from the ``input string`` and store the result in the ``output variable``. +from the input ``<string>`` and store the result in the ``<output_variable>``. .. _REPEAT: .. code-block:: cmake - string(REPEAT <input string> <count> <output variable>) + string(REPEAT <string> <count> <output_variable>) -Produce the output string as repetion of ``input string`` ``count`` times. +Produce the output string as the input ``<string>`` repeated ``<count>`` times. Comparison ^^^^^^^^^^ @@ -285,14 +298,14 @@ Comparison .. code-block:: cmake - string(COMPARE LESS <string1> <string2> <output variable>) - string(COMPARE GREATER <string1> <string2> <output variable>) - string(COMPARE EQUAL <string1> <string2> <output variable>) - string(COMPARE NOTEQUAL <string1> <string2> <output variable>) - string(COMPARE LESS_EQUAL <string1> <string2> <output variable>) - string(COMPARE GREATER_EQUAL <string1> <string2> <output variable>) + string(COMPARE LESS <string1> <string2> <output_variable>) + string(COMPARE GREATER <string1> <string2> <output_variable>) + string(COMPARE EQUAL <string1> <string2> <output_variable>) + string(COMPARE NOTEQUAL <string1> <string2> <output_variable>) + string(COMPARE LESS_EQUAL <string1> <string2> <output_variable>) + string(COMPARE GREATER_EQUAL <string1> <string2> <output_variable>) -Compare the strings and store true or false in the output variable. +Compare the strings and store true or false in the ``<output_variable>``. .. _`Supported Hash Algorithms`: @@ -303,9 +316,9 @@ Hashing .. code-block:: cmake - string(<HASH> <output variable> <input>) + string(<HASH> <output_variable> <input>) -Compute a cryptographic hash of the input string. +Compute a cryptographic hash of the ``<input>`` string. The supported ``<HASH>`` algorithm names are: ``MD5`` @@ -336,7 +349,7 @@ Generation .. code-block:: cmake - string(ASCII <number> [<number> ...] <output variable>) + string(ASCII <number> [<number> ...] <output_variable>) Convert all numbers into corresponding ASCII characters. @@ -344,31 +357,31 @@ Convert all numbers into corresponding ASCII characters. .. code-block:: cmake - string(CONFIGURE <string1> <output variable> + string(CONFIGURE <string> <output_variable> [@ONLY] [ESCAPE_QUOTES]) -Transform a string like :command:`configure_file` transforms a file. +Transform a ``<string>`` like :command:`configure_file` transforms a file. .. _MAKE_C_IDENTIFIER: .. code-block:: cmake - string(MAKE_C_IDENTIFIER <input string> <output variable>) + string(MAKE_C_IDENTIFIER <string> <output_variable>) -Convert each non-alphanumeric character in the ``<input string>`` to an -underscore and store the result in the ``<output variable>``. If the first -character of the string is a digit, an underscore will also be prepended to -the result. +Convert each non-alphanumeric character in the input ``<string>`` to an +underscore and store the result in the ``<output_variable>``. If the first +character of the ``<string>`` is a digit, an underscore will also be prepended +to the result. .. _RANDOM: .. code-block:: cmake string(RANDOM [LENGTH <length>] [ALPHABET <alphabet>] - [RANDOM_SEED <seed>] <output variable>) + [RANDOM_SEED <seed>] <output_variable>) -Return a random string of given length consisting of -characters from the given alphabet. Default length is 5 characters +Return a random string of given ``<length>`` consisting of +characters from the given ``<alphabet>``. Default length is 5 characters and default alphabet is all numbers and upper and lower case letters. If an integer ``RANDOM_SEED`` is given, its value will be used to seed the random number generator. @@ -377,18 +390,18 @@ random number generator. .. code-block:: cmake - string(TIMESTAMP <output variable> [<format string>] [UTC]) + string(TIMESTAMP <output_variable> [<format_string>] [UTC]) Write a string representation of the current date -and/or time to the output variable. +and/or time to the ``<output_variable>``. -Should the command be unable to obtain a timestamp the output variable -will be set to the empty string "". +If the command is unable to obtain a timestamp, the ``<output_variable>`` +will be set to the empty string ``""``. The optional ``UTC`` flag requests the current date/time representation to be in Coordinated Universal Time (UTC) rather than local time. -The optional ``<format string>`` may contain the following format +The optional ``<format_string>`` may contain the following format specifiers: :: @@ -415,7 +428,7 @@ specifiers: Unknown format specifiers will be ignored and copied to the output as-is. -If no explicit ``<format string>`` is given it will default to: +If no explicit ``<format_string>`` is given, it will default to: :: @@ -432,7 +445,7 @@ If no explicit ``<format string>`` is given it will default to: .. code-block:: cmake - string(UUID <output variable> NAMESPACE <namespace> NAME <name> + string(UUID <output_variable> NAMESPACE <namespace> NAME <name> TYPE <MD5|SHA1> [UPPER]) Create a universally unique identifier (aka GUID) as per RFC4122 @@ -441,6 +454,6 @@ based on the hash of the combined values of ``<namespace>`` The hash algorithm can be either ``MD5`` (Version 3 UUID) or ``SHA1`` (Version 5 UUID). A UUID has the format ``xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`` -where each `x` represents a lower case hexadecimal character. -Where required an uppercase representation can be requested +where each ``x`` represents a lower case hexadecimal character. +Where required, an uppercase representation can be requested with the optional ``UPPER`` flag. diff --git a/Help/guide/tutorial/index.rst b/Help/guide/tutorial/index.rst index db8e7a0..41ed0c4 100644 --- a/Help/guide/tutorial/index.rst +++ b/Help/guide/tutorial/index.rst @@ -228,7 +228,8 @@ remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level CMakeLists. Once this is done, run **cmake** or **cmake-gui** to configure the project -and then build it with your chosen build tool. +and then build it with your chosen build tool or by using ``cmake --build .`` +from the build directory. Installing and Testing (Step 4) =============================== @@ -258,14 +259,15 @@ And the to top-level ``CMakeLists.txt`` we add: That is all that is needed to create a basic local install of the tutorial. Run **cmake** or **cmake-gui** to configure the project and then build it -with your chosen build tool. Build the ``install`` target by typing -``make install`` from the command line or build the ``INSTALL`` target from -an IDE. This will install the appropriate header files, libraries, and -executables. +with your chosen build tool. Run the install step by typing +``cmake --install .`` or from the command line, or build the ``INSTALL`` +target from an IDE. This will install the appropriate header files, libraries, +and executables. Verify that the installed Tutorial runs. Note: The CMake variable ``CMAKE_INSTALL_PREFIX`` is used to determine the root of where the files will -be installed. +be installed. If using ``cmake --install`` a custom installation directory can +be given via ``--prefix`` argument. Testing Support --------------- diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index e0ce6f7..c3f6f8a 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -69,6 +69,7 @@ Variables that Provide Information /variable/CMAKE_MAKE_PROGRAM /variable/CMAKE_MATCH_COUNT /variable/CMAKE_MATCH_n + /variable/CMAKE_MESSAGE_INDENT /variable/CMAKE_MINIMUM_REQUIRED_VERSION /variable/CMAKE_MINOR_VERSION /variable/CMAKE_NETRC @@ -609,7 +610,6 @@ Variables for CPack /variable/CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION /variable/CPACK_INCLUDE_TOPLEVEL_DIRECTORY /variable/CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS - /variable/CPACK_INSTALL_SCRIPT /variable/CPACK_PACKAGING_INSTALL_PREFIX /variable/CPACK_SET_DESTDIR /variable/CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION diff --git a/Help/release/dev/cpack-install-scripts.rst b/Help/release/dev/cpack-install-scripts.rst new file mode 100644 index 0000000..7b80d33 --- /dev/null +++ b/Help/release/dev/cpack-install-scripts.rst @@ -0,0 +1,5 @@ +cpack-install-scripts +--------------------- + +* The ``CPACK_INSTALL_SCRIPT`` variable has been deprecated in favor of the + new, more accurately named :variable:`CPACK_INSTALL_SCRIPTS` variable. diff --git a/Help/release/dev/message-indent.rst b/Help/release/dev/message-indent.rst new file mode 100644 index 0000000..b170708 --- /dev/null +++ b/Help/release/dev/message-indent.rst @@ -0,0 +1,5 @@ +message-indent +-------------- + +* The :command:`message` command learned indentation control with the new + :variable:`CMAKE_MESSAGE_INDENT` variable. diff --git a/Help/variable/CMAKE_MESSAGE_INDENT.rst b/Help/variable/CMAKE_MESSAGE_INDENT.rst new file mode 100644 index 0000000..f7975ab --- /dev/null +++ b/Help/variable/CMAKE_MESSAGE_INDENT.rst @@ -0,0 +1,30 @@ +CMAKE_MESSAGE_INDENT +-------------------- + +The :command:`message` command joins the strings from this list and for +log levels of ``NOTICE`` and below, it prepends the resultant string to +each line of the message. + +Example: + +.. code-block:: cmake + + list(APPEND listVar one two three) + + message(VERBOSE [[Collected items in the "listVar":]]) + list(APPEND CMAKE_MESSAGE_INDENT " ") + + foreach(item IN LISTS listVar) + message(VERBOSE ${item}) + endforeach() + + list(POP_BACK CMAKE_MESSAGE_INDENT) + message(VERBOSE "No more indent") + +Which results in the following output: + + -- Collected items in the "listVar": + -- one + -- two + -- tree + -- No more indent diff --git a/Help/variable/CPACK_INSTALL_SCRIPT.rst b/Help/variable/CPACK_INSTALL_SCRIPT.rst deleted file mode 100644 index 12a48a4..0000000 --- a/Help/variable/CPACK_INSTALL_SCRIPT.rst +++ /dev/null @@ -1,8 +0,0 @@ -CPACK_INSTALL_SCRIPT --------------------- - -Extra CMake script provided by the user. - -If set this CMake script will be executed by CPack during its local -[CPack-private] installation which is done right before packaging the -files. The script is not called by e.g.: ``make install``. diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index c9008db..8a6a712 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -325,7 +325,21 @@ The following variables are for advanced uses of CPack: .. variable:: CPACK_INSTALL_COMMANDS - Extra commands to install components. + Extra commands to install components. The environment variable + ``CMAKE_INSTALL_PREFIX`` is set to the temporary install directory + during execution. + +.. variable:: CPACK_INSTALL_SCRIPTS + + Extra CMake scripts executed by CPack during its local staging + installation, which is done right before packaging the files. + The scripts are not called by a standalone install (e.g.: ``make install``). + For every script, the following variables will be set: + :variable:`CMAKE_CURRENT_SOURCE_DIR`, :variable:`CMAKE_CURRENT_BINARY_DIR` + and :variable:`CMAKE_INSTALL_PREFIX` (which is set to the staging install + directory). The singular form ``CMAKE_INSTALL_SCRIPT`` is supported as + an alternative variable for historical reasons, but its value is ignored if + ``CMAKE_INSTALL_SCRIPTS`` is set and a warning will be issued. .. variable:: CPACK_INSTALLED_DIRECTORIES diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index cf21839..f0084cd 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 15) -set(CMake_VERSION_PATCH 20190719) +set(CMake_VERSION_PATCH 20190722) #set(CMake_VERSION_RC 1) diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 4a91698..350ebed 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -235,7 +235,7 @@ int cmCPackGenerator::InstallProject() return 0; } - // If the CPackConfig file sets CPACK_INSTALL_SCRIPT then run them + // If the CPackConfig file sets CPACK_INSTALL_SCRIPT(S) then run them // as listed if (!this->InstallProjectViaInstallScript(setDestDir, tempInstallDirectory)) { @@ -448,7 +448,19 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( int cmCPackGenerator::InstallProjectViaInstallScript( bool setDestDir, const std::string& tempInstallDirectory) { - const char* cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPT"); + const char* cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPTS"); + { + const char* const cmakeScript = this->GetOption("CPACK_INSTALL_SCRIPT"); + if (cmakeScript && cmakeScripts) { + cmCPackLogger( + cmCPackLog::LOG_WARNING, + "Both CPACK_INSTALL_SCRIPTS and CPACK_INSTALL_SCRIPT are set, " + "the latter will be ignored." + << std::endl); + } else if (cmakeScript && !cmakeScripts) { + cmakeScripts = cmakeScript; + } + } if (cmakeScripts && *cmakeScripts) { cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Install scripts: " << cmakeScripts << std::endl); diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 728f2a4..817f41e 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -68,9 +68,7 @@ void cmGeneratorExpressionDAGChecker::Initialize() return; } } - const_cast<cmGeneratorExpressionDAGChecker*>(top) - ->Seen[this->Target] - .insert(this->Property); + top->Seen[this->Target].insert(this->Property); } } diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index e1fba5e..6d7d6ef 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -88,7 +88,7 @@ private: const cmGeneratorExpressionDAGChecker* const Parent; cmGeneratorTarget const* Target; const std::string Property; - std::map<cmGeneratorTarget const*, std::set<std::string>> Seen; + mutable std::map<cmGeneratorTarget const*, std::set<std::string>> Seen; const GeneratorExpressionContent* const Content; const cmListFileBacktrace Backtrace; Result CheckResult; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index d3e8248..6e6c917 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -92,9 +92,6 @@ public: virtual bool GetHadContextSensitiveCondition() const { return false; } cmLinkImplItem const& LinkImplItem; - -private: - cmListFileBacktrace Backtrace; }; cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem; @@ -209,6 +206,63 @@ void CreatePropertyGeneratorExpressions( } } +namespace { +// Represent a target property entry after evaluating generator expressions +// and splitting up lists. +struct EvaluatedTargetPropertyEntry +{ + EvaluatedTargetPropertyEntry(cmLinkImplItem const& item, + cmListFileBacktrace bt) + : LinkImplItem(item) + , Backtrace(std::move(bt)) + { + } + + // Move-only. + EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry&&) = default; + EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry const&) = delete; + EvaluatedTargetPropertyEntry& operator=(EvaluatedTargetPropertyEntry&&) = + delete; + EvaluatedTargetPropertyEntry& operator=( + EvaluatedTargetPropertyEntry const&) = delete; + + cmLinkImplItem const& LinkImplItem; + cmListFileBacktrace Backtrace; + std::vector<std::string> Values; + bool ContextDependent = false; +}; + +EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry( + cmGeneratorTarget const* thisTarget, std::string const& config, + std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker, + cmGeneratorTarget::TargetPropertyEntry* entry) +{ + EvaluatedTargetPropertyEntry ee(entry->LinkImplItem, entry->GetBacktrace()); + cmSystemTools::ExpandListArgument( + entry->Evaluate(thisTarget->GetLocalGenerator(), config, false, thisTarget, + dagChecker, lang), + ee.Values); + if (entry->GetHadContextSensitiveCondition()) { + ee.ContextDependent = true; + } + return ee; +} + +std::vector<EvaluatedTargetPropertyEntry> EvaluateTargetPropertyEntries( + cmGeneratorTarget const* thisTarget, std::string const& config, + std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker, + std::vector<cmGeneratorTarget::TargetPropertyEntry*> const& in) +{ + std::vector<EvaluatedTargetPropertyEntry> out; + out.reserve(in.size()); + for (cmGeneratorTarget::TargetPropertyEntry* entry : in) { + out.emplace_back(EvaluateTargetPropertyEntry(thisTarget, config, lang, + dagChecker, entry)); + } + return out; +} +} + cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) : Target(t) , FortranModuleDirectoryCreated(false) @@ -654,12 +708,14 @@ std::vector<cmSourceFile*> const* cmGeneratorTarget::GetSourceDepends( return nullptr; } -static void handleSystemIncludesDep( - cmLocalGenerator* lg, cmGeneratorTarget const* depTgt, - const std::string& config, cmGeneratorTarget const* headTarget, - cmGeneratorExpressionDAGChecker* dagChecker, - std::vector<std::string>& result, bool excludeImported, - std::string const& language) +namespace { +void handleSystemIncludesDep(cmLocalGenerator* lg, + cmGeneratorTarget const* depTgt, + const std::string& config, + cmGeneratorTarget const* headTarget, + cmGeneratorExpressionDAGChecker* dagChecker, + std::vector<std::string>& result, + bool excludeImported, std::string const& language) { if (const char* dirs = depTgt->GetProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES")) { @@ -682,6 +738,7 @@ static void handleSystemIncludesDep( result); } } +} /* clang-format off */ #define IMPLEMENT_VISIT(KIND) \ @@ -1084,77 +1141,91 @@ bool cmGeneratorTarget::GetPropertyAsBool(const std::string& prop) const return this->Target->GetPropertyAsBool(prop); } -static void AddInterfaceEntries( - cmGeneratorTarget const* thisTarget, std::string const& config, - std::string const& prop, - std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries) +namespace { +void AddInterfaceEntries(cmGeneratorTarget const* headTarget, + std::string const& config, std::string const& prop, + std::string const& lang, + cmGeneratorExpressionDAGChecker* dagChecker, + std::vector<EvaluatedTargetPropertyEntry>& entries) { if (cmLinkImplementationLibraries const* impl = - thisTarget->GetLinkImplementationLibraries(config)) { + headTarget->GetLinkImplementationLibraries(config)) { for (cmLinkImplItem const& lib : impl->Libraries) { if (lib.Target) { std::string uniqueName = - thisTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely( + headTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely( lib.Target); std::string genex = "$<TARGET_PROPERTY:" + std::move(uniqueName) + "," + prop + ">"; cmGeneratorExpression ge(lib.Backtrace); std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex); cge->SetEvaluateForBuildsystem(true); - entries.push_back(new TargetPropertyEntryGenex(std::move(cge), lib)); + + EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace); + cmSystemTools::ExpandListArgument( + cge->Evaluate(headTarget->GetLocalGenerator(), config, false, + headTarget, dagChecker, lang), + ee.Values); + if (cge->GetHadContextSensitiveCondition()) { + ee.ContextDependent = true; + } + entries.emplace_back(std::move(ee)); } } } } -static void AddObjectEntries( - cmGeneratorTarget const* thisTarget, std::string const& config, - std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries) +void AddObjectEntries(cmGeneratorTarget const* headTarget, + std::string const& config, + cmGeneratorExpressionDAGChecker* dagChecker, + std::vector<EvaluatedTargetPropertyEntry>& entries) { if (cmLinkImplementationLibraries const* impl = - thisTarget->GetLinkImplementationLibraries(config)) { + headTarget->GetLinkImplementationLibraries(config)) { for (cmLinkImplItem const& lib : impl->Libraries) { if (lib.Target && lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) { std::string uniqueName = - thisTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely( + headTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely( lib.Target); std::string genex = "$<TARGET_OBJECTS:" + std::move(uniqueName) + ">"; cmGeneratorExpression ge(lib.Backtrace); std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex); cge->SetEvaluateForBuildsystem(true); - entries.push_back(new TargetPropertyEntryGenex(std::move(cge), lib)); + + EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace); + cmSystemTools::ExpandListArgument( + cge->Evaluate(headTarget->GetLocalGenerator(), config, false, + headTarget, dagChecker), + ee.Values); + if (cge->GetHadContextSensitiveCondition()) { + ee.ContextDependent = true; + } + entries.emplace_back(std::move(ee)); } } } } -static bool processSources( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& srcs, - std::unordered_set<std::string>& uniqueSrcs, - cmGeneratorExpressionDAGChecker* dagChecker, std::string const& config, - bool debugSources) +bool processSources(cmGeneratorTarget const* tgt, + std::vector<EvaluatedTargetPropertyEntry>& entries, + std::vector<BT<std::string>>& srcs, + std::unordered_set<std::string>& uniqueSrcs, + bool debugSources) { cmMakefile* mf = tgt->Target->GetMakefile(); bool contextDependent = false; - for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) { - cmLinkImplItem const& item = entry->LinkImplItem; - std::string const& targetName = item.AsStr(); - std::vector<std::string> entrySources; - cmSystemTools::ExpandListArgument(entry->Evaluate(tgt->GetLocalGenerator(), - config, false, tgt, tgt, - dagChecker), - entrySources); - - if (entry->GetHadContextSensitiveCondition()) { + for (EvaluatedTargetPropertyEntry& entry : entries) { + if (entry.ContextDependent) { contextDependent = true; } - for (std::string& src : entrySources) { + cmLinkImplItem const& item = entry.LinkImplItem; + std::string const& targetName = item.AsStr(); + + for (std::string& src : entry.Values) { cmSourceFile* sf = mf->GetOrCreateSource(src); std::string e; std::string fullPath = sf->GetFullPath(&e); @@ -1183,9 +1254,9 @@ static bool processSources( src = fullPath; } std::string usedSources; - for (std::string const& src : entrySources) { + for (std::string const& src : entry.Values) { if (uniqueSrcs.insert(src).second) { - srcs.emplace_back(src, entry->GetBacktrace()); + srcs.emplace_back(src, entry.Backtrace); if (debugSources) { usedSources += " * " + src + "\n"; } @@ -1196,11 +1267,12 @@ static bool processSources( MessageType::LOG, std::string("Used sources for target ") + tgt->GetName() + ":\n" + usedSources, - entry->GetBacktrace()); + entry.Backtrace); } } return contextDependent; } +} std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( std::string const& config) const @@ -1248,28 +1320,28 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( cmGeneratorExpressionDAGChecker dagChecker(this, "SOURCES", nullptr, nullptr); + std::vector<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, std::string(), &dagChecker, + this->SourceEntries); + std::unordered_set<std::string> uniqueSrcs; bool contextDependentDirectSources = - processSources(this, this->SourceEntries, files, uniqueSrcs, &dagChecker, - config, debugSources); + processSources(this, entries, files, uniqueSrcs, debugSources); // Collect INTERFACE_SOURCES of all direct link-dependencies. - std::vector<cmGeneratorTarget::TargetPropertyEntry*> - linkInterfaceSourcesEntries; - AddInterfaceEntries(this, config, "INTERFACE_SOURCES", - linkInterfaceSourcesEntries); + std::vector<EvaluatedTargetPropertyEntry> linkInterfaceSourcesEntries; + AddInterfaceEntries(this, config, "INTERFACE_SOURCES", std::string(), + &dagChecker, linkInterfaceSourcesEntries); std::vector<std::string>::size_type numFilesBefore = files.size(); - bool contextDependentInterfaceSources = - processSources(this, linkInterfaceSourcesEntries, files, uniqueSrcs, - &dagChecker, config, debugSources); + bool contextDependentInterfaceSources = processSources( + this, linkInterfaceSourcesEntries, files, uniqueSrcs, debugSources); // Collect TARGET_OBJECTS of direct object link-dependencies. - std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkObjectsEntries; - AddObjectEntries(this, config, linkObjectsEntries); + std::vector<EvaluatedTargetPropertyEntry> linkObjectsEntries; + AddObjectEntries(this, config, &dagChecker, linkObjectsEntries); std::vector<std::string>::size_type numFilesBefore2 = files.size(); bool contextDependentObjects = - processSources(this, linkObjectsEntries, files, uniqueSrcs, &dagChecker, - config, debugSources); + processSources(this, linkObjectsEntries, files, uniqueSrcs, debugSources); if (!contextDependentDirectSources && !(contextDependentInterfaceSources && numFilesBefore < files.size()) && @@ -1277,8 +1349,6 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( this->LinkImplementationLanguageIsContextDependent = false; } - cmDeleteAll(linkInterfaceSourcesEntries); - cmDeleteAll(linkObjectsEntries); return files; } @@ -1855,16 +1925,17 @@ std::string cmGeneratorTarget::GetSOName(const std::string& config) const return this->GetLibraryNames(config).SharedObject; } -static bool shouldAddFullLevel(cmGeneratorTarget::BundleDirectoryLevel level) +namespace { +bool shouldAddFullLevel(cmGeneratorTarget::BundleDirectoryLevel level) { return level == cmGeneratorTarget::FullLevel; } -static bool shouldAddContentLevel( - cmGeneratorTarget::BundleDirectoryLevel level) +bool shouldAddContentLevel(cmGeneratorTarget::BundleDirectoryLevel level) { return level == cmGeneratorTarget::ContentLevel || shouldAddFullLevel(level); } +} std::string cmGeneratorTarget::GetAppBundleDirectory( const std::string& config, BundleDirectoryLevel level) const @@ -2767,27 +2838,22 @@ std::string cmGeneratorTarget::GetCreateRuleVariable( } return ""; } -static void processIncludeDirectories( + +namespace { +void processIncludeDirectories( cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, + std::vector<EvaluatedTargetPropertyEntry>& entries, std::vector<BT<std::string>>& includes, - std::unordered_set<std::string>& uniqueIncludes, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - bool debugIncludes, const std::string& language) + std::unordered_set<std::string>& uniqueIncludes, bool debugIncludes) { - for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) { - cmLinkImplItem const& item = entry->LinkImplItem; + for (EvaluatedTargetPropertyEntry& entry : entries) { + cmLinkImplItem const& item = entry.LinkImplItem; std::string const& targetName = item.AsStr(); bool const fromImported = item.Target && item.Target->IsImported(); bool const checkCMP0027 = item.FromGenex; - std::vector<std::string> entryIncludes; - cmSystemTools::ExpandListArgument(entry->Evaluate(tgt->GetLocalGenerator(), - config, false, tgt, - dagChecker, language), - entryIncludes); std::string usedIncludes; - for (std::string& entryInclude : entryIncludes) { + for (std::string& entryInclude : entry.Values) { if (fromImported && !cmSystemTools::FileExists(entryInclude)) { std::ostringstream e; MessageType messageType = MessageType::FATAL_ERROR; @@ -2859,12 +2925,11 @@ static void processIncludeDirectories( if (!cmSystemTools::IsOff(entryInclude)) { cmSystemTools::ConvertToUnixSlashes(entryInclude); } - std::string inc = entryInclude; - if (uniqueIncludes.insert(inc).second) { - includes.emplace_back(inc, entry->GetBacktrace()); + if (uniqueIncludes.insert(entryInclude).second) { + includes.emplace_back(entryInclude, entry.Backtrace); if (debugIncludes) { - usedIncludes += " * " + inc + "\n"; + usedIncludes += " * " + entryInclude + "\n"; } } } @@ -2873,10 +2938,11 @@ static void processIncludeDirectories( MessageType::LOG, std::string("Used includes for target ") + tgt->GetName() + ":\n" + usedIncludes, - entry->GetBacktrace()); + entry.Backtrace); } } } +} std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( const std::string& config, const std::string& lang) const @@ -2902,14 +2968,12 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( this->DebugIncludesDone = true; } - processIncludeDirectories(this, this->IncludeDirectoriesEntries, includes, - uniqueIncludes, &dagChecker, config, debugIncludes, - lang); + std::vector<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, lang, &dagChecker, + this->IncludeDirectoriesEntries); - std::vector<cmGeneratorTarget::TargetPropertyEntry*> - linkInterfaceIncludeDirectoriesEntries; - AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES", - linkInterfaceIncludeDirectoriesEntries); + AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES", lang, + &dagChecker, entries); if (this->Makefile->IsOn("APPLE")) { cmLinkImplementationLibraries const* impl = @@ -2925,16 +2989,14 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( libDir = frameworkCheck.match(1); - linkInterfaceIncludeDirectoriesEntries.push_back( - CreateTargetPropertyEntry(libDir)); + EvaluatedTargetPropertyEntry ee(lib, cmListFileBacktrace()); + ee.Values.emplace_back(std::move(libDir)); + entries.emplace_back(std::move(ee)); } } - processIncludeDirectories(this, linkInterfaceIncludeDirectoriesEntries, - includes, uniqueIncludes, &dagChecker, config, - debugIncludes, lang); - - cmDeleteAll(linkInterfaceIncludeDirectoriesEntries); + processIncludeDirectories(this, entries, includes, uniqueIncludes, + debugIncludes); return includes; } @@ -2945,33 +3007,26 @@ enum class OptionsParse Shell }; -static void processOptionsInternal( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& options, - std::unordered_set<std::string>& uniqueOptions, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - bool debugOptions, const char* logName, std::string const& language, - OptionsParse parse) -{ - for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) { - std::vector<std::string> entryOptions; - cmSystemTools::ExpandListArgument(entry->Evaluate(tgt->GetLocalGenerator(), - config, false, tgt, - dagChecker, language), - entryOptions); +namespace { +void processOptions(cmGeneratorTarget const* tgt, + std::vector<EvaluatedTargetPropertyEntry> const& entries, + std::vector<BT<std::string>>& options, + std::unordered_set<std::string>& uniqueOptions, + bool debugOptions, const char* logName, OptionsParse parse) +{ + for (EvaluatedTargetPropertyEntry const& entry : entries) { std::string usedOptions; - for (std::string const& opt : entryOptions) { + for (std::string const& opt : entry.Values) { if (uniqueOptions.insert(opt).second) { if (parse == OptionsParse::Shell && cmHasLiteralPrefix(opt, "SHELL:")) { std::vector<std::string> tmp; cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, tmp); for (std::string& o : tmp) { - options.emplace_back(std::move(o), entry->GetBacktrace()); + options.emplace_back(std::move(o), entry.Backtrace); } } else { - options.emplace_back(opt, entry->GetBacktrace()); + options.emplace_back(opt, entry.Backtrace); } if (debugOptions) { usedOptions += " * " + opt + "\n"; @@ -2983,22 +3038,10 @@ static void processOptionsInternal( MessageType::LOG, std::string("Used ") + logName + std::string(" for target ") + tgt->GetName() + ":\n" + usedOptions, - entry->GetBacktrace()); + entry.Backtrace); } } } - -static void processCompileOptions( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& options, - std::unordered_set<std::string>& uniqueOptions, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - bool debugOptions, std::string const& language) -{ - processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, - config, debugOptions, "compile options", language, - OptionsParse::Shell); } void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result, @@ -3036,37 +3079,19 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileOptions( this->DebugCompileOptionsDone = true; } - processCompileOptions(this, this->CompileOptionsEntries, result, - uniqueOptions, &dagChecker, config, debugOptions, - language); + std::vector<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, language, &dagChecker, + this->CompileOptionsEntries); - std::vector<cmGeneratorTarget::TargetPropertyEntry*> - linkInterfaceCompileOptionsEntries; + AddInterfaceEntries(this, config, "INTERFACE_COMPILE_OPTIONS", language, + &dagChecker, entries); - AddInterfaceEntries(this, config, "INTERFACE_COMPILE_OPTIONS", - linkInterfaceCompileOptionsEntries); + processOptions(this, entries, result, uniqueOptions, debugOptions, + "compile options", OptionsParse::Shell); - processCompileOptions(this, linkInterfaceCompileOptionsEntries, result, - uniqueOptions, &dagChecker, config, debugOptions, - language); - - cmDeleteAll(linkInterfaceCompileOptionsEntries); return result; } -static void processCompileFeatures( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& options, - std::unordered_set<std::string>& uniqueOptions, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - bool debugOptions) -{ - processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, - config, debugOptions, "compile features", - std::string(), OptionsParse::None); -} - void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result, const std::string& config) const { @@ -3101,34 +3126,19 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileFeatures( this->DebugCompileFeaturesDone = true; } - processCompileFeatures(this, this->CompileFeaturesEntries, result, - uniqueFeatures, &dagChecker, config, debugFeatures); + std::vector<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, std::string(), &dagChecker, + this->CompileFeaturesEntries); - std::vector<cmGeneratorTarget::TargetPropertyEntry*> - linkInterfaceCompileFeaturesEntries; AddInterfaceEntries(this, config, "INTERFACE_COMPILE_FEATURES", - linkInterfaceCompileFeaturesEntries); + std::string(), &dagChecker, entries); - processCompileFeatures(this, linkInterfaceCompileFeaturesEntries, result, - uniqueFeatures, &dagChecker, config, debugFeatures); + processOptions(this, entries, result, uniqueFeatures, debugFeatures, + "compile features", OptionsParse::None); - cmDeleteAll(linkInterfaceCompileFeaturesEntries); return result; } -static void processCompileDefinitions( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& options, - std::unordered_set<std::string>& uniqueOptions, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - bool debugOptions, std::string const& language) -{ - processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, - config, debugOptions, "compile definitions", language, - OptionsParse::None); -} - void cmGeneratorTarget::GetCompileDefinitions( std::vector<std::string>& result, const std::string& config, const std::string& language) const @@ -3165,14 +3175,13 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( this->DebugCompileDefinitionsDone = true; } - processCompileDefinitions(this, this->CompileDefinitionsEntries, list, - uniqueOptions, &dagChecker, config, debugDefines, - language); + std::vector<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, language, &dagChecker, + this->CompileDefinitionsEntries); + + AddInterfaceEntries(this, config, "INTERFACE_COMPILE_DEFINITIONS", language, + &dagChecker, entries); - std::vector<cmGeneratorTarget::TargetPropertyEntry*> - linkInterfaceCompileDefinitionsEntries; - AddInterfaceEntries(this, config, "INTERFACE_COMPILE_DEFINITIONS", - linkInterfaceCompileDefinitionsEntries); if (!config.empty()) { std::string configPropName = "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config); @@ -3187,8 +3196,10 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( CM_FALLTHROUGH; } case cmPolicies::OLD: { - linkInterfaceCompileDefinitionsEntries.push_back( + std::unique_ptr<TargetPropertyEntry> entry( CreateTargetPropertyEntry(configProp)); + entries.emplace_back(EvaluateTargetPropertyEntry( + this, config, language, &dagChecker, entry.get())); } break; case cmPolicies::NEW: case cmPolicies::REQUIRED_ALWAYS: @@ -3198,29 +3209,12 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( } } - processCompileDefinitions(this, linkInterfaceCompileDefinitionsEntries, list, - uniqueOptions, &dagChecker, config, debugDefines, - language); + processOptions(this, entries, list, uniqueOptions, debugDefines, + "compile definitions", OptionsParse::None); - cmDeleteAll(linkInterfaceCompileDefinitionsEntries); return list; } -namespace { -void processLinkOptions( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& options, - std::unordered_set<std::string>& uniqueOptions, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - bool debugOptions, std::string const& language) -{ - processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, - config, debugOptions, "link options", language, - OptionsParse::Shell); -} -} - void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result, const std::string& config, const std::string& language) const @@ -3256,20 +3250,15 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( this->DebugLinkOptionsDone = true; } - processLinkOptions(this, this->LinkOptionsEntries, result, uniqueOptions, - &dagChecker, config, debugOptions, language); - - std::vector<cmGeneratorTarget::TargetPropertyEntry*> - linkInterfaceLinkOptionsEntries; + std::vector<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, language, &dagChecker, + this->LinkOptionsEntries); - AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS", - linkInterfaceLinkOptionsEntries); + AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS", language, + &dagChecker, entries); - processLinkOptions(this, linkInterfaceLinkOptionsEntries, result, - uniqueOptions, &dagChecker, config, debugOptions, - language); - - cmDeleteAll(linkInterfaceLinkOptionsEntries); + processOptions(this, entries, result, uniqueOptions, debugOptions, + "link options", OptionsParse::Shell); // Last step: replace "LINKER:" prefixed elements by // actual linker wrapper @@ -3375,21 +3364,6 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( return result; } -namespace { -void processStaticLibraryLinkOptions( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& options, - std::unordered_set<std::string>& uniqueOptions, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - std::string const& language) -{ - processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, - config, false, "static library link options", - language, OptionsParse::Shell); -} -} - void cmGeneratorTarget::GetStaticLibraryLinkOptions( std::vector<std::string>& result, const std::string& config, const std::string& language) const @@ -3406,47 +3380,41 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetStaticLibraryLinkOptions( std::string const& config, std::string const& language) const { std::vector<BT<std::string>> result; - std::vector<cmGeneratorTarget::TargetPropertyEntry*> entries; std::unordered_set<std::string> uniqueOptions; cmGeneratorExpressionDAGChecker dagChecker(this, "STATIC_LIBRARY_OPTIONS", nullptr, nullptr); + std::vector<EvaluatedTargetPropertyEntry> entries; if (const char* linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) { std::vector<std::string> options; cmSystemTools::ExpandListArgument(linkOptions, options); for (const auto& option : options) { - entries.push_back(CreateTargetPropertyEntry(option)); + std::unique_ptr<TargetPropertyEntry> entry( + CreateTargetPropertyEntry(option)); + entries.emplace_back(EvaluateTargetPropertyEntry( + this, config, language, &dagChecker, entry.get())); } } - processStaticLibraryLinkOptions(this, entries, result, uniqueOptions, - &dagChecker, config, language); + processOptions(this, entries, result, uniqueOptions, false, + "static library link options", OptionsParse::Shell); - cmDeleteAll(entries); return result; } namespace { -void processLinkDirectories( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& directories, - std::unordered_set<std::string>& uniqueDirectories, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - bool debugDirectories, std::string const& language) -{ - for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) { - cmLinkImplItem const& item = entry->LinkImplItem; +void processLinkDirectories(cmGeneratorTarget const* tgt, + std::vector<EvaluatedTargetPropertyEntry>& entries, + std::vector<BT<std::string>>& directories, + std::unordered_set<std::string>& uniqueDirectories, + bool debugDirectories) +{ + for (EvaluatedTargetPropertyEntry& entry : entries) { + cmLinkImplItem const& item = entry.LinkImplItem; std::string const& targetName = item.AsStr(); - std::vector<std::string> entryDirectories; - cmSystemTools::ExpandListArgument(entry->Evaluate(tgt->GetLocalGenerator(), - config, false, tgt, - dagChecker, language), - entryDirectories); - std::string usedDirectories; - for (std::string& entryDirectory : entryDirectories) { + for (std::string& entryDirectory : entry.Values) { if (!cmSystemTools::FileIsFullPath(entryDirectory)) { std::ostringstream e; bool noMessage = false; @@ -3499,7 +3467,7 @@ void processLinkDirectories( MessageType::LOG, std::string("Used link directories for target ") + tgt->GetName() + ":\n" + usedDirectories, - entry->GetBacktrace()); + entry.Backtrace); } } } @@ -3541,39 +3509,19 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDirectories( this->DebugLinkDirectoriesDone = true; } - processLinkDirectories(this, this->LinkDirectoriesEntries, result, - uniqueDirectories, &dagChecker, config, - debugDirectories, language); - - std::vector<cmGeneratorTarget::TargetPropertyEntry*> - linkInterfaceLinkDirectoriesEntries; + std::vector<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, language, &dagChecker, + this->LinkDirectoriesEntries); - AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES", - linkInterfaceLinkDirectoriesEntries); + AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES", language, + &dagChecker, entries); - processLinkDirectories(this, linkInterfaceLinkDirectoriesEntries, result, - uniqueDirectories, &dagChecker, config, - debugDirectories, language); + processLinkDirectories(this, entries, result, uniqueDirectories, + debugDirectories); - cmDeleteAll(linkInterfaceLinkDirectoriesEntries); return result; } -namespace { -void processLinkDepends( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& options, - std::unordered_set<std::string>& uniqueOptions, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - std::string const& language) -{ - processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, - config, false, "link depends", language, - OptionsParse::None); -} -} - void cmGeneratorTarget::GetLinkDepends(std::vector<std::string>& result, const std::string& config, const std::string& language) const @@ -3589,24 +3537,27 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends( std::string const& config, std::string const& language) const { std::vector<BT<std::string>> result; - std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkDependsEntries; std::unordered_set<std::string> uniqueOptions; cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DEPENDS", nullptr, nullptr); + std::vector<EvaluatedTargetPropertyEntry> entries; if (const char* linkDepends = this->GetProperty("LINK_DEPENDS")) { std::vector<std::string> depends; cmSystemTools::ExpandListArgument(linkDepends, depends); for (const auto& depend : depends) { - linkDependsEntries.push_back(CreateTargetPropertyEntry(depend)); + std::unique_ptr<TargetPropertyEntry> entry( + CreateTargetPropertyEntry(depend)); + entries.emplace_back(EvaluateTargetPropertyEntry( + this, config, language, &dagChecker, entry.get())); } } - AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS", - linkDependsEntries); - processLinkDepends(this, linkDependsEntries, result, uniqueOptions, - &dagChecker, config, language); + AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS", language, + &dagChecker, entries); + + processOptions(this, entries, result, uniqueOptions, false, "link depends", + OptionsParse::None); - cmDeleteAll(linkDependsEntries); return result; } @@ -4346,8 +4297,9 @@ void checkPropertyConsistency(cmGeneratorTarget const* depender, } } -static std::string intersect(const std::set<std::string>& s1, - const std::set<std::string>& s2) +namespace { +std::string intersect(const std::set<std::string>& s1, + const std::set<std::string>& s2) { std::set<std::string> intersect; std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), @@ -4358,9 +4310,9 @@ static std::string intersect(const std::set<std::string>& s1, return ""; } -static std::string intersect(const std::set<std::string>& s1, - const std::set<std::string>& s2, - const std::set<std::string>& s3) +std::string intersect(const std::set<std::string>& s1, + const std::set<std::string>& s2, + const std::set<std::string>& s3) { std::string result; result = intersect(s1, s2); @@ -4374,10 +4326,10 @@ static std::string intersect(const std::set<std::string>& s1, return intersect(s2, s3); } -static std::string intersect(const std::set<std::string>& s1, - const std::set<std::string>& s2, - const std::set<std::string>& s3, - const std::set<std::string>& s4) +std::string intersect(const std::set<std::string>& s1, + const std::set<std::string>& s2, + const std::set<std::string>& s3, + const std::set<std::string>& s4) { std::string result; result = intersect(s1, s2); @@ -4394,6 +4346,7 @@ static std::string intersect(const std::set<std::string>& s1, } return intersect(s2, s3, s4); } +} void cmGeneratorTarget::CheckPropertyCompatibility( cmComputeLinkInformation* info, const std::string& config) const diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 4ffd6e0..d177278 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1134,11 +1134,13 @@ void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags, std::string const& linkLanguage, cmGeneratorTarget* target) { - this->AppendFlags( - flags, this->Makefile->GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS")); - if (!config.empty()) { - std::string name = "CMAKE_STATIC_LINKER_FLAGS_" + config; - this->AppendFlags(flags, this->Makefile->GetSafeDefinition(name)); + if (linkLanguage != "Swift") { + this->AppendFlags( + flags, this->Makefile->GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS")); + if (!config.empty()) { + std::string name = "CMAKE_STATIC_LINKER_FLAGS_" + config; + this->AppendFlags(flags, this->Makefile->GetSafeDefinition(name)); + } } this->AppendFlags(flags, target->GetProperty("STATIC_LIBRARY_FLAGS")); if (!config.empty()) { diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx index 5320ec5..58f3b2f 100644 --- a/Source/cmMessageCommand.cxx +++ b/Source/cmMessageCommand.cxx @@ -25,7 +25,6 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args, auto i = args.cbegin(); auto type = MessageType::MESSAGE; - auto status = false; auto fatal = false; auto level = cmake::LogLevel::LOG_UNDEFINED; if (*i == "SEND_ERROR") { @@ -55,19 +54,15 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args, } ++i; } else if (*i == "STATUS") { - status = true; level = cmake::LogLevel::LOG_STATUS; ++i; } else if (*i == "VERBOSE") { - status = true; level = cmake::LogLevel::LOG_VERBOSE; ++i; } else if (*i == "DEBUG") { - status = true; level = cmake::LogLevel::LOG_DEBUG; ++i; } else if (*i == "TRACE") { - status = true; level = cmake::LogLevel::LOG_TRACE; ++i; } else if (*i == "DEPRECATION") { @@ -105,17 +100,46 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args, auto message = cmJoin(cmMakeRange(i, args.cend()), ""); - if (type != MessageType::MESSAGE) { - // we've overridden the message type, above, so display it directly - cmMessenger* m = this->Makefile->GetMessenger(); - m->DisplayMessage(type, message, this->Makefile->GetBacktrace()); - } else { - if (status) { - this->Makefile->DisplayStatus(message, -1); - } else { + if (cmake::LogLevel::LOG_NOTICE <= level) { + // Check if any indentation has requested: + // `CMAKE_MESSAGE_INDENT` is a list of "padding" pieces + // to be joined and prepended to the message lines. + auto indent = + cmJoin(cmSystemTools::ExpandedListArgument( + this->Makefile->GetSafeDefinition("CMAKE_MESSAGE_INDENT")), + ""); + // Make every line of the `message` indented + // NOTE Can't reuse `cmDocumentationFormatter::PrintPreformatted` + // here cuz it appends `\n` to the EOM ;-( + cmSystemTools::ReplaceString(message, "\n", "\n" + indent); + message = indent + message; + } + + switch (level) { + case cmake::LogLevel::LOG_ERROR: + case cmake::LogLevel::LOG_WARNING: + // we've overridden the message type, above, so display it directly + this->Makefile->GetMessenger()->DisplayMessage( + type, message, this->Makefile->GetBacktrace()); + break; + + case cmake::LogLevel::LOG_NOTICE: cmSystemTools::Message(message); - } + break; + + case cmake::LogLevel::LOG_STATUS: + case cmake::LogLevel::LOG_VERBOSE: + case cmake::LogLevel::LOG_DEBUG: + case cmake::LogLevel::LOG_TRACE: + this->Makefile->DisplayStatus(message, -1); + break; + + default: + assert("Unexpected log level! Review the `cmMessageCommand.cxx`." && + false); + break; } + if (fatal) { cmSystemTools::SetFatalErrorOccured(); } diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake index 37df57c..d93f280 100644 --- a/Tests/RunCMake/CPack/RunCMakeTest.cmake +++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake @@ -33,6 +33,6 @@ run_cpack_test(TIMESTAMPS "DEB.TIMESTAMPS;TGZ" false "COMPONENT") unset(ENVIRONMENT) run_cpack_test(USER_FILELIST "RPM.USER_FILELIST" false "MONOLITHIC") run_cpack_test(MD5SUMS "DEB.MD5SUMS" false "MONOLITHIC;COMPONENT") -run_cpack_test(CPACK_INSTALL_SCRIPT "ZIP" false "MONOLITHIC") +run_cpack_test_subtests(CPACK_INSTALL_SCRIPTS "singular;plural;both" "ZIP" false "MONOLITHIC") run_cpack_test(DEB_PACKAGE_VERSION_BACK_COMPATIBILITY "DEB.DEB_PACKAGE_VERSION_BACK_COMPATIBILITY" false "MONOLITHIC;COMPONENT") run_cpack_test_subtests(EXTERNAL "none;good;good_multi;bad_major;bad_minor;invalid_good;invalid_bad;stage_and_package" "External" false "MONOLITHIC;COMPONENT") diff --git a/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/test.cmake b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/test.cmake deleted file mode 100644 index e3fe0ca..0000000 --- a/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/test.cmake +++ /dev/null @@ -1,11 +0,0 @@ -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/abc.txt" "test content") -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/user-script.cmake" - "file(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/foo\" - TYPE FILE FILES \"${CMAKE_CURRENT_BINARY_DIR}/abc.txt\")") -set(CPACK_INSTALL_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/user-script.cmake") - -function(run_after_include_cpack) - file(READ "${CPACK_OUTPUT_CONFIG_FILE}" conf_file_) - string(REGEX REPLACE "SET\\(CPACK_INSTALL_CMAKE_PROJECTS [^)]*\\)" "" conf_file_ "${conf_file_}") - file(WRITE "${CPACK_OUTPUT_CONFIG_FILE}" "${conf_file_}") -endfunction() diff --git a/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPTS/ExpectedFiles.cmake index 02a7821..02a7821 100644 --- a/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/ExpectedFiles.cmake +++ b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPTS/ExpectedFiles.cmake diff --git a/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPTS/both-stderr.txt b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPTS/both-stderr.txt new file mode 100644 index 0000000..666030e --- /dev/null +++ b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPTS/both-stderr.txt @@ -0,0 +1 @@ +CPack Warning: Both CPACK_INSTALL_SCRIPTS and CPACK_INSTALL_SCRIPT are set, the latter will be ignored. diff --git a/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPTS/test.cmake b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPTS/test.cmake new file mode 100644 index 0000000..249d2e6 --- /dev/null +++ b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPTS/test.cmake @@ -0,0 +1,26 @@ +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/abc.txt" "test content") +set(user_script_ "${CMAKE_CURRENT_BINARY_DIR}/user-script.cmake") +file(WRITE "${user_script_}" + "file(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/foo\" + TYPE FILE FILES \"${CMAKE_CURRENT_BINARY_DIR}/abc.txt\")") + +if(RunCMake_SUBTEST_SUFFIX STREQUAL "both") + set(CPACK_INSTALL_SCRIPT "${user_script_}") + set(CPACK_INSTALL_SCRIPTS "${CPACK_INSTALL_SCRIPT}") + +elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "singular") + set(CPACK_INSTALL_SCRIPT "${user_script_}") + +elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "plural") + set(CPACK_INSTALL_SCRIPTS "${user_script_}") + +else() + message(FATAL_ERROR "Unexpected subtest name: ${RunCMake_SUBTEST_SUFFIX}") + +endif() + +function(run_after_include_cpack) + file(READ "${CPACK_OUTPUT_CONFIG_FILE}" conf_file_) + string(REGEX REPLACE "SET\\(CPACK_INSTALL_CMAKE_PROJECTS [^)]*\\)" "" conf_file_ "${conf_file_}") + file(WRITE "${CPACK_OUTPUT_CONFIG_FILE}" "${conf_file_}") +endfunction() diff --git a/Tests/RunCMake/message/RunCMakeTest.cmake b/Tests/RunCMake/message/RunCMakeTest.cmake index cecfc7f..3c7e51c 100644 --- a/Tests/RunCMake/message/RunCMakeTest.cmake +++ b/Tests/RunCMake/message/RunCMakeTest.cmake @@ -52,3 +52,12 @@ run_cmake_command( message-loglevel-trace ${CMAKE_COMMAND} --loglevel=trace -P ${RunCMake_SOURCE_DIR}/message-all-loglevels.cmake ) + +run_cmake_command( + message-indent + ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/message-indent.cmake + ) +run_cmake_command( + message-indent-multiline + ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/message-indent-multiline.cmake + ) diff --git a/Tests/RunCMake/message/message-indent-multiline-stderr.txt b/Tests/RunCMake/message/message-indent-multiline-stderr.txt new file mode 100644 index 0000000..5853a31 --- /dev/null +++ b/Tests/RunCMake/message/message-indent-multiline-stderr.txt @@ -0,0 +1,3 @@ + >This is + >the multiline + >message diff --git a/Tests/RunCMake/message/message-indent-multiline-stdout.txt b/Tests/RunCMake/message/message-indent-multiline-stdout.txt new file mode 100644 index 0000000..ae0c72e --- /dev/null +++ b/Tests/RunCMake/message/message-indent-multiline-stdout.txt @@ -0,0 +1,8 @@ +-- >This is + >the multiline + >message + > + > +-- >This is + >the multiline + >message diff --git a/Tests/RunCMake/message/message-indent-multiline.cmake b/Tests/RunCMake/message/message-indent-multiline.cmake new file mode 100644 index 0000000..0f789bf --- /dev/null +++ b/Tests/RunCMake/message/message-indent-multiline.cmake @@ -0,0 +1,13 @@ +# NOTE Use non-space indent string, to check indentation +# of line endings and "empty" lines. +# ALERT Do not put any space characters after the non-space! +list(APPEND CMAKE_MESSAGE_INDENT " >") +set(msg [[This is +the multiline +message]]) # No `\n` at the end! +# NOTE Two empty lines after the text +message(STATUS "${msg}\n\n") +message(STATUS "${msg}") +# This is just to make sure NOTICE messages are also get indented: +# https://gitlab.kitware.com/cmake/cmake/issues/19418#note_588011 +message(NOTICE "${msg}") diff --git a/Tests/RunCMake/message/message-indent-stdout.txt b/Tests/RunCMake/message/message-indent-stdout.txt new file mode 100644 index 0000000..b2c3c60 --- /dev/null +++ b/Tests/RunCMake/message/message-indent-stdout.txt @@ -0,0 +1,13 @@ +-- COUNTING: +-- COUNTING_ENGLISH: +-- one +-- two +-- three +-- four +-- five +-- COUNTING_BAHASA: +-- satu +-- dua +-- tiga +-- empat +-- lima diff --git a/Tests/RunCMake/message/message-indent.cmake b/Tests/RunCMake/message/message-indent.cmake new file mode 100644 index 0000000..c07ff45 --- /dev/null +++ b/Tests/RunCMake/message/message-indent.cmake @@ -0,0 +1,19 @@ +function(debug_list LIST_VAR) + message(STATUS "${LIST_VAR}:") + list(APPEND CMAKE_MESSAGE_INDENT " ") + foreach(_item IN LISTS ${LIST_VAR}) + list(LENGTH ${_item} _item_len) + if(_item_len GREATER 1) + debug_list(${_item}) + else() + message(STATUS "${_item}") + endif() + endforeach() +endfunction() + +list(APPEND COUNTING_ENGLISH one two three four five) +list(APPEND COUNTING_BAHASA satu dua tiga empat lima) + +list(APPEND COUNTING COUNTING_ENGLISH COUNTING_BAHASA) + +debug_list(COUNTING) |