diff options
58 files changed, 640 insertions, 286 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e88e925..ee987d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. -cmake_minimum_required(VERSION 3.1 FATAL_ERROR) +cmake_minimum_required(VERSION 3.1...3.12 FATAL_ERROR) set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/Source/Modules/OverrideC.cmake) set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX ${CMAKE_CURRENT_SOURCE_DIR}/Source/Modules/OverrideCXX.cmake) project(CMake) diff --git a/Copyright.txt b/Copyright.txt index 0b0fbf1..c7a81b1 100644 --- a/Copyright.txt +++ b/Copyright.txt @@ -64,6 +64,7 @@ The following individuals and institutions are among the Contributors: * Insight Software Consortium <insightsoftwareconsortium.org> * Jan Woetzel * Kelly Thompson <kgt@lanl.gov> +* Laurent Montel <montel@kde.org> * Konstantin Podsvirov <konstantin@podsvirov.pro> * Mario Bensi <mbensi@ipsquad.net> * Martin Gräßlin <mgraesslin@kde.org> diff --git a/Help/command/execute_process.rst b/Help/command/execute_process.rst index 716f457..fc7d177 100644 --- a/Help/command/execute_process.rst +++ b/Help/command/execute_process.rst @@ -5,8 +5,8 @@ Execute one or more child processes. .. code-block:: cmake - execute_process(COMMAND <cmd1> [args1...]] - [COMMAND <cmd2> [args2...] [...]] + execute_process(COMMAND <cmd1> [<arguments>] + [COMMAND <cmd2> [<arguments>]]... [WORKING_DIRECTORY <directory>] [TIMEOUT <seconds>] [RESULT_VARIABLE <variable>] diff --git a/Help/command/target_link_libraries.rst b/Help/command/target_link_libraries.rst index 229d10c..58f312e 100644 --- a/Help/command/target_link_libraries.rst +++ b/Help/command/target_link_libraries.rst @@ -43,6 +43,9 @@ Each ``<item>`` may be: the library instead of using the full path (e.g. ``/usr/lib/libfoo.so`` becomes ``-lfoo``). + The full path to the target's artifact will be quoted/escaped for + the shell automatically. + * **A full path to a library file**: The generated link line will normally preserve the full path to the file. The buildsystem will have a dependency to re-link ``<target>`` if the library file changes. @@ -62,9 +65,15 @@ Each ``<item>`` may be: imported into generated project files. This is not supported by other generators. + The full path to the library file will be quoted/escaped for + the shell automatically. + * **A plain library name**: The generated link line will ask the linker to search for the library (e.g. ``foo`` becomes ``-lfoo`` or ``foo.lib``). + The library name/flag is treated as a command-line string fragment and + will be used with no extra quoting or escaping. + * **A link flag**: Item names starting with ``-``, but not ``-l`` or ``-framework``, are treated as linker flags. Note that such flags will be treated like any other library link item for purposes of transitive @@ -78,6 +87,9 @@ Each ``<item>`` may be: flags explicitly. The flags will then be placed at the toolchain-defined flag position in the link command. + The link flag is treated as a command-line string fragment and + will be used with no extra quoting or escaping. + * **A generator expression**: A ``$<...>`` :manual:`generator expression <cmake-generator-expressions(7)>` may evaluate to any of the above items or to a :ref:`;-list <CMake Language Lists>` of them. diff --git a/Help/manual/cmake-language.7.rst b/Help/manual/cmake-language.7.rst index 71649ba..8740d97 100644 --- a/Help/manual/cmake-language.7.rst +++ b/Help/manual/cmake-language.7.rst @@ -206,9 +206,10 @@ enclosed content, such as `Escape Sequences`_ or `Variable References`_, is performed. A bracket argument is always given to the command invocation as exactly one argument. -For example: +.. No code-block syntax highlighting in the following example + (long string literal not supported by our cmake.py) -.. code-block:: cmake +For example:: message([=[ This is the first line in a bracket argument with bracket length 1. @@ -253,9 +254,10 @@ closing quotes. Both `Escape Sequences`_ and `Variable References`_ are evaluated. A quoted argument is always given to the command invocation as exactly one argument. -For example: +.. No code-block syntax highlighting in the following example + (escape \" not supported by our cmake.py) -:: +For example:: message("This is a quoted argument containing multiple lines. This is always one argument even though it contains a ; character. @@ -264,11 +266,12 @@ For example: It does end in an unescaped double quote. ") +.. No code-block syntax highlighting in the following example + (for conformity with the two above examples) + The final ``\`` on any line ending in an odd number of backslashes is treated as a line continuation and ignored along with the -immediately following newline character. For example: - -.. code-block:: cmake +immediately following newline character. For example:: message("\ This is the first line of a quoted argument. \ diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index f9b4afb..c0bef08 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -131,6 +131,7 @@ They are normally called through the :command:`find_package` command. /module/FindFLEX /module/FindFLTK2 /module/FindFLTK + /module/FindFontconfig /module/FindFreetype /module/FindGCCXML /module/FindGDAL diff --git a/Help/module/FindFontconfig.rst b/Help/module/FindFontconfig.rst new file mode 100644 index 0000000..449fe09 --- /dev/null +++ b/Help/module/FindFontconfig.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/FindFontconfig.cmake diff --git a/Help/policy/CMP0049.rst b/Help/policy/CMP0049.rst index a3ce4b1..291bf57 100644 --- a/Help/policy/CMP0049.rst +++ b/Help/policy/CMP0049.rst @@ -3,14 +3,14 @@ CMP0049 Do not expand variables in target source entries. -CMake 2.8.12 and lower performed and extra layer of variable expansion -when evaluating source file names: - -.. code-block:: cmake +CMake 2.8.12 and lower performed an extra layer of variable expansion +when evaluating source file names:: set(a_source foo.c) add_executable(foo \${a_source}) +.. note: no cmake highlighting since this syntax is deprecated + This was undocumented behavior. The OLD behavior for this policy is to expand such variables when processing diff --git a/Help/release/dev/find_fontconfig.rst b/Help/release/dev/find_fontconfig.rst new file mode 100644 index 0000000..4ae18c9 --- /dev/null +++ b/Help/release/dev/find_fontconfig.rst @@ -0,0 +1,6 @@ +find_fontconfig +--------------- + +* The :module:`FindFontconfig` module was added to find `fontconfig`_. + +.. _`fontconfig`: https://www.freedesktop.org/wiki/Software/fontconfig/ diff --git a/Modules/AddFileDependencies.cmake b/Modules/AddFileDependencies.cmake index fdd8432..999da95 100644 --- a/Modules/AddFileDependencies.cmake +++ b/Modules/AddFileDependencies.cmake @@ -5,9 +5,13 @@ # AddFileDependencies # ------------------- # -# ADD_FILE_DEPENDENCIES(source_file depend_files...) +# Add dependencies to a source file. # -# Adds the given files as dependencies to source_file +# .. code-block:: cmake +# +# ADD_FILE_DEPENDENCIES(<source> <files>) +# +# Adds the given ``<files>`` to the dependencies of file ``<source>``. macro(ADD_FILE_DEPENDENCIES _file) diff --git a/Modules/AndroidTestUtilities.cmake b/Modules/AndroidTestUtilities.cmake index 62d04f3..e333cdb 100644 --- a/Modules/AndroidTestUtilities.cmake +++ b/Modules/AndroidTestUtilities.cmake @@ -40,7 +40,7 @@ Module Functions .. command:: android_add_test_data - :: + .. code-block:: cmake android_add_test_data(<test-name> [FILES <files>...] [FILES_DEST <device-dir>] diff --git a/Modules/BundleUtilities.cmake b/Modules/BundleUtilities.cmake index 6940352..4a3f476 100644 --- a/Modules/BundleUtilities.cmake +++ b/Modules/BundleUtilities.cmake @@ -12,7 +12,7 @@ bundles on the Mac and bundle-like directories on any OS. The following functions are provided by this module: -:: +.. code-block:: cmake fixup_bundle copy_and_fixup_bundle @@ -39,7 +39,7 @@ DO NOT USE THESE FUNCTIONS AT CONFIGURE TIME (from ``CMakeLists.txt``)! Instead, invoke them from an :command:`install(CODE)` or :command:`install(SCRIPT)` rule. -:: +.. code-block:: cmake FIXUP_BUNDLE(<app> <libs> <dirs>) @@ -62,14 +62,14 @@ ensure that it is truly standalone. As an optional parameter (IGNORE_ITEM) a list of file names can be passed, which are then ignored (e.g. IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe") -:: +.. code-block:: cmake COPY_AND_FIXUP_BUNDLE(<src> <dst> <libs> <dirs>) Makes a copy of the bundle <src> at location <dst> and then fixes up the new copied bundle in-place at <dst>... -:: +.. code-block:: cmake VERIFY_APP(<app>) @@ -80,14 +80,14 @@ is not verified. As an optional parameter (IGNORE_ITEM) a list of file names can be passed, which are then ignored (e.g. IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe") -:: +.. code-block:: cmake GET_BUNDLE_MAIN_EXECUTABLE(<bundle> <result_var>) The result will be the full path name of the bundle's main executable file or an "error:" prefixed string if it could not be determined. -:: +.. code-block:: cmake GET_DOTAPP_DIR(<exe> <dotapp_dir_var>) @@ -97,7 +97,7 @@ simply return the dir containing the executable. The returned directory may or may not exist. -:: +.. code-block:: cmake GET_BUNDLE_AND_EXECUTABLE(<app> <bundle_var> <executable_var> <valid_var>) @@ -106,14 +106,14 @@ nested inside a ".app" directory and returns the path to the ".app" directory in <bundle_var> and the path to its main executable in <executable_var> -:: +.. code-block:: cmake GET_BUNDLE_ALL_EXECUTABLES(<bundle> <exes_var>) Scans the given bundle recursively for all executable files and accumulates them into a variable. -:: +.. code-block:: cmake GET_ITEM_KEY(<item> <key_var>) @@ -125,7 +125,7 @@ extension with "." replaced by "_" This key is used as a prefix for CMake variables so that we can associate a set of variables with a given item based on its key. -:: +.. code-block:: cmake CLEAR_BUNDLE_KEYS(<keys_var>) @@ -135,7 +135,7 @@ each key. After the loop, clear the list of keys itself. Caller of get_bundle_keys should call clear_bundle_keys when done with list of keys. -:: +.. code-block:: cmake SET_BUNDLE_KEY_VALUES(<keys_var> <context> <item> <exepath> <dirs> <copyflag> [<rpaths>]) @@ -143,7 +143,7 @@ list of keys. Add a key to the list (if necessary) for the given item. If added, also set all the variables associated with that key. -:: +.. code-block:: cmake GET_BUNDLE_KEYS(<app> <libs> <dirs> <keys_var>) @@ -156,7 +156,7 @@ appropriate install_name_tool fixups. As an optional parameter (IGNORE_ITEM) a list of file names can be passed, which are then ignored (e.g. IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe") -:: +.. code-block:: cmake COPY_RESOLVED_ITEM_INTO_BUNDLE(<resolved_item> <resolved_embedded_item>) @@ -164,7 +164,7 @@ Copy a resolved item into the bundle if necessary. Copy is not necessary if the resolved_item is "the same as" the resolved_embedded_item. -:: +.. code-block:: cmake COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE(<resolved_item> <resolved_embedded_item>) @@ -178,7 +178,7 @@ BU_COPY_FULL_FRAMEWORK_CONTENTS to ON before calling fixup_bundle. By default, COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE copies the framework dylib itself plus the framework Resources directory. -:: +.. code-block:: cmake FIXUP_BUNDLE_ITEM(<resolved_embedded_item> <exepath> <dirs>) @@ -204,7 +204,7 @@ once. If the BU_CHMOD_BUNDLE_ITEMS variable is set then bundle items will be marked writable before install_name_tool tries to change them. -:: +.. code-block:: cmake VERIFY_BUNDLE_PREREQUISITES(<bundle> <result_var> <info_var>) @@ -215,7 +215,7 @@ presumed to exist everywhere. As an optional parameter (IGNORE_ITEM) a list of file names can be passed, which are then ignored (e.g. IGNORE_ITEM "vcredist_x86.exe;vcredist_x64.exe") -:: +.. code-block:: cmake VERIFY_BUNDLE_SYMLINKS(<bundle> <result_var> <info_var>) diff --git a/Modules/CheckCCompilerFlag.cmake b/Modules/CheckCCompilerFlag.cmake index 9d2c74d..f5c1127 100644 --- a/Modules/CheckCCompilerFlag.cmake +++ b/Modules/CheckCCompilerFlag.cmake @@ -9,7 +9,7 @@ Check whether the C compiler supports a given flag. .. command:: check_c_compiler_flag - :: + .. code-block:: cmake check_c_compiler_flag(<flag> <var>) diff --git a/Modules/CheckCSourceCompiles.cmake b/Modules/CheckCSourceCompiles.cmake index 114213a..5b0b70e 100644 --- a/Modules/CheckCSourceCompiles.cmake +++ b/Modules/CheckCSourceCompiles.cmake @@ -9,15 +9,16 @@ Check if given C source compiles and links into an executable. .. command:: check_c_source_compiles - :: + .. code-block:: cmake - check_c_source_compiles(code resultVar [FAIL_REGEX regex1 [regex2...]]) + check_c_source_compiles(<code> <resultVar> + [FAIL_REGEX <regex1> [<regex2>...]]) - Check that the source supplied in ``code`` can be compiled as a C source + Check that the source supplied in ``<code>`` can be compiled as a C source file and linked as an executable (so it must contain at least a ``main()`` function). The result will be stored in the internal cache variable specified - by ``resultVar``, with a boolean true value for success and boolean false for - failure. If ``FAIL_REGEX`` is provided, then failure is determined by + by ``<resultVar>``, with a boolean true value for success and boolean false + for failure. If ``FAIL_REGEX`` is provided, then failure is determined by checking if anything in the output matches any of the specified regular expressions. @@ -34,7 +35,7 @@ Check if given C source compiles and links into an executable. ``CMAKE_REQUIRED_DEFINITIONS`` A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form ``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by - ``resultVar`` will also be added automatically. + ``<resultVar>`` will also be added automatically. ``CMAKE_REQUIRED_INCLUDES`` A :ref:`;-list <CMake Language Lists>` of header search paths to pass to @@ -53,10 +54,10 @@ Check if given C source compiles and links into an executable. associated with the check will be suppressed. The check is only performed once, with the result cached in the variable - named by ``resultVar``. Every subsequent CMake run will re-use this cached - value rather than performing the check again, even if the ``code`` changes. + named by ``<resultVar>``. Every subsequent CMake run will re-use this cached + value rather than performing the check again, even if the ``<code>`` changes. In order to force the check to be re-evaluated, the variable named by - ``resultVar`` must be manually removed from the cache. + ``<resultVar>`` must be manually removed from the cache. #]=======================================================================] @@ -131,4 +132,3 @@ macro(CHECK_C_SOURCE_COMPILES SOURCE VAR) endif() endif() endmacro() - diff --git a/Modules/CheckCSourceRuns.cmake b/Modules/CheckCSourceRuns.cmake index 7eb050c..e682b29 100644 --- a/Modules/CheckCSourceRuns.cmake +++ b/Modules/CheckCSourceRuns.cmake @@ -10,16 +10,16 @@ subsequently be run. .. command:: check_c_source_runs - :: + .. code-block:: cmake - check_c_source_runs(code resultVar) + check_c_source_runs(<code> <resultVar>) - Check that the source supplied in ``code`` can be compiled as a C source - file, linked as an executable and then run. The ``code`` must contain at - least a ``main()`` function. If the code could be built and run successfully, - the internal cache variable specified by ``resultVar`` will be set to 1, - otherwise it will be set to an value that evaluates to boolean false (e.g. - an empty string or an error message). + Check that the source supplied in ``<code>`` can be compiled as a C source + file, linked as an executable and then run. The ``<code>`` must contain at + least a ``main()`` function. If the ``<code>`` could be built and run + successfully, the internal cache variable specified by ``<resultVar>`` will + be set to 1, otherwise it will be set to an value that evaluates to boolean + false (e.g. an empty string or an error message). The underlying check is performed by the :command:`try_run` command. The compile and link commands can be influenced by setting any of the following @@ -34,7 +34,7 @@ subsequently be run. ``CMAKE_REQUIRED_DEFINITIONS`` A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form ``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by - ``resultVar`` will also be added automatically. + ``<resultVar>`` will also be added automatically. ``CMAKE_REQUIRED_INCLUDES`` A :ref:`;-list <CMake Language Lists>` of header search paths to pass to @@ -53,10 +53,10 @@ subsequently be run. associated with the check will be suppressed. The check is only performed once, with the result cached in the variable - named by ``resultVar``. Every subsequent CMake run will re-use this cached - value rather than performing the check again, even if the ``code`` changes. + named by ``<resultVar>``. Every subsequent CMake run will re-use this cached + value rather than performing the check again, even if the ``<code>`` changes. In order to force the check to be re-evaluated, the variable named by - ``resultVar`` must be manually removed from the cache. + ``<resultVar>`` must be manually removed from the cache. #]=======================================================================] @@ -132,4 +132,3 @@ macro(CHECK_C_SOURCE_RUNS SOURCE VAR) endif() endif() endmacro() - diff --git a/Modules/CheckCXXCompilerFlag.cmake b/Modules/CheckCXXCompilerFlag.cmake index dd60835..a01e142 100644 --- a/Modules/CheckCXXCompilerFlag.cmake +++ b/Modules/CheckCXXCompilerFlag.cmake @@ -9,7 +9,7 @@ Check whether the CXX compiler supports a given flag. .. command:: check_cxx_compiler_flag - :: + .. code-block:: cmake check_cxx_compiler_flag(<flag> <var>) @@ -61,4 +61,3 @@ macro (CHECK_CXX_COMPILER_FLAG _FLAG _RESULT) set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") endmacro () - diff --git a/Modules/CheckCXXSourceCompiles.cmake b/Modules/CheckCXXSourceCompiles.cmake index ed8661b..f7ec8eb 100644 --- a/Modules/CheckCXXSourceCompiles.cmake +++ b/Modules/CheckCXXSourceCompiles.cmake @@ -9,15 +9,16 @@ Check if given C++ source compiles and links into an executable. .. command:: check_cxx_source_compiles - :: + .. code-block:: cmake - check_cxx_source_compiles(code resultVar [FAIL_REGEX regex1 [regex2...]]) + check_cxx_source_compiles(<code> <resultVar> + [FAIL_REGEX <regex1> [<regex2>...]]) - Check that the source supplied in ``code`` can be compiled as a C++ source + Check that the source supplied in ``<code>`` can be compiled as a C++ source file and linked as an executable (so it must contain at least a ``main()`` function). The result will be stored in the internal cache variable specified - by ``resultVar``, with a boolean true value for success and boolean false for - failure. If ``FAIL_REGEX`` is provided, then failure is determined by + by ``<resultVar>``, with a boolean true value for success and boolean false + for failure. If ``FAIL_REGEX`` is provided, then failure is determined by checking if anything in the output matches any of the specified regular expressions. @@ -34,7 +35,7 @@ Check if given C++ source compiles and links into an executable. ``CMAKE_REQUIRED_DEFINITIONS`` A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form ``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by - ``resultVar`` will also be added automatically. + ``<resultVar>`` will also be added automatically. ``CMAKE_REQUIRED_INCLUDES`` A :ref:`;-list <CMake Language Lists>` of header search paths to pass to @@ -53,10 +54,10 @@ Check if given C++ source compiles and links into an executable. associated with the check will be suppressed. The check is only performed once, with the result cached in the variable - named by ``resultVar``. Every subsequent CMake run will re-use this cached - value rather than performing the check again, even if the ``code`` changes. + named by ``<resultVar>``. Every subsequent CMake run will re-use this cached + value rather than performing the check again, even if the ``<code>`` changes. In order to force the check to be re-evaluated, the variable named by - ``resultVar`` must be manually removed from the cache. + ``<resultVar>`` must be manually removed from the cache. #]=======================================================================] @@ -132,4 +133,3 @@ macro(CHECK_CXX_SOURCE_COMPILES SOURCE VAR) endif() endif() endmacro() - diff --git a/Modules/CheckCXXSourceRuns.cmake b/Modules/CheckCXXSourceRuns.cmake index 83bf2f2..bdc2291 100644 --- a/Modules/CheckCXXSourceRuns.cmake +++ b/Modules/CheckCXXSourceRuns.cmake @@ -10,16 +10,16 @@ subsequently be run. .. command:: check_cxx_source_runs - :: + .. code-block:: cmake - check_cxx_source_runs(code resultVar) + check_cxx_source_runs(<code> <resultVar>) - Check that the source supplied in ``code`` can be compiled as a C++ source - file, linked as an executable and then run. The ``code`` must contain at - least a ``main()`` function. If the code could be built and run successfully, - the internal cache variable specified by ``resultVar`` will be set to 1, - otherwise it will be set to an value that evaluates to boolean false (e.g. - an empty string or an error message). + Check that the source supplied in ``<code>`` can be compiled as a C++ source + file, linked as an executable and then run. The ``<code>`` must contain at + least a ``main()`` function. If the ``<code>`` could be built and run + successfully, the internal cache variable specified by ``<resultVar>`` will + be set to 1, otherwise it will be set to an value that evaluates to boolean + false (e.g. an empty string or an error message). The underlying check is performed by the :command:`try_run` command. The compile and link commands can be influenced by setting any of the following @@ -34,7 +34,7 @@ subsequently be run. ``CMAKE_REQUIRED_DEFINITIONS`` A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form ``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by - ``resultVar`` will also be added automatically. + ``<resultVar>`` will also be added automatically. ``CMAKE_REQUIRED_INCLUDES`` A :ref:`;-list <CMake Language Lists>` of header search paths to pass to @@ -53,10 +53,10 @@ subsequently be run. associated with the check will be suppressed. The check is only performed once, with the result cached in the variable - named by ``resultVar``. Every subsequent CMake run will re-use this cached - value rather than performing the check again, even if the ``code`` changes. + named by ``<resultVar>``. Every subsequent CMake run will re-use this cached + value rather than performing the check again, even if the ``<code>`` changes. In order to force the check to be re-evaluated, the variable named by - ``resultVar`` must be manually removed from the cache. + ``<resultVar>`` must be manually removed from the cache. #]=======================================================================] @@ -127,4 +127,3 @@ macro(CHECK_CXX_SOURCE_RUNS SOURCE VAR) endif() endif() endmacro() - diff --git a/Modules/CheckCXXSymbolExists.cmake b/Modules/CheckCXXSymbolExists.cmake index 117a458..ce23ffd 100644 --- a/Modules/CheckCXXSymbolExists.cmake +++ b/Modules/CheckCXXSymbolExists.cmake @@ -7,10 +7,12 @@ # # Check if a symbol exists as a function, variable, or macro in C++ # -# CHECK_CXX_SYMBOL_EXISTS(<symbol> <files> <variable>) +# .. code-block:: cmake # -# Check that the <symbol> is available after including given header -# <files> and store the result in a <variable>. Specify the list of +# CHECK_CXX_SYMBOL_EXISTS(<symbol> <files> <variable>) +# +# Check that the ``<symbol>`` is available after including given header +# ``<files>`` and store the result in a ``<variable>``. Specify the list of # files in one argument as a semicolon-separated list. # CHECK_CXX_SYMBOL_EXISTS() can be used to check in C++ files, as # opposed to CHECK_SYMBOL_EXISTS(), which works only for C. @@ -24,13 +26,16 @@ # The following variables may be set before calling this macro to modify # the way the check is run: # -# :: -# -# CMAKE_REQUIRED_FLAGS = string of compile command line flags -# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) -# CMAKE_REQUIRED_INCLUDES = list of include directories -# CMAKE_REQUIRED_LIBRARIES = list of libraries to link -# CMAKE_REQUIRED_QUIET = execute quietly without messages +# ``CMAKE_REQUIRED_FLAGS`` +# string of compile command line flags +# ``CMAKE_REQUIRED_DEFINITIONS`` +# list of macros to define (-DFOO=bar) +# ``CMAKE_REQUIRED_INCLUDES`` +# list of include directories +# ``CMAKE_REQUIRED_LIBRARIES`` +# list of libraries to link +# ``CMAKE_REQUIRED_QUIET`` +# execute quietly without messages include_guard(GLOBAL) include(CheckSymbolExists) diff --git a/Modules/CheckFortranCompilerFlag.cmake b/Modules/CheckFortranCompilerFlag.cmake index 2cb2532..299cd8c 100644 --- a/Modules/CheckFortranCompilerFlag.cmake +++ b/Modules/CheckFortranCompilerFlag.cmake @@ -9,7 +9,7 @@ Check whether the Fortran compiler supports a given flag. .. command:: check_fortran_compiler_flag - :: + .. code-block:: cmake check_fortran_compiler_flag(<flag> <var>) diff --git a/Modules/CheckFortranFunctionExists.cmake b/Modules/CheckFortranFunctionExists.cmake index f3ced93..fbfa061 100644 --- a/Modules/CheckFortranFunctionExists.cmake +++ b/Modules/CheckFortranFunctionExists.cmake @@ -5,24 +5,24 @@ # CheckFortranFunctionExists # -------------------------- # -# macro which checks if the Fortran function exists +# :command:`Macro <macro>` which checks if a Fortran function exists. # -# CHECK_FORTRAN_FUNCTION_EXISTS(FUNCTION VARIABLE) +# .. code-block:: cmake # -# :: -# -# FUNCTION - the name of the Fortran function -# VARIABLE - variable to store the result -# Will be created as an internal cache variable. +# CHECK_FORTRAN_FUNCTION_EXISTS(<function> <result>) # +# where # +# ``<function>`` +# the name of the Fortran function +# ``<result>`` +# variable to store the result; will be created as an internal cache variable. # # The following variables may be set before calling this macro to modify # the way the check is run: # -# :: -# -# CMAKE_REQUIRED_LIBRARIES = list of libraries to link +# ``CMAKE_REQUIRED_LIBRARIES`` +# list of libraries to link include_guard(GLOBAL) diff --git a/Modules/CheckFortranSourceCompiles.cmake b/Modules/CheckFortranSourceCompiles.cmake index d2b0cca..977b7b4 100644 --- a/Modules/CheckFortranSourceCompiles.cmake +++ b/Modules/CheckFortranSourceCompiles.cmake @@ -9,23 +9,24 @@ Check if given Fortran source compiles and links into an executable. .. command:: check_fortran_source_compiles - :: + .. code-block:: cmake - check_fortran_source_compiles(code resultVar - [FAIL_REGEX regex1 [regex2...]] - [SRC_EXT ext] + check_fortran_source_compiles(<code> <resultVar> + [FAIL_REGEX <regex>...] + [SRC_EXT <extension>] ) - Check that the source supplied in ``code`` can be compiled as a Fortran + Checks that the source supplied in ``<code>`` can be compiled as a Fortran source file and linked as an executable (so it must contain at least a ``PROGRAM`` entry point). The result will be stored in the internal cache - variable specified by ``resultVar``, with a boolean true value for success - and boolean false for failure. If ``FAIL_REGEX`` is provided, then failure is - determined by checking if anything in the output matches any of the specified - regular expressions. + variable ``<resultVar>``, with a boolean true value for success and boolean + false for failure. + + If ``FAIL_REGEX`` is provided, then failure is determined by checking + if anything in the output matches any of the specified regular expressions. By default, the test source file will be given a ``.F`` file extension. The - ``SRC_EXT`` option can be used to override this with ``.ext`` instead. + ``SRC_EXT`` option can be used to override this with ``.<extension>`` instead. The underlying check is performed by the :command:`try_compile` command. The compile and link commands can be influenced by setting any of the following @@ -40,7 +41,7 @@ Check if given Fortran source compiles and links into an executable. ``CMAKE_REQUIRED_DEFINITIONS`` A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form ``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by - ``resultVar`` will also be added automatically. + ``<resultVar>`` will also be added automatically. ``CMAKE_REQUIRED_INCLUDES`` A :ref:`;-list <CMake Language Lists>` of header search paths to pass to @@ -59,10 +60,10 @@ Check if given Fortran source compiles and links into an executable. associated with the check will be suppressed. The check is only performed once, with the result cached in the variable - named by ``resultVar``. Every subsequent CMake run will re-use this cached - value rather than performing the check again, even if the ``code`` changes. + named by ``<resultVar>``. Every subsequent CMake run will re-use this cached + value rather than performing the check again, even if the ``<code>`` changes. In order to force the check to be re-evaluated, the variable named by - ``resultVar`` must be manually removed from the cache. + ``<resultVar>`` must be manually removed from the cache. #]=======================================================================] diff --git a/Modules/CheckFunctionExists.cmake b/Modules/CheckFunctionExists.cmake index d00aa8a..45f7a6b 100644 --- a/Modules/CheckFunctionExists.cmake +++ b/Modules/CheckFunctionExists.cmake @@ -5,24 +5,29 @@ # CheckFunctionExists # ------------------- # -# Check if a C function can be linked:: +# Check if a C function can be linked +# +# .. code-block:: cmake # # check_function_exists(<function> <variable>) # -# Check that the ``<function>`` is provided by libraries on the system and store -# the result in a ``<variable>``. ``<variable>`` will be created as an internal +# Checks that the ``<function>`` is provided by libraries on the system and store +# the result in a ``<variable>``, which will be created as an internal # cache variable. # # The following variables may be set before calling this macro to modify the # way the check is run: # -# :: -# -# CMAKE_REQUIRED_FLAGS = string of compile command line flags -# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) -# CMAKE_REQUIRED_INCLUDES = list of include directories -# CMAKE_REQUIRED_LIBRARIES = list of libraries to link -# CMAKE_REQUIRED_QUIET = execute quietly without messages +# ``CMAKE_REQUIRED_FLAGS`` +# string of compile command line flags +# ``CMAKE_REQUIRED_DEFINITIONS`` +# list of macros to define (-DFOO=bar) +# ``CMAKE_REQUIRED_INCLUDES`` +# list of include directories +# ``CMAKE_REQUIRED_LIBRARIES`` +# list of libraries to link +# ``CMAKE_REQUIRED_QUIET`` +# execute quietly without messages # # .. note:: # diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index f987d2d..eb4f9fa 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -16,7 +16,9 @@ External Project Definition The ``ExternalProject_Add()`` function creates a custom target to drive download, update/patch, configure, build, install and test steps of an - external project:: + external project: + + .. code-block:: cmake ExternalProject_Add(<name> [<option>...]) @@ -608,7 +610,9 @@ External Project Definition appended to them by following them with as many ``COMMAND ...`` options as needed (:manual:`generator expressions <cmake-generator-expressions(7)>` are - supported). For example:: + supported). For example: + + .. code-block:: cmake ExternalProject_Add(example ... # Download options, etc. @@ -627,7 +631,9 @@ Obtaining Project Properties .. command:: ExternalProject_Get_Property The ``ExternalProject_Get_Property()`` function retrieves external project - target properties:: + target properties: + + .. code-block:: cmake ExternalProject_Get_Property(<name> <prop1> [<prop2>...]) @@ -655,7 +661,9 @@ control needed to implement such step-level capabilities. The ``ExternalProject_Add_Step()`` function specifies an additional custom step for an external project defined by an earlier call to - :command:`ExternalProject_Add`:: + :command:`ExternalProject_Add`: + + .. code-block:: cmake ExternalProject_Add_Step(<name> <step> [<option>...]) @@ -722,7 +730,9 @@ control needed to implement such step-level capabilities. The ``ExternalProject_Add_StepTargets()`` function generates targets for the steps listed. The name of each created target will be of the form - ``<name>-<step>``:: + ``<name>-<step>``: + + .. code-block:: cmake ExternalProject_Add_StepTargets(<name> [NO_DEPENDS] <step1> [<step2>...]) @@ -773,7 +783,9 @@ control needed to implement such step-level capabilities. The ``ExternalProject_Add_StepDependencies()`` function can be used to add dependencies to a step. The dependencies added must be targets CMake already knows about (these can be ordinary executable or library targets, custom - targets or even step targets of another external project):: + targets or even step targets of another external project): + + .. code-block:: cmake ExternalProject_Add_StepDependencies(<name> <step> <target1> [<target2>...]) diff --git a/Modules/FindFontconfig.cmake b/Modules/FindFontconfig.cmake new file mode 100644 index 0000000..96e1e76 --- /dev/null +++ b/Modules/FindFontconfig.cmake @@ -0,0 +1,101 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindFontconfig +-------------- + +Find Fontconfig headers and library. + +Imported Targets +^^^^^^^^^^^^^^^^ + +``Fontconfig::Fontconfig`` + The Fontconfig library, if found. + +Result Variables +^^^^^^^^^^^^^^^^ + +This will define the following variables in your project: + +``FONTCONFIG_FOUND`` + true if (the requested version of) Fontconfig is available. +``FONTCONFIG_VERSION`` + the version of Fontconfig. +``FONTCONFIG_LIBRARIES`` + the libraries to link against to use Fontconfig. +``FONTCONFIG_INCLUDE_DIRS`` + where to find the Fontconfig headers. +``FONTCONFIG_COMPILE_OPTIONS`` + this should be passed to target_compile_options(), if the + target is not used for linking + +#]=======================================================================] + + +# use pkg-config to get the directories and then use these values +# in the FIND_PATH() and FIND_LIBRARY() calls +find_package(PkgConfig QUIET) +pkg_check_modules(PKG_FONTCONFIG QUIET fontconfig) +set(FONTCONFIG_COMPILE_OPTIONS ${PKG_FONTCONFIG_CFLAGS_OTHER}) +set(FONTCONFIG_VERSION ${PKG_FONTCONFIG_VERSION}) + +find_path( FONTCONFIG_INCLUDE_DIR + NAMES + fontconfig/fontconfig.h + HINTS + ${PKG_FONTCONFIG_INCLUDE_DIRS} + /usr/X11/include +) + +find_library( FONTCONFIG_LIBRARY + NAMES + fontconfig + PATHS + ${PKG_FONTCONFIG_LIBRARY_DIRS} +) + +if (FONTCONFIG_INCLUDE_DIR AND NOT FONTCONFIG_VERSION) + file(STRINGS ${FONTCONFIG_INCLUDE_DIR}/fontconfig/fontconfig.h _contents REGEX "^#define[ \t]+FC_[A-Z]+[ \t]+[0-9]+$") + unset(FONTCONFIG_VERSION) + foreach(VPART MAJOR MINOR REVISION) + foreach(VLINE ${_contents}) + if(VLINE MATCHES "^#define[\t ]+FC_${VPART}[\t ]+([0-9]+)$") + set(FONTCONFIG_VERSION_PART "${CMAKE_MATCH_1}") + if(FONTCONFIG_VERSION) + string(APPEND FONTCONFIG_VERSION ".${FONTCONFIG_VERSION_PART}") + else() + set(FONTCONFIG_VERSION "${FONTCONFIG_VERSION_PART}") + endif() + endif() + endforeach() + endforeach() +endif () + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Fontconfig + FOUND_VAR + FONTCONFIG_FOUND + REQUIRED_VARS + FONTCONFIG_LIBRARY + FONTCONFIG_INCLUDE_DIR + VERSION_VAR + FONTCONFIG_VERSION +) + + +if(FONTCONFIG_FOUND AND NOT TARGET Fontconfig::Fontconfig) + add_library(Fontconfig::Fontconfig UNKNOWN IMPORTED) + set_target_properties(Fontconfig::Fontconfig PROPERTIES + IMPORTED_LOCATION "${FONTCONFIG_LIBRARY}" + INTERFACE_COMPILE_OPTIONS "${FONTCONFIG_COMPILE_OPTIONS}" + INTERFACE_INCLUDE_DIRECTORIES "${FONTCONFIG_INCLUDE_DIR}" + ) +endif() + +mark_as_advanced(FONTCONFIG_LIBRARY FONTCONFIG_INCLUDE_DIR) + +if(FONTCONFIG_FOUND) + set(FONTCONFIG_LIBRARIES ${FONTCONFIG_LIBRARY}) + set(FONTCONFIG_INCLUDE_DIRS ${FONTCONFIG_INCLUDE_DIR}) +endif() diff --git a/Modules/FindLibinput.cmake b/Modules/FindLibinput.cmake index 1057c91..c1fe455 100644 --- a/Modules/FindLibinput.cmake +++ b/Modules/FindLibinput.cmake @@ -79,5 +79,4 @@ mark_as_advanced(Libinput_LIBRARY Libinput_INCLUDE_DIR) if(Libinput_FOUND) set(Libinput_LIBRARIES ${Libinput_LIBRARY}) set(Libinput_INCLUDE_DIRS ${Libinput_INCLUDE_DIR}) - set(Libinput_VERSION_STRING ${Libinput_VERSION}) endif() diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index 06beb7d..a45aef2 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -9,12 +9,14 @@ A ``pkg-config`` module for CMake. Finds the ``pkg-config`` executable and adds the :command:`pkg_get_variable`, :command:`pkg_check_modules` and :command:`pkg_search_module` commands. The -following variables will also be set:: +following variables will also be set: - PKG_CONFIG_FOUND ... if pkg-config executable was found - PKG_CONFIG_EXECUTABLE ... pathname of the pkg-config program - PKG_CONFIG_VERSION_STRING ... the version of the pkg-config program found - (since CMake 2.8.8) +``PKG_CONFIG_FOUND`` + if pkg-config executable was found +``PKG_CONFIG_EXECUTABLE`` + pathname of the pkg-config program +``PKG_CONFIG_VERSION_STRING`` + version of pkg-config (since CMake 2.8.8) #]========================================] @@ -86,7 +88,9 @@ endmacro() .. command:: pkg_get_variable Retrieves the value of a pkg-config variable ``varName`` and stores it in the - result variable ``resultVar`` in the calling scope. :: + result variable ``resultVar`` in the calling scope. + + .. code-block:: cmake pkg_get_variable(<resultVar> <moduleName> <varName>) @@ -512,7 +516,9 @@ endmacro() .. command:: pkg_check_modules Checks for all the given modules, setting a variety of result variables in - the calling scope. :: + the calling scope. + + .. code-block:: cmake pkg_check_modules(<prefix> [REQUIRED] [QUIET] @@ -543,27 +549,36 @@ endmacro() Each ``<moduleSpec>`` can be either a bare module name or it can be a module name with a version constraint (operators ``=``, ``<``, ``>``, ``<=`` and ``>=`` are supported). The following are examples for a module - named ``foo`` with various constraints:: - - foo # Any version matches - foo<2 # Only match versions before 2 - foo>=3.1 # Match any version from 3.1 or later - foo=1.2.3 # Foo must be exactly version 1.2.3 - - The following variables may be set upon return. Two sets of values exist, - one for the common case (``<XXX> = <prefix>``) and another for the - information ``pkg-config`` provides when it is called with the ``--static`` - option (``<XXX> = <prefix>_STATIC``):: - - <XXX>_FOUND ... set to 1 if module(s) exist - <XXX>_LIBRARIES ... only the libraries (without the '-l') - <XXX>_LINK_LIBRARIES ... the libraries and their absolute paths - <XXX>_LIBRARY_DIRS ... the paths of the libraries (without the '-L') - <XXX>_LDFLAGS ... all required linker flags - <XXX>_LDFLAGS_OTHER ... all other linker flags - <XXX>_INCLUDE_DIRS ... the '-I' preprocessor flags (without the '-I') - <XXX>_CFLAGS ... all required cflags - <XXX>_CFLAGS_OTHER ... the other compiler flags + named ``foo`` with various constraints: + + - ``foo`` matches any version. + - ``foo<2`` only matches versions before 2. + - ``foo>=3.1`` matches any version from 3.1 or later. + - ``foo=1.2.3`` requires that foo must be exactly version 1.2.3. + + The following variables may be set upon return. Two sets of values exist: + One for the common case (``<XXX> = <prefix>``) and another for the + information ``pkg-config`` provides when called with the ``--static`` + option (``<XXX> = <prefix>_STATIC``). + + ``<XXX>_FOUND`` + set to 1 if module(s) exist + ``<XXX>_LIBRARIES`` + only the libraries (without the '-l') + ``<XXX>_LINK_LIBRARIES`` + the libraries and their absolute paths + ``<XXX>_LIBRARY_DIRS`` + the paths of the libraries (without the '-L') + ``<XXX>_LDFLAGS`` + all required linker flags + ``<XXX>_LDFLAGS_OTHER`` + all other linker flags + ``<XXX>_INCLUDE_DIRS`` + the '-I' preprocessor flags (without the '-I') + ``<XXX>_CFLAGS`` + all required cflags + ``<XXX>_CFLAGS_OTHER`` + the other compiler flags All but ``<XXX>_FOUND`` may be a :ref:`;-list <CMake Language Lists>` if the associated variable returned from ``pkg-config`` has multiple values. @@ -571,14 +586,18 @@ endmacro() There are some special variables whose prefix depends on the number of ``<moduleSpec>`` given. When there is only one ``<moduleSpec>``, ``<YYY>`` will simply be ``<prefix>``, but if two or more ``<moduleSpec>`` - items are given, ``<YYY>`` will be ``<prefix>_<moduleName>``:: + items are given, ``<YYY>`` will be ``<prefix>_<moduleName>``. - <YYY>_VERSION ... version of the module - <YYY>_PREFIX ... prefix directory of the module - <YYY>_INCLUDEDIR ... include directory of the module - <YYY>_LIBDIR ... lib directory of the module + ``<YYY>_VERSION`` + version of the module + ``<YYY>_PREFIX`` + prefix directory of the module + ``<YYY>_INCLUDEDIR`` + include directory of the module + ``<YYY>_LIBDIR`` + lib directory of the module - Examples + Examples: .. code-block:: cmake @@ -638,7 +657,9 @@ endmacro() The behavior of this command is the same as :command:`pkg_check_modules`, except that rather than checking for all the specified modules, it searches - for just the first successful match. :: + for just the first successful match. + + .. code-block:: cmake pkg_search_module(<prefix> [REQUIRED] [QUIET] @@ -647,7 +668,7 @@ endmacro() [IMPORTED_TARGET [GLOBAL]] <moduleSpec> [<moduleSpec>...]) - Examples + Example: .. code-block:: cmake diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index beafab2..6960b7f 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 13) -set(CMake_VERSION_PATCH 20181018) +set(CMake_VERSION_PATCH 20181019) #set(CMake_VERSION_RC 1) diff --git a/Source/cmComputeComponentGraph.cxx b/Source/cmComputeComponentGraph.cxx index a7dc1ca..5820df6 100644 --- a/Source/cmComputeComponentGraph.cxx +++ b/Source/cmComputeComponentGraph.cxx @@ -125,8 +125,8 @@ void cmComputeComponentGraph::TransferEdges() if (i_component != j_component) { // We do not attempt to combine duplicate edges, but instead // store the inter-component edges with suitable multiplicity. - this->ComponentGraph[i_component].emplace_back(j_component, - ni.IsStrong()); + this->ComponentGraph[i_component].emplace_back( + j_component, ni.IsStrong(), ni.GetBacktrace()); } } } diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index aa17de6..4717cf6 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -6,6 +6,7 @@ #include "cmComputeComponentGraph.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmStateTypes.h" @@ -419,7 +420,8 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep) // This shared library dependency must follow the item that listed // it. - this->EntryConstraintGraph[dep.DependerIndex].push_back(index); + this->EntryConstraintGraph[dep.DependerIndex].emplace_back( + index, true, cmListFileBacktrace()); // Target items may have their own dependencies. if (entry.Target) { @@ -522,7 +524,8 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index, // The dependee must come after the depender. if (depender_index >= 0) { - this->EntryConstraintGraph[depender_index].push_back(dependee_index); + this->EntryConstraintGraph[depender_index].emplace_back( + dependee_index, false, cmListFileBacktrace()); } else { // This is a direct dependency of the target being linked. this->OriginalEntries.push_back(dependee_index); @@ -565,7 +568,7 @@ cmLinkItem cmComputeLinkDepends::ResolveLinkItem(int depender_index, from = depender; } } - return from->ResolveLinkItem(name); + return from->ResolveLinkItem(name, cmListFileBacktrace()); } void cmComputeLinkDepends::InferDependencies() @@ -594,7 +597,10 @@ void cmComputeLinkDepends::InferDependencies() // Add the inferred dependencies to the graph. cmGraphEdgeList& edges = this->EntryConstraintGraph[depender_index]; - edges.insert(edges.end(), common.begin(), common.end()); + edges.reserve(edges.size() + common.size()); + for (auto const& c : common) { + edges.emplace_back(c, true, cmListFileBacktrace()); + } } } diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 268e749..f8ac333 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -6,6 +6,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmLinkItem.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmPolicies.h" @@ -22,8 +23,6 @@ #include <stdio.h> #include <utility> -class cmListFileBacktrace; - /* This class is meant to analyze inter-target dependencies globally @@ -152,6 +151,7 @@ void cmComputeTargetDepends::GetTargetDirectDepends(cmGeneratorTarget const* t, cmGeneratorTarget const* dep = this->Targets[ni]; cmTargetDependSet::iterator di = deps.insert(dep).first; di->SetType(ni.IsStrong()); + di->SetBacktrace(ni.GetBacktrace()); } } @@ -208,7 +208,8 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) for (cmSourceFile const* o : objectFiles) { std::string const& objLib = o->GetObjectLibrary(); if (!objLib.empty()) { - cmLinkItem const& objItem = depender->ResolveLinkItem(objLib); + cmLinkItem const& objItem = + depender->ResolveLinkItem(objLib, cmListFileBacktrace()); if (emitted.insert(objItem).second) { if (depender->GetType() != cmStateEnums::EXECUTABLE && depender->GetType() != cmStateEnums::STATIC_LIBRARY && @@ -230,7 +231,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) cmLinkImplementation const* impl = depender->GetLinkImplementation(it); // A target should not depend on itself. - emitted.insert(cmLinkItem(depender)); + emitted.insert(cmLinkItem(depender, cmListFileBacktrace())); for (cmLinkImplItem const& lib : impl->Libraries) { // Don't emit the same library twice for this target. if (emitted.insert(lib).second) { @@ -246,7 +247,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) std::set<cmLinkItem> const& tutils = depender->GetUtilityItems(); std::set<cmLinkItem> emitted; // A target should not depend on itself. - emitted.insert(cmLinkItem(depender)); + emitted.insert(cmLinkItem(depender, cmListFileBacktrace())); for (cmLinkItem const& litem : tutils) { // Don't emit the same utility twice for this target. if (emitted.insert(litem).second) { @@ -258,7 +259,8 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) void cmComputeTargetDepends::AddInterfaceDepends( int depender_index, const cmGeneratorTarget* dependee, - const std::string& config, std::set<cmLinkItem>& emitted) + cmListFileBacktrace const& dependee_backtrace, const std::string& config, + std::set<cmLinkItem>& emitted) { cmGeneratorTarget const* depender = this->Targets[depender_index]; if (cmLinkInterface const* iface = @@ -266,8 +268,13 @@ void cmComputeTargetDepends::AddInterfaceDepends( for (cmLinkItem const& lib : iface->Libraries) { // Don't emit the same library twice for this target. if (emitted.insert(lib).second) { - this->AddTargetDepend(depender_index, lib, true); - this->AddInterfaceDepends(depender_index, lib, config, emitted); + // Inject the backtrace of the original link dependency whose + // link interface we are adding. This indicates the line of + // code in the project that caused this dependency to be added. + cmLinkItem libBT = lib; + libBT.Backtrace = dependee_backtrace; + this->AddTargetDepend(depender_index, libBT, true); + this->AddInterfaceDepends(depender_index, libBT, config, emitted); } } } @@ -289,8 +296,9 @@ void cmComputeTargetDepends::AddInterfaceDepends( if (dependee) { // A target should not depend on itself. - emitted.insert(cmLinkItem(depender)); - this->AddInterfaceDepends(depender_index, dependee, config, emitted); + emitted.insert(cmLinkItem(depender, cmListFileBacktrace())); + this->AddInterfaceDepends(depender_index, dependee, + dependee_name.Backtrace, config, emitted); } } @@ -327,13 +335,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, e << "The dependency target \"" << dependee_name << "\" of target \"" << depender->GetName() << "\" does not exist."; - cmListFileBacktrace const* backtrace = - depender->GetUtilityBacktrace(dependee_name.AsStr()); - if (backtrace) { - cm->IssueMessage(messageType, e.str(), *backtrace); - } else { - cm->IssueMessage(messageType, e.str()); - } + cm->IssueMessage(messageType, e.str(), dependee_name.Backtrace); } } @@ -346,13 +348,14 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, } if (dependee) { - this->AddTargetDepend(depender_index, dependee, linking); + this->AddTargetDepend(depender_index, dependee, dependee_name.Backtrace, + linking); } } -void cmComputeTargetDepends::AddTargetDepend(int depender_index, - const cmGeneratorTarget* dependee, - bool linking) +void cmComputeTargetDepends::AddTargetDepend( + int depender_index, cmGeneratorTarget const* dependee, + cmListFileBacktrace const& dependee_backtrace, bool linking) { if (dependee->IsImported() || dependee->GetType() == cmStateEnums::INTERFACE_LIBRARY) { @@ -361,7 +364,8 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, std::set<cmLinkItem> const& utils = dependee->GetUtilityItems(); for (cmLinkItem const& i : utils) { if (cmGeneratorTarget const* transitive_dependee = i.Target) { - this->AddTargetDepend(depender_index, transitive_dependee, false); + this->AddTargetDepend(depender_index, transitive_dependee, i.Backtrace, + false); } } } else { @@ -373,7 +377,8 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index, int dependee_index = tii->second; // Add this entry to the dependency graph. - this->InitialGraph[depender_index].emplace_back(dependee_index, !linking); + this->InitialGraph[depender_index].emplace_back(dependee_index, !linking, + dependee_backtrace); } } @@ -507,7 +512,7 @@ bool cmComputeTargetDepends::IntraComponent(std::vector<int> const& cmap, for (cmGraphEdge const& edge : el) { int j = edge; if (cmap[j] == c && edge.IsStrong()) { - this->FinalGraph[i].emplace_back(j, true); + this->FinalGraph[i].emplace_back(j, true, edge.GetBacktrace()); if (!this->IntraComponent(cmap, c, j, head, emitted, visited)) { return false; } @@ -516,7 +521,7 @@ bool cmComputeTargetDepends::IntraComponent(std::vector<int> const& cmap, // Prepend to a linear linked-list of intra-component edges. if (*head >= 0) { - this->FinalGraph[i].emplace_back(*head, false); + this->FinalGraph[i].emplace_back(*head, false, cmListFileBacktrace()); } else { this->ComponentTail[c] = i; } @@ -567,7 +572,7 @@ bool cmComputeTargetDepends::ComputeFinalDepends( int dependee_component = ni; int dependee_component_head = this->ComponentHead[dependee_component]; this->FinalGraph[depender_component_tail].emplace_back( - dependee_component_head, ni.IsStrong()); + dependee_component_head, ni.IsStrong(), ni.GetBacktrace()); } } return true; diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h index 3046e8a..3840bd7 100644 --- a/Source/cmComputeTargetDepends.h +++ b/Source/cmComputeTargetDepends.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmGraphAdjacencyList.h" +#include "cmListFileCache.h" #include <map> #include <set> @@ -47,6 +48,7 @@ private: void AddTargetDepend(int depender_index, cmLinkItem const& dependee_name, bool linking); void AddTargetDepend(int depender_index, cmGeneratorTarget const* dependee, + cmListFileBacktrace const& dependee_backtrace, bool linking); bool ComputeFinalDepends(cmComputeComponentGraph const& ccg); void AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name, @@ -54,6 +56,7 @@ private: std::set<cmLinkItem>& emitted); void AddInterfaceDepends(int depender_index, cmGeneratorTarget const* dependee, + cmListFileBacktrace const& dependee_backtrace, const std::string& config, std::set<cmLinkItem>& emitted); cmGlobalGenerator* GlobalGenerator; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index ea283c6..fa489e2 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -674,13 +674,13 @@ std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const { if (!this->UtilityItemsDone) { this->UtilityItemsDone = true; - std::set<std::string> const& utilities = this->GetUtilities(); - for (std::string const& i : utilities) { + std::set<BT<std::string>> const& utilities = this->GetUtilities(); + for (BT<std::string> const& i : utilities) { if (cmGeneratorTarget* gt = - this->LocalGenerator->FindGeneratorTargetToUse(i)) { - this->UtilityItems.insert(cmLinkItem(gt)); + this->LocalGenerator->FindGeneratorTargetToUse(i.Value)) { + this->UtilityItems.insert(cmLinkItem(gt, i.Backtrace)); } else { - this->UtilityItems.insert(cmLinkItem(i)); + this->UtilityItems.insert(cmLinkItem(i.Value, i.Backtrace)); } } } @@ -1710,17 +1710,11 @@ cmListFileBacktrace cmGeneratorTarget::GetBacktrace() const return this->Target->GetBacktrace(); } -const std::set<std::string>& cmGeneratorTarget::GetUtilities() const +const std::set<BT<std::string>>& cmGeneratorTarget::GetUtilities() const { return this->Target->GetUtilities(); } -const cmListFileBacktrace* cmGeneratorTarget::GetUtilityBacktrace( - const std::string& u) const -{ - return this->Target->GetUtilityBacktrace(u); -} - bool cmGeneratorTarget::HaveWellDefinedOutputFiles() const { return this->GetType() == cmStateEnums::STATIC_LIBRARY || @@ -4618,6 +4612,7 @@ void cmGeneratorTarget::ReportPropertyOrigin( } void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names, + cmListFileBacktrace const& bt, std::vector<cmLinkItem>& items) const { for (std::string const& n : names) { @@ -4625,7 +4620,7 @@ void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names, if (name == this->GetName() || name.empty()) { continue; } - items.push_back(this->ResolveLinkItem(name)); + items.push_back(this->ResolveLinkItem(name, bt)); } } @@ -4647,7 +4642,7 @@ void cmGeneratorTarget::ExpandLinkItems( false, headTarget, this, &dagChecker), libs); - this->LookupLinkItems(libs, items); + this->LookupLinkItems(libs, cge->GetBacktrace(), items); hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition(); } @@ -5200,7 +5195,7 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface( iface.HadHeadSensitiveCondition); std::vector<std::string> deps; cmSystemTools::ExpandListArgument(info->SharedDeps, deps); - this->LookupLinkItems(deps, iface.SharedDeps); + this->LookupLinkItems(deps, cmListFileBacktrace(), iface.SharedDeps); } return &iface; @@ -5736,7 +5731,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } // The entry is meant for this configuration. - impl.Libraries.emplace_back(this->ResolveLinkItem(name), *btIt, + impl.Libraries.emplace_back(this->ResolveLinkItem(name, *btIt), evaluated != *le); } @@ -5764,7 +5759,8 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( continue; } // Support OLD behavior for CMP0003. - impl.WrongConfigLibraries.push_back(this->ResolveLinkItem(name)); + impl.WrongConfigLibraries.push_back( + this->ResolveLinkItem(name, cmListFileBacktrace())); } } } @@ -5811,12 +5807,13 @@ cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference( return resolved; } -cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name) const +cmLinkItem cmGeneratorTarget::ResolveLinkItem( + std::string const& name, cmListFileBacktrace const& bt) const { TargetOrString resolved = this->ResolveTargetReference(name); if (!resolved.Target) { - return cmLinkItem(resolved.String); + return cmLinkItem(resolved.String, bt); } // Skip targets that will not really be linked. This is probably a @@ -5824,10 +5821,10 @@ cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name) const // within the project. if (resolved.Target->GetType() == cmStateEnums::EXECUTABLE && !resolved.Target->IsExecutableWithExports()) { - return cmLinkItem(resolved.Target->GetName()); + return cmLinkItem(resolved.Target->GetName(), bt); } - return cmLinkItem(resolved.Target); + return cmLinkItem(resolved.Target, bt); } std::string cmGeneratorTarget::GetPDBDirectory(const std::string& config) const diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 98669c3..7de306e 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -273,8 +273,7 @@ public: cmListFileBacktrace GetBacktrace() const; - std::set<std::string> const& GetUtilities() const; - cmListFileBacktrace const* GetUtilityBacktrace(const std::string& u) const; + std::set<BT<std::string>> const& GetUtilities() const; bool LinkLanguagePropagatesToDependents() const { @@ -362,7 +361,8 @@ public: }; TargetOrString ResolveTargetReference(std::string const& name) const; - cmLinkItem ResolveLinkItem(std::string const& name) const; + cmLinkItem ResolveLinkItem(std::string const& name, + cmListFileBacktrace const& bt) const; // Compute the set of languages compiled by the target. This is // computed every time it is called because the languages can change @@ -838,6 +838,7 @@ private: std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition) const; void LookupLinkItems(std::vector<std::string> const& names, + cmListFileBacktrace const& bt, std::vector<cmLinkItem>& items) const; void GetSourceFiles(std::vector<std::string>& files, diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index f513403..8c69f42 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -19,6 +19,7 @@ #include "cmGeneratedFileStream.h" #include "cmGeneratorExpressionEvaluationFile.h" #include "cmGeneratorTarget.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmLocalNinjaGenerator.h" #include "cmMakefile.h" @@ -1008,10 +1009,11 @@ void cmGlobalNinjaGenerator::AppendTargetDepends( { if (target->GetType() == cmStateEnums::GLOBAL_TARGET) { // These depend only on other CMake-provided targets, e.g. "all". - std::set<std::string> const& utils = target->GetUtilities(); - for (std::string const& util : utils) { + std::set<BT<std::string>> const& utils = target->GetUtilities(); + for (BT<std::string> const& util : utils) { std::string d = - target->GetLocalGenerator()->GetCurrentBinaryDirectory() + "/" + util; + target->GetLocalGenerator()->GetCurrentBinaryDirectory() + "/" + + util.Value; outputs.push_back(this->ConvertToNinjaPath(d)); } } else { diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index 0b086b0..a216346 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -159,7 +159,7 @@ void cmGlobalVisualStudio71Generator::WriteProjectDepends( // executables to the libraries it uses are also done here void cmGlobalVisualStudio71Generator::WriteExternalProject( std::ostream& fout, const std::string& name, const char* location, - const char* typeGuid, const std::set<std::string>& depends) + const char* typeGuid, const std::set<BT<std::string>>& depends) { fout << "Project(\"{" << (typeGuid ? typeGuid : this->ExternalProjectType(location)) @@ -171,9 +171,10 @@ void cmGlobalVisualStudio71Generator::WriteExternalProject( // project instead of in the global section if (!depends.empty()) { fout << "\tProjectSection(ProjectDependencies) = postProject\n"; - for (std::string const& it : depends) { - if (!it.empty()) { - fout << "\t\t{" << this->GetGUID(it) << "} = {" << this->GetGUID(it) + for (BT<std::string> const& it : depends) { + std::string const& dep = it.Value; + if (!dep.empty()) { + fout << "\t\t{" << this->GetGUID(dep) << "} = {" << this->GetGUID(dep) << "}\n"; } } diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h index 054c342..b6e3131 100644 --- a/Source/cmGlobalVisualStudio71Generator.h +++ b/Source/cmGlobalVisualStudio71Generator.h @@ -33,7 +33,7 @@ protected: const std::string& platformMapping = "") override; void WriteExternalProject(std::ostream& fout, const std::string& name, const char* path, const char* typeGuid, - const std::set<std::string>& depends) override; + const std::set<BT<std::string>>& depends) override; void WriteSLNHeader(std::ostream& fout) override; // Folders are not supported by VS 7.1. diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 0c9dd88..251478d 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -145,7 +145,7 @@ protected: virtual void WriteExternalProject( std::ostream& fout, const std::string& name, const char* path, - const char* typeGuid, const std::set<std::string>& dependencies) = 0; + const char* typeGuid, const std::set<BT<std::string>>& dependencies) = 0; std::string ConvertToSolutionPath(const char* path); diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index ba138c2..b155d9c 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -315,9 +315,9 @@ bool cmGlobalVisualStudio8Generator::NeedLinkLibraryDependencies( cmGeneratorTarget* target) { // Look for utility dependencies that magically link. - for (std::string const& ui : target->GetUtilities()) { + for (BT<std::string> const& ui : target->GetUtilities()) { if (cmGeneratorTarget* depTarget = - target->GetLocalGenerator()->FindGeneratorTargetToUse(ui)) { + target->GetLocalGenerator()->FindGeneratorTargetToUse(ui.Value)) { if (depTarget->GetType() != cmStateEnums::INTERFACE_LIBRARY && depTarget->GetProperty("EXTERNAL_MSPROJECT")) { // This utility dependency names an external .vcproj target. diff --git a/Source/cmGraphAdjacencyList.h b/Source/cmGraphAdjacencyList.h index 6a0a799..fb2eee2 100644 --- a/Source/cmGraphAdjacencyList.h +++ b/Source/cmGraphAdjacencyList.h @@ -5,6 +5,8 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include "cmListFileCache.h" + #include <vector> /** @@ -15,18 +17,22 @@ class cmGraphEdge { public: - cmGraphEdge(int n = 0, bool s = true) + cmGraphEdge(int n, bool s, cmListFileBacktrace const& bt) : Dest(n) , Strong(s) + , Backtrace(bt) { } operator int() const { return this->Dest; } bool IsStrong() const { return this->Strong; } + cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; } + private: int Dest; bool Strong; + cmListFileBacktrace Backtrace; }; struct cmGraphEdgeList : public std::vector<cmGraphEdge> { diff --git a/Source/cmLinkItem.cxx b/Source/cmLinkItem.cxx index 69b6821..121731d 100644 --- a/Source/cmLinkItem.cxx +++ b/Source/cmLinkItem.cxx @@ -12,15 +12,18 @@ cmLinkItem::cmLinkItem() { } -cmLinkItem::cmLinkItem(std::string const& n) +cmLinkItem::cmLinkItem(std::string const& n, cmListFileBacktrace const& bt) : String(n) , Target(nullptr) + , Backtrace(bt) { } -cmLinkItem::cmLinkItem(cmGeneratorTarget const* t) +cmLinkItem::cmLinkItem(cmGeneratorTarget const* t, + cmListFileBacktrace const& bt) : String() , Target(t) + , Backtrace(bt) { } @@ -58,15 +61,12 @@ std::ostream& operator<<(std::ostream& os, cmLinkItem const& item) cmLinkImplItem::cmLinkImplItem() : cmLinkItem() - , Backtrace() , FromGenex(false) { } -cmLinkImplItem::cmLinkImplItem(cmLinkItem item, cmListFileBacktrace const& bt, - bool fromGenex) +cmLinkImplItem::cmLinkImplItem(cmLinkItem item, bool fromGenex) : cmLinkItem(std::move(item)) - , Backtrace(bt) , FromGenex(fromGenex) { } diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h index 74fd298..e1ddd22 100644 --- a/Source/cmLinkItem.h +++ b/Source/cmLinkItem.h @@ -24,10 +24,11 @@ class cmLinkItem public: cmLinkItem(); - explicit cmLinkItem(std::string const& s); - explicit cmLinkItem(cmGeneratorTarget const* t); + cmLinkItem(std::string const& s, cmListFileBacktrace const& bt); + cmLinkItem(cmGeneratorTarget const* t, cmListFileBacktrace const& bt); std::string const& AsStr() const; cmGeneratorTarget const* Target; + cmListFileBacktrace Backtrace; friend bool operator<(cmLinkItem const& l, cmLinkItem const& r); friend bool operator==(cmLinkItem const& l, cmLinkItem const& r); friend std::ostream& operator<<(std::ostream& os, cmLinkItem const& item); @@ -37,9 +38,7 @@ class cmLinkImplItem : public cmLinkItem { public: cmLinkImplItem(); - cmLinkImplItem(cmLinkItem item, cmListFileBacktrace const& bt, - bool fromGenex); - cmListFileBacktrace Backtrace; + cmLinkImplItem(cmLinkItem item, bool fromGenex); bool FromGenex; }; diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 4d7e1e2..d0495f7 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -9,10 +9,10 @@ #include "cmSystemTools.h" #include "cmake.h" -#include <algorithm> #include <assert.h> #include <memory> #include <sstream> +#include <utility> cmCommandContext::cmCommandName& cmCommandContext::cmCommandName::operator=( std::string const& name) @@ -474,3 +474,21 @@ bool operator!=(const cmListFileContext& lhs, const cmListFileContext& rhs) { return !(lhs == rhs); } + +std::ostream& operator<<(std::ostream& os, BT<std::string> const& s) +{ + return os << s.Value; +} + +std::vector<BT<std::string>> ExpandListWithBacktrace( + const char* list, cmListFileBacktrace const& bt) +{ + std::vector<BT<std::string>> result; + std::vector<std::string> tmp; + cmSystemTools::ExpandListArgument(list, tmp); + result.reserve(tmp.size()); + for (std::string& i : tmp) { + result.emplace_back(std::move(i), bt); + } + return result; +} diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h index 3d3afdf..7c2802e 100644 --- a/Source/cmListFileCache.h +++ b/Source/cmListFileCache.h @@ -9,6 +9,7 @@ #include <memory> // IWYU pragma: keep #include <stddef.h> #include <string> +#include <utility> #include <vector> #include "cmStateSnapshot.h" @@ -169,6 +170,37 @@ private: cmListFileBacktrace(std::shared_ptr<Entry const> top); }; +// Wrap type T as a value with a backtrace. For purposes of +// ordering and equality comparison, only the original value is +// used. The backtrace is considered incidental. +template <typename T> +class BT +{ +public: + BT(T v = T(), cmListFileBacktrace bt = cmListFileBacktrace()) + : Value(std::move(v)) + , Backtrace(std::move(bt)) + { + } + T Value; + cmListFileBacktrace Backtrace; + friend bool operator==(BT<T> const& l, BT<T> const& r) + { + return l.Value == r.Value; + } + friend bool operator<(BT<T> const& l, BT<T> const& r) + { + return l.Value < r.Value; + } + friend bool operator==(BT<T> const& l, T const& r) { return l.Value == r; } + friend bool operator==(T const& l, BT<T> const& r) { return l == r.Value; } +}; + +std::ostream& operator<<(std::ostream& os, BT<std::string> const& s); + +std::vector<BT<std::string>> ExpandListWithBacktrace( + const char* list, cmListFileBacktrace const& bt = cmListFileBacktrace()); + struct cmListFile { bool ParseFile(const char* path, cmMessenger* messenger, diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 68cdef0..6a535c1 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -17,6 +17,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmGlobalUnixMakefileGenerator3.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmMakefileTargetGenerator.h" @@ -1546,8 +1547,10 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( if (!text) { text = "Running external command ..."; } - depends.insert(depends.end(), gt->GetUtilities().begin(), - gt->GetUtilities().end()); + depends.reserve(gt->GetUtilities().size()); + for (BT<std::string> const& u : gt->GetUtilities()) { + depends.push_back(u.Value); + } this->AppendEcho(commands, text, cmLocalUnixMakefileGenerator3::EchoGlobal); diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 6bc3b61..7700767 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -12,6 +12,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmLinkItem.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmOutputConverter.h" @@ -940,8 +941,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() new cmGeneratorTarget(autogenTarget, localGen)); // Forward origin utilities to autogen target - for (std::string const& depName : this->Target->Target->GetUtilities()) { - autogenTarget->AddUtility(depName, makefile); + for (BT<std::string> const& depName : this->Target->GetUtilities()) { + autogenTarget->AddUtility(depName.Value, makefile); } // Add additional autogen target dependencies to autogen target for (cmTarget* depTarget : this->AutogenTarget.DependTargets) { diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index f0d6519..1458f01 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -486,24 +486,10 @@ cmGlobalGenerator* cmTarget::GetGlobalGenerator() const return this->GetMakefile()->GetGlobalGenerator(); } -void cmTarget::AddUtility(const std::string& u, cmMakefile* makefile) +void cmTarget::AddUtility(std::string const& u, cmMakefile* mf) { - if (this->Utilities.insert(u).second && makefile) { - this->UtilityBacktraces.insert( - std::make_pair(u, makefile->GetBacktrace())); - } -} - -cmListFileBacktrace const* cmTarget::GetUtilityBacktrace( - const std::string& u) const -{ - std::map<std::string, cmListFileBacktrace>::const_iterator i = - this->UtilityBacktraces.find(u); - if (i == this->UtilityBacktraces.end()) { - return nullptr; - } - - return &i->second; + BT<std::string> util(u, mf ? mf->GetBacktrace() : cmListFileBacktrace()); + this->Utilities.insert(util); } cmListFileBacktrace const& cmTarget::GetBacktrace() const diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 694de1c..aa2859d 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -190,10 +190,12 @@ public: * name as would be specified to the ADD_EXECUTABLE or UTILITY_SOURCE * commands. It is not a full path nor does it have an extension. */ - void AddUtility(const std::string& u, cmMakefile* makefile = nullptr); + void AddUtility(std::string const& u, cmMakefile* mf = nullptr); ///! Get the utilities used by this target - std::set<std::string> const& GetUtilities() const { return this->Utilities; } - cmListFileBacktrace const* GetUtilityBacktrace(const std::string& u) const; + std::set<BT<std::string>> const& GetUtilities() const + { + return this->Utilities; + } ///! Set/Get a property of this target file void SetProperty(const std::string& prop, const char* value); @@ -307,8 +309,7 @@ private: bool IsGeneratorProvided; cmPropertyMap Properties; std::set<std::string> SystemIncludeDirectories; - std::set<std::string> Utilities; - std::map<std::string, cmListFileBacktrace> UtilityBacktraces; + std::set<BT<std::string>> Utilities; cmPolicies::PolicyMap PolicyMap; std::string Name; std::string InstallPath; diff --git a/Source/cmTargetDepend.h b/Source/cmTargetDepend.h index b698db6..5ea0085 100644 --- a/Source/cmTargetDepend.h +++ b/Source/cmTargetDepend.h @@ -19,6 +19,7 @@ class cmTargetDepend // mutable members to achieve a map with set syntax. mutable bool Link; mutable bool Util; + mutable cmListFileBacktrace Backtrace; public: cmTargetDepend(cmGeneratorTarget const* t) @@ -42,8 +43,13 @@ public: this->Link = true; } } + void SetBacktrace(cmListFileBacktrace const& bt) const + { + this->Backtrace = bt; + } bool IsLink() const { return this->Link; } bool IsUtil() const { return this->Util; } + cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; } }; /** Unordered set of (direct) dependencies of a target. */ diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 2b2ac95..71928a9 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1376,6 +1376,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release add_subdirectory(FindEXPAT) endif() + if(CMake_TEST_FindFontconfig) + add_subdirectory(FindFontconfig) + endif() + if(CMake_TEST_FindFreetype) add_subdirectory(FindFreetype) endif() diff --git a/Tests/FindFontconfig/CMakeLists.txt b/Tests/FindFontconfig/CMakeLists.txt new file mode 100644 index 0000000..d683d87 --- /dev/null +++ b/Tests/FindFontconfig/CMakeLists.txt @@ -0,0 +1,10 @@ +add_test(NAME FindFontconfig.Test COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindFontconfig/Test" + "${CMake_BINARY_DIR}/Tests/FindFontconfig/Test" + ${build_generator_args} + --build-project TestFindFontconfig + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) diff --git a/Tests/FindFontconfig/Test/CMakeLists.txt b/Tests/FindFontconfig/Test/CMakeLists.txt new file mode 100644 index 0000000..81db3ba --- /dev/null +++ b/Tests/FindFontconfig/Test/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.10) +project(TestFindFontconfig C) +include(CTest) + +find_package(Fontconfig REQUIRED) + +add_definitions(-DCMAKE_EXPECTED_FONTCONFIG_VERSION="${FONTCONFIG_VERSION}") + +add_executable(test_tgt main.c) +target_link_libraries(test_tgt Fontconfig::Fontconfig) +add_test(NAME test_tgt COMMAND test_tgt) + +add_executable(test_var main.c) +target_include_directories(test_var PRIVATE ${FONTCONFIG_INCLUDE_DIRS}) +target_link_libraries(test_var PRIVATE ${FONTCONFIG_LIBRARIES}) +add_test(NAME test_var COMMAND test_var) diff --git a/Tests/FindFontconfig/Test/main.c b/Tests/FindFontconfig/Test/main.c new file mode 100644 index 0000000..c5b5963 --- /dev/null +++ b/Tests/FindFontconfig/Test/main.c @@ -0,0 +1,17 @@ +#include <assert.h> +#include <fontconfig/fontconfig.h> +#include <stdio.h> +#include <string.h> + +int main() +{ + FcInit(); + printf("Found Fontconfig.\n"); + + char fontconfig_version_string[16]; + snprintf(fontconfig_version_string, 16, "%i.%i.%i", FC_MAJOR, FC_MINOR, + FC_REVISION); + assert( + strcmp(fontconfig_version_string, CMAKE_EXPECTED_FONTCONFIG_VERSION) == 0); + return 0; +} diff --git a/Utilities/Doxygen/CMakeLists.txt b/Utilities/Doxygen/CMakeLists.txt index 6a90c84..2cdd767 100644 --- a/Utilities/Doxygen/CMakeLists.txt +++ b/Utilities/Doxygen/CMakeLists.txt @@ -3,7 +3,7 @@ if(NOT CMake_SOURCE_DIR) set(CMakeDeveloperReference_STANDALONE 1) - cmake_minimum_required(VERSION 3.1 FATAL_ERROR) + cmake_minimum_required(VERSION 3.1...3.12 FATAL_ERROR) get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH) get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH) include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake) diff --git a/Utilities/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt index 1cbc463..15204d6 100644 --- a/Utilities/Sphinx/CMakeLists.txt +++ b/Utilities/Sphinx/CMakeLists.txt @@ -3,7 +3,7 @@ if(NOT CMake_SOURCE_DIR) set(CMakeHelp_STANDALONE 1) - cmake_minimum_required(VERSION 3.1 FATAL_ERROR) + cmake_minimum_required(VERSION 3.1...3.12 FATAL_ERROR) get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH) get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH) include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake) diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py index ebf44da..882cdc1 100644 --- a/Utilities/Sphinx/cmake.py +++ b/Utilities/Sphinx/cmake.py @@ -4,14 +4,55 @@ import os import re -# Monkey patch for pygments reporting an error when generator expressions are -# used. -# https://bitbucket.org/birkenfeld/pygments-main/issue/942/cmake-generator-expressions-not-handled +# Override much of pygments' CMakeLexer. +# We need to parse CMake syntax definitions, not CMake code. + +# For hard test cases that use much of the syntax below, see +# - module/FindPkgConfig.html (with "glib-2.0>=2.10 gtk+-2.0" and similar) +# - module/ExternalProject.html (with http:// https:// git@; also has command options -E --build) +# - manual/cmake-buildsystem.7.html (with nested $<..>; relative and absolute paths, "::") + from pygments.lexers import CMakeLexer -from pygments.token import Name, Operator +from pygments.token import Name, Operator, Punctuation, String, Text, Comment, Generic, Whitespace, Number from pygments.lexer import bygroups -CMakeLexer.tokens["args"].append(('(\\$<)(.+?)(>)', - bygroups(Operator, Name.Variable, Operator))) + +# Notes on regular expressions below: +# - [\.\+-] are needed for string constants like gtk+-2.0 +# - Unix paths are recognized by '/'; support for Windows paths may be added if needed +# - (\\.) allows for \-escapes (used in manual/cmake-language.7) +# - $<..$<..$>..> nested occurence in cmake-buildsystem + +CMakeLexer.tokens["root"] = [ + (r'\b(\w+)([ \t]*)(\()', bygroups(Name.Function, Text, Name.Function), '#push'), # fctn( + (r'\(', Name.Function, '#push'), + (r'\)', Name.Function, '#pop'), + (r'\[', Punctuation, '#push'), + (r'\]', Punctuation, '#pop'), + (r'[|;,.=*\-]', Punctuation), + (r'\\\\', Punctuation), # used in commands/source_group + (r'[:]', Operator), + (r'[<>]=', Punctuation), # used in FindPkgConfig.cmake + (r'\$<', Operator, '#push'), # $<...> + (r'<[^<|]+?>(\w*\.\.\.)?', Name.Variable), # <expr> + (r'(\$\w*\{)(.+?)(\})', bygroups(Operator, Name.Tag, Operator)), # ${..} $ENV{..} + (r'([A-Z]+\{)(.+?)(\})', bygroups(Operator, Name.Tag, Operator)), # DATA{ ...} + (r'[a-z]+(@|(://))((\\.)|[\w.+-:/\\])+', Name.Attribute), # URL, git@, ... + (r'/\w[\w\.\+-/\\]*', Name.Attribute), # absolute path + (r'/', Name.Attribute), + (r'\w[\w\.\+-]*/[\w.+-/\\]*', Name.Attribute), # relative path + (r'[A-Z]((\\.)|[\w.+-])*[a-z]((\\.)|[\w.+-])*', Name.Builtin), # initial A-Z, contains a-z + (r'@?[A-Z][A-Z0-9_]*', Name.Constant), + (r'[a-z_]((\\;)|(\\ )|[\w.+-])*', Name.Builtin), + (r'[0-9][0-9\.]*', Number), + (r'(?s)"(\\"|[^"])*"', String), # "string" + (r'\.\.\.', Name.Variable), + (r'<', Operator, '#push'), # <..|..> is different from <expr> + (r'>', Operator, '#pop'), + (r'\n', Whitespace), + (r'[ \t]+', Whitespace), + (r'#.*\n', Comment), + # (r'[^<>\])\}\|$"# \t\n]+', Name.Exception), # fallback, for debugging only +] # Monkey patch for sphinx generating invalid content for qcollectiongenerator # https://bitbucket.org/birkenfeld/sphinx/issue/1435/qthelp-builder-should-htmlescape-keywords diff --git a/Utilities/Sphinx/colors.py b/Utilities/Sphinx/colors.py new file mode 100644 index 0000000..f98a483 --- /dev/null +++ b/Utilities/Sphinx/colors.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- + +from pygments.style import Style +from pygments.token import Name, Comment, String, Number, Operator, Whitespace + +class CMakeTemplateStyle(Style): + """ + for more token names, see pygments/styles.default + """ + + background_color = "#f8f8f8" + default_style = "" + + styles = { + Whitespace: "#bbbbbb", + Comment: "italic #408080", + Operator: "bold #000000", + String: "#217A21", + Number: "#105030", + Name.Builtin: "#400080", # anything lowercase + Name.Function: "bold #1010A0", # function + Name.Variable: "#1080B0", # <..> + Name.Tag: "#19177C", # ${..} + Name.Constant: "#6020E0", # uppercase only + Name.Entity: "italic #70A020", # @..@ + Name.Attribute: "#906060", # paths, URLs + Name.Label: "#A0A000", # anything left over + Name.Exception: "bold #FF0000", # for debugging only + } diff --git a/Utilities/Sphinx/conf.py.in b/Utilities/Sphinx/conf.py.in index f52ccd1..70ba080 100644 --- a/Utilities/Sphinx/conf.py.in +++ b/Utilities/Sphinx/conf.py.in @@ -15,6 +15,7 @@ project = 'CMake' copyright = '@conf_copyright@' version = '@conf_version@' # feature version release = '@conf_release@' # full version string +pygments_style = 'colors.CMakeTemplateStyle' primary_domain = 'cmake' highlight_language = 'none' |