diff options
1181 files changed, 24995 insertions, 16705 deletions
diff --git a/.clang-tidy b/.clang-tidy index bfcb67c..6f96c22 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -3,29 +3,35 @@ Checks: "-*,\ bugprone-*,\ -bugprone-macro-parentheses,\ -bugprone-misplaced-widening-cast,\ +-bugprone-narrowing-conversions,\ +-bugprone-too-small-loop-variable,\ google-readability-casting,\ misc-*,\ -misc-incorrect-roundings,\ -misc-macro-parentheses,\ -misc-misplaced-widening-cast,\ +-misc-non-private-member-variables-in-classes,\ -misc-static-assert,\ modernize-*,\ +-modernize-avoid-c-arrays,\ -modernize-deprecated-headers,\ -modernize-return-braced-init-list,\ -modernize-use-auto,\ +-modernize-use-nodiscard,\ -modernize-use-noexcept,\ -modernize-use-transparent-functors,\ -modernize-use-using,\ performance-*,\ --performance-inefficient-string-concatenation,\ readability-*,\ -readability-function-size,\ -readability-identifier-naming,\ -readability-implicit-bool-cast,\ -readability-implicit-bool-conversion,\ -readability-inconsistent-declaration-parameter-name,\ +-readability-magic-numbers,\ -readability-named-parameter,\ -readability-redundant-declaration,\ +-readability-uppercase-literal-suffix,\ " HeaderFilterRegex: 'Source/cm[^/]*\.(h|hxx|cxx)$' CheckOptions: diff --git a/.gitattributes b/.gitattributes index 24fd9c2..3da2d60 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,4 @@ -.gitattributes export-ignore +.git* export-ignore .hooks* export-ignore # Custom attribute to mark sources as using our C code style. @@ -11,6 +11,7 @@ bootstrap eol=lf configure eol=lf *.[1-9] eol=lf +*.bash eol=lf *.sh eol=lf *.sh.in eol=lf diff --git a/Auxiliary/bash-completion/cmake b/Auxiliary/bash-completion/cmake index 638b1c4..d8d2c86 100644 --- a/Auxiliary/bash-completion/cmake +++ b/Auxiliary/bash-completion/cmake @@ -76,8 +76,8 @@ _cmake() compopt -o nospace else # complete variable names - COMPREPLY=( $( compgen -W '$( cmake -LA -N | tail -n +2 | - cut -f1 -d: )' -P "$prefix" -- "$cur" ) ) + COMPREPLY=( $( compgen -W '$( cmake -LA -N 2>/dev/null | + tail -n +2 | cut -f1 -d: )' -P "$prefix" -- "$cur" ) ) compopt -o nospace fi return diff --git a/Auxiliary/cmake-mode.el b/Auxiliary/cmake-mode.el index e4fa6c1..caaf0d5 100644 --- a/Auxiliary/cmake-mode.el +++ b/Auxiliary/cmake-mode.el @@ -1,5 +1,7 @@ ;;; cmake-mode.el --- major-mode for editing CMake sources +;; Package-Requires: ((emacs "24.1")) + ; Distributed under the OSI-approved BSD 3-Clause License. See accompanying ; file Copyright.txt or https://cmake.org/licensing for details. @@ -224,17 +226,11 @@ the indentation. Otherwise it retains the same position on the line" ;; (defvar cmake-mode-hook nil) -;------------------------------------------------------------------------------ - -;; For compatibility with Emacs < 24 -(defalias 'cmake--parent-mode - (if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode)) - ;;------------------------------------------------------------------------------ ;; Mode definition. ;; ;;;###autoload -(define-derived-mode cmake-mode cmake--parent-mode "CMake" +(define-derived-mode cmake-mode prog-mode "CMake" "Major mode for editing CMake source files." ; Setup font-lock mode. diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim index cd8385b..5de117b 100644 --- a/Auxiliary/vim/syntax/cmake.vim +++ b/Auxiliary/vim/syntax/cmake.vim @@ -288,6 +288,7 @@ syn keyword cmakeProperty contained \ SKIP_AUTORCC \ SKIP_AUTOUIC \ SKIP_BUILD_RPATH + \ SKIP_REGULAR_EXPRESSION \ SKIP_RETURN_CODE \ SOURCES \ SOURCE_DIR @@ -915,6 +916,7 @@ syn keyword cmakeVariable contained \ CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES \ CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT \ CMAKE_ECLIPSE_MAKE_ARGUMENTS + \ CMAKE_ECLIPSE_RESOURCE_ENCODING \ CMAKE_ECLIPSE_VERSION \ CMAKE_EDIT_COMMAND \ CMAKE_ENABLE_EXPORTS @@ -948,6 +950,12 @@ syn keyword cmakeVariable contained \ CMAKE_FIND_ROOT_PATH_MODE_LIBRARY \ CMAKE_FIND_ROOT_PATH_MODE_PACKAGE \ CMAKE_FIND_ROOT_PATH_MODE_PROGRAM + \ CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH + \ CMAKE_FIND_USE_CMAKE_PATH + \ CMAKE_FIND_USE_CMAKE_SYSTEM_PATH + \ CMAKE_FIND_USE_PACKAGE_REGISTRY + \ CMAKE_FIND_USE_PACKAGE_ROOT_PATH + \ CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH \ CMAKE_FOLDER \ CMAKE_FRAMEWORK \ CMAKE_FRAMEWORK_PATH @@ -1765,6 +1773,7 @@ syn keyword cmakeKWadd_test contained \ NAME \ OFF \ PASS_REGULAR_EXPRESSION + \ SKIP_REGULAR_EXPRESSION \ TARGET_FILE \ WILL_FAIL \ WORKING_DIRECTORY diff --git a/CMakeLists.txt b/CMakeLists.txt index e60b6c5..25f17aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,24 @@ # 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...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.1...3.15 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) unset(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX) unset(CMAKE_USER_MAKE_RULES_OVERRIDE_C) +# FIXME: This block should go away after a transition period. +if(MSVC AND NOT CMAKE_VERSION VERSION_LESS 3.15) + # Filter out MSVC runtime library flags that may have come from + # the cache of an existing build tree or from scripts. + foreach(l C CXX) + foreach(c DEBUG MINSIZEREL RELEASE RELWITHDEBINFO) + string(REGEX REPLACE "[-/]M[DT]d?( |$)" "" "CMAKE_${l}_FLAGS_${c}" "${CMAKE_${l}_FLAGS_${c}}") + endforeach() + endforeach() +endif() + # Make sure we can find internal find_package modules only used for # building CMake and not for shipping externally list(INSERT CMAKE_MODULE_PATH 0 ${CMake_SOURCE_DIR}/Source/Modules) @@ -429,10 +440,7 @@ macro (CMAKE_BUILD_UTILITIES) set(_CMAKE_USE_OPENSSL_DEFAULT OFF) if(NOT DEFINED CMAKE_USE_OPENSSL AND NOT WIN32 AND NOT APPLE AND CMAKE_SYSTEM_NAME MATCHES "(Linux|FreeBSD)") - find_package(OpenSSL QUIET) - if(OPENSSL_FOUND) - set(_CMAKE_USE_OPENSSL_DEFAULT ON) - endif() + set(_CMAKE_USE_OPENSSL_DEFAULT ON) endif() option(CMAKE_USE_OPENSSL "Use OpenSSL." ${_CMAKE_USE_OPENSSL_DEFAULT}) mark_as_advanced(CMAKE_USE_OPENSSL) @@ -629,8 +637,7 @@ endif() # The main section of the CMakeLists file # #----------------------------------------------------------------------- -# Compute CMake_VERSION, etc. -include(Source/CMakeVersionCompute.cmake) +include(Source/CMakeVersion.cmake) # Include the standard Dart testing module enable_testing() @@ -817,7 +824,7 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) PATTERN "*.sh*" PERMISSIONS OWNER_READ OWNER_EXECUTE OWNER_WRITE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE - REGEX "Help/dev($|/)" EXCLUDE + REGEX "Help/(dev|guide)($|/)" EXCLUDE ) # Install auxiliary files integrating with other tools. diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt index dde4dbb..40f1c1a 100644 --- a/Help/command/FIND_XXX.txt +++ b/Help/command/FIND_XXX.txt @@ -89,7 +89,8 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows: searched after paths from the current module, i.e. ``<CurrentPackage>_ROOT``, ``ENV{<CurrentPackage>_ROOT}``, ``<ParentPackage>_ROOT``, ``ENV{<ParentPackage>_ROOT}``, etc. - This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed. + This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed or by setting + the :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` to ``FALSE``. See policy :policy:`CMP0074`. * |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| @@ -97,7 +98,8 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows: 2. Search paths specified in cmake-specific cache variables. These are intended to be used on the command line with a ``-DVAR=value``. The values are interpreted as :ref:`semicolon-separated lists <CMake Language Lists>`. - This can be skipped if ``NO_CMAKE_PATH`` is passed. + This can be skipped if ``NO_CMAKE_PATH`` is passed or by setting the + :variable:`CMAKE_FIND_USE_CMAKE_PATH` to ``FALSE``. * |CMAKE_PREFIX_PATH_XXX| * |CMAKE_XXX_PATH| @@ -107,7 +109,8 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows: These are intended to be set in the user's shell configuration, and therefore use the host's native path separator (``;`` on Windows and ``:`` on UNIX). - This can be skipped if ``NO_CMAKE_ENVIRONMENT_PATH`` is passed. + This can be skipped if ``NO_CMAKE_ENVIRONMENT_PATH`` is passed or + by setting the :variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH` to ``FALSE``. * |CMAKE_PREFIX_PATH_XXX| * |CMAKE_XXX_PATH| @@ -119,13 +122,16 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows: Hard-coded guesses should be specified with the ``PATHS`` option. 5. Search the standard system environment variables. - This can be skipped if ``NO_SYSTEM_ENVIRONMENT_PATH`` is an argument. + This can be skipped if ``NO_SYSTEM_ENVIRONMENT_PATH`` is passed or by + setting the :variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH` to ``FALSE``. * |SYSTEM_ENVIRONMENT_PATH_XXX| + * |SYSTEM_ENVIRONMENT_PATH_WINDOWS_XXX| 6. Search cmake variables defined in the Platform files for the current system. This can be skipped if ``NO_CMAKE_SYSTEM_PATH`` - is passed. + is passed or by setting the :variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH` + to ``FALSE``. * |CMAKE_SYSTEM_PREFIX_PATH_XXX| * |CMAKE_SYSTEM_XXX_PATH| diff --git a/Help/command/add_test.rst b/Help/command/add_test.rst index 46b9b63..a77ba37 100644 --- a/Help/command/add_test.rst +++ b/Help/command/add_test.rst @@ -7,7 +7,8 @@ Add a test to the project to be run by :manual:`ctest(1)`. add_test(NAME <name> COMMAND <command> [<arg>...] [CONFIGURATIONS <config>...] - [WORKING_DIRECTORY <dir>]) + [WORKING_DIRECTORY <dir>] + [COMMAND_EXPAND_LISTS]) Adds a test called ``<name>``. The test name may not contain spaces, quotes, or other characters special in CMake syntax. The options are: @@ -28,12 +29,18 @@ quotes, or other characters special in CMake syntax. The options are: directory set to the build directory corresponding to the current source directory. +``COMMAND_EXPAND_LISTS`` + Lists in ``COMMAND`` arguments will be expanded, including those + created with + :manual:`generator expressions <cmake-generator-expressions(7)>`. + The given test command is expected to exit with code ``0`` to pass and non-zero to fail, or vice-versa if the :prop_test:`WILL_FAIL` test property is set. Any output written to stdout or stderr will be captured by :manual:`ctest(1)` but does not affect the pass/fail status -unless the :prop_test:`PASS_REGULAR_EXPRESSION` or -:prop_test:`FAIL_REGULAR_EXPRESSION` test property is used. +unless the :prop_test:`PASS_REGULAR_EXPRESSION`, +:prop_test:`FAIL_REGULAR_EXPRESSION` or +:prop_test:`SKIP_REGULAR_EXPRESSION` test property is used. The ``COMMAND`` and ``WORKING_DIRECTORY`` options may use "generator expressions" with the syntax ``$<...>``. See the diff --git a/Help/command/ctest_coverage.rst b/Help/command/ctest_coverage.rst index 8d27b9c..d50f634 100644 --- a/Help/command/ctest_coverage.rst +++ b/Help/command/ctest_coverage.rst @@ -8,7 +8,7 @@ Perform the :ref:`CTest Coverage Step` as a :ref:`Dashboard Client`. ctest_coverage([BUILD <build-dir>] [APPEND] [LABELS <label>...] [RETURN_VALUE <result-var>] - [CAPTURE_CMAKE_ERROR <result-var] + [CAPTURE_CMAKE_ERROR <result-var>] [QUIET] ) diff --git a/Help/command/ctest_start.rst b/Help/command/ctest_start.rst index 6db9a48..f0704ac 100644 --- a/Help/command/ctest_start.rst +++ b/Help/command/ctest_start.rst @@ -5,9 +5,9 @@ Starts the testing for a given model :: - ctest_start(<model> [<source> [<binary>]] [TRACK <track>] [QUIET]) + ctest_start(<model> [<source> [<binary>]] [GROUP <group>] [QUIET]) - ctest_start([<model> [<source> [<binary>]]] [TRACK <track>] APPEND [QUIET]) + ctest_start([<model> [<source> [<binary>]]] [GROUP <group>] APPEND [QUIET]) Starts the testing for a given model. The command should be called after the binary directory is initialized. @@ -26,20 +26,21 @@ The parameters are as follows: Set the binary directory. If not specified, the value of :variable:`CTEST_BINARY_DIRECTORY` is used instead. -``TRACK <track>`` - If ``TRACK`` is used, the submissions will go to the specified track on the - CDash server. If no ``TRACK`` is specified, the name of the model is used by - default. +``GROUP <group>`` + If ``GROUP`` is used, the submissions will go to the specified group on the + CDash server. If no ``GROUP`` is specified, the name of the model is used by + default. This replaces the deprecated option ``TRACK``. Despite the name + change its behavior is unchanged. ``APPEND`` If ``APPEND`` is used, the existing ``TAG`` is used rather than creating a new one based on the current time stamp. If you use ``APPEND``, you can omit the - ``<model>`` and ``TRACK <track>`` parameters, because they will be read from + ``<model>`` and ``GROUP <group>`` parameters, because they will be read from the generated ``TAG`` file. For example: .. code-block:: cmake - ctest_start(Experimental TRACK TrackExperimental) + ctest_start(Experimental GROUP GroupExperimental) Later, in another ``ctest -S`` script: @@ -48,11 +49,11 @@ The parameters are as follows: ctest_start(APPEND) When the second script runs ``ctest_start(APPEND)``, it will read the - ``Experimental`` model and ``TrackExperimental`` track from the ``TAG`` file + ``Experimental`` model and ``GroupExperimental`` group from the ``TAG`` file generated by the first ``ctest_start()`` command. Please note that if you - call ``ctest_start(APPEND)`` and specify a different model or track than + call ``ctest_start(APPEND)`` and specify a different model or group than in the first ``ctest_start()`` command, a warning will be issued, and the - new model and track will be used. + new model and group will be used. ``QUIET`` If ``QUIET`` is used, CTest will suppress any non-error messages that it @@ -65,11 +66,11 @@ equivalent: .. code-block:: cmake - ctest_start(Experimental path/to/source path/to/binary TRACK SomeTrack QUIET APPEND) + ctest_start(Experimental path/to/source path/to/binary GROUP SomeGroup QUIET APPEND) - ctest_start(TRACK SomeTrack Experimental QUIET path/to/source APPEND path/to/binary) + ctest_start(GROUP SomeGroup Experimental QUIET path/to/source APPEND path/to/binary) - ctest_start(APPEND QUIET Experimental path/to/source TRACK SomeTrack path/to/binary) + ctest_start(APPEND QUIET Experimental path/to/source GROUP SomeGroup path/to/binary) However, for the sake of readability, it is recommended that you order your parameters in the order listed at the top of this page. diff --git a/Help/command/file.rst b/Help/command/file.rst index f99021e..c06451a 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -13,6 +13,7 @@ Synopsis file(`STRINGS`_ <filename> <out-var> [...]) file(`\<HASH\> <HASH_>`_ <filename> <out-var>) file(`TIMESTAMP`_ <filename> <out-var> [...]) + file(`GET_RUNTIME_DEPENDENCIES`_ [...]) `Writing`_ file({`WRITE`_ | `APPEND`_} <filename> <content>...) @@ -130,6 +131,273 @@ timestamp variable will be set to the empty string (""). See the :command:`string(TIMESTAMP)` command for documentation of the ``<format>`` and ``UTC`` options. +.. _GET_RUNTIME_DEPENDENCIES: + +.. code-block:: cmake + + file(GET_RUNTIME_DEPENDENCIES + [RESOLVED_DEPENDENCIES_VAR <deps_var>] + [UNRESOLVED_DEPENDENCIES_VAR <unresolved_deps_var>] + [CONFLICTING_DEPENDENICES_PREFIX <conflicting_deps_prefix>] + [EXECUTABLES [<executable_files>...]] + [LIBRARIES [<library_files>...]] + [MODULES [<module_files>...]] + [DIRECTORIES [<directories>...]] + [BUNDLE_EXECUTABLE <bundle_executable_file>] + [PRE_INCLUDE_REGEXES [<regexes>...]] + [PRE_EXCLUDE_REGEXES [<regexes>...]] + [POST_INCLUDE_REGEXES [<regexes>...]] + [POST_EXCLUDE_REGEXES [<regexes>...]] + ) + +Recursively get the list of libraries depended on by the given files. + +Please note that this sub-command is not intended to be used in project mode. +Instead, use it in an :command:`install(CODE)` or :command:`install(SCRIPT)` +block. For example: + +.. code-block:: cmake + + install(CODE [[ + file(GET_RUNTIME_DEPENDENCIES + # ... + ) + ]]) + +The arguments are as follows: + +``RESOLVED_DEPENDENCIES_VAR <deps_var>`` + Name of the variable in which to store the list of resolved dependencies. + +``UNRESOLVED_DEPENDENCIES_VAR <unresolved_deps_var>`` + Name of the variable in which to store the list of unresolved dependencies. + If this variable is not specified, and there are any unresolved dependencies, + an error is issued. + +``CONFLICTING_DEPENDENCIES_PREFIX <conflicting_deps_prefix>`` + Variable prefix in which to store conflicting dependency information. + Dependencies are conflicting if two files with the same name are found in + two different directories. The list of filenames that conflict are stored in + ``<conflicting_deps_prefix>_FILENAMES``. For each filename, the list of paths + that were found for that filename are stored in + ``<conflicting_deps_prefix>_<filename>``. + +``EXECUTABLES <executable_files>`` + List of executable files to read for dependencies. These are executables that + are typically created with :command:`add_executable`, but they do not have to + be created by CMake. On Apple platforms, the paths to these files determine + the value of ``@executable_path`` when recursively resolving the libraries. + Specifying ``STATIC`` libraries, ``MODULE`` s, or ``SHARED`` libraries here + will result in undefined behavior. + +``LIBRARIES <library_files>`` + List of library files to read for dependencies. These are libraries that are + typically created with :command:`add_library(SHARED)`, but they do not have + to be created by CMake. Specifying ``STATIC`` libraries, ``MODULE`` s, or + executables here will result in undefined behavior. + +``MODULES <module_files>`` + List of loadable module files to read for dependencies. These are modules + that are typically created with :command:`add_library(MODULE)`, but they do + not have to be created by CMake. They are typically used by calling + ``dlopen()`` at runtime rather than linked at link time with ``ld -l``. + Specifying ``STATIC`` libraries, ``SHARED`` libraries, or executables here + will result in undefined behavior. + +``DIRECTORIES <directories>`` + List of additional directories to search for dependencies. On Linux + platforms, these directories are searched if the dependency is not found in + any of the other usual paths. If it is found in such a directory, a warning + is issued, because it means that the file is incomplete (it does not list all + of the directories that contain its dependencies.) On Windows platforms, + these directories are searched if the dependency is not found in any of the + other search paths, but no warning is issued, because searching other paths + is a normal part of Windows dependency resolution. On Apple platforms, this + argument has no effect. + +``BUNDLE_EXECTUBLE <bundle_executable_file>`` + Executable to treat as the "bundle executable" when resolving libraries. On + Apple platforms, this argument determines the value of ``@executable_path`` + when recursively resolving libraries for ``LIBRARIES`` and ``MODULES`` files. + It has no effect on ``EXECUTABLES`` files. On other platforms, it has no + effect. This is typically (but not always) one of the executables in the + ``EXECUTABLES`` argument which designates the "main" executable of the + package. + +The following arguments specify filters for including or excluding libraries to +be resolved. See below for a full description of how they work. + +``PRE_INCLUDE_REGEXES <regexes>`` + List of pre-include regexes through which to filter the names of + not-yet-resolved dependencies. + +``PRE_EXCLUDE_REGEXES <regexes>`` + List of pre-exclude regexes through which to filter the names of + not-yet-resolved dependencies. + +``POST_INCLUDE_REGEXES <regexes>`` + List of post-include regexes through which to filter the names of resolved + dependencies. + +``POST_EXCLUDE_REGEXES <regexes>`` + List of post-exclude regexes through which to filter the names of resolved + dependencies. + +These arguments can be used to blacklist unwanted system libraries when +resolving the dependencies, or to whitelist libraries from a specific +directory. The filtering works as follows: + +1. If the not-yet-resolved dependency matches any of the + ``PRE_INCLUDE_REGEXES``, steps 2 and 3 are skipped, and the dependency + resolution proceeds to step 4. +2. If the not-yet-resolved dependency matches any of the + ``PRE_EXCLUDE_REGEXES``, dependency resolution stops for that dependency. +3. Otherwise, dependency resolution proceeds. +4. ``file(GET_RUNTIME_DEPENDENCIES)`` searches for the dependency according to + the linking rules of the platform (see below). +5. If the dependency is found, and its full path matches one of the + ``POST_INCLUDE_REGEXES``, the full path is added to the resolved + dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)`` recursively resolves + that library's own dependencies. Otherwise, resolution proceeds to step 6. +6. If the dependency is found, but its full path matches one of the + ``POST_EXCLUDE_REGEXES``, it is not added to the resolved dependencies, and + dependency resolution stops for that dependency. +7. If the dependency is found, and its full path does not match either + ``POST_INCLUDE_REGEXES`` or ``POST_EXCLUDE_REGEXES``, the full path is added + to the resolved dependencies, and ``file(GET_RUNTIME_DEPENDENCIES)`` + recursively resolves that library's own dependencies. + +Different platforms have different rules for how dependencies are resolved. +These specifics are described here. + +On Linux platforms, library resolution works as follows: + +1. If the depending file does not have any ``RUNPATH`` entries, and the library + exists in one of the depending file's ``RPATH`` entries, or its parents', in + that order, the dependency is resolved to that file. +2. Otherwise, if the depending file has any ``RUNPATH`` entries, and the + library exists in one of those entries, the dependency is resolved to that + file. +3. Otherwise, if the library exists in one of the directories listed by + ``ldconfig``, the dependency is resolved to that file. +4. Otherwise, if the library exists in one of the ``DIRECTORIES`` entries, the + dependency is resolved to that file. In this case, a warning is issued, + because finding a file in one of the ``DIRECTORIES`` means that the + depending file is not complete (it does not list all the directories from + which it pulls dependencies.) +5. Otherwise, the dependency is unresolved. + +On Windows platforms, library resolution works as follows: + +1. The dependent DLL name is converted to lowercase. Windows DLL names are + case-insensitive, and some linkers mangle the case of the DLL dependency + names. However, this makes it more difficult for ``PRE_INCLUDE_REGEXES``, + ``PRE_EXCLUDE_REGEXES``, ``POST_INCLUDE_REGEXES``, and + ``POST_EXCLUDE_REGEXES`` to properly filter DLL names - every regex would + have to check for both uppercase and lowercase letters. For example: + + .. code-block:: cmake + + file(GET_RUNTIME_DEPENDENCIES + # ... + PRE_INCLUDE_REGEXES "^[Mm][Yy][Ll][Ii][Bb][Rr][Aa][Rr][Yy]\\.[Dd][Ll][Ll]$" + ) + + Converting the DLL name to lowercase allows the regexes to only match + lowercase names, thus simplifying the regex. For example: + + .. code-block:: cmake + + file(GET_RUNTIME_DEPENDENCIES + # ... + PRE_INCLUDE_REGEXES "^mylibrary\\.dll$" + ) + + This regex will match ``mylibrary.dll`` regardless of how it is cased, + either on disk or in the depending file. (For example, it will match + ``mylibrary.dll``, ``MyLibrary.dll``, and ``MYLIBRARY.DLL``.) + + Please note that the directory portion of any resolved DLLs retains its + casing and is not converted to lowercase. Only the filename portion is + converted. + +2. (**Not yet implemented**) If the depending file is a Windows Store app, and + the dependency is listed as a dependency in the application's package + manifest, the dependency is resolved to that file. +3. Otherwise, if the library exists in the same directory as the depending + file, the dependency is resolved to that file. +4. Otherwise, if the library exists in either the operating system's + ``system32`` directory or the ``Windows`` directory, in that order, the + dependency is resolved to that file. +5. Otherwise, if the library exists in one of the directories specified by + ``DIRECTORIES``, in the order they are listed, the dependency is resolved to + that file. (In this case, a warning is not issued, because searching other + directories is a normal part of Windows library resolution.) +6. Otherwise, the dependency is unresolved. + +On Apple platforms, library resolution works as follows: + +1. If the dependency starts with ``@executable_path/``, and an ``EXECUTABLES`` + argument is in the process of being resolved, and replacing + ``@executable_path/`` with the directory of the executable yields an + existing file, the dependency is resolved to that file. +2. Otherwise, if the dependency starts with ``@executable_path/``, and there is + a ``BUNDLE_EXECUTABLE`` argument, and replacing ``@executable_path/`` with + the directory of the bundle executable yields an existing file, the + dependency is resolved to that file. +3. Otherwise, if the dependency starts with ``@loader_path/``, and replacing + ``@loader_path/`` with the directory of the depending file yields an + existing file, the dependency is resolved to that file. +4. Otherwise, if the dependency starts with ``@rpath/``, and replacing + ``@rpath/`` with one of the ``RPATH`` entries of the depending file yields + an existing file, the dependency is resolved to that file. (Note that + ``RPATH`` entries that start with ``@executable_path/`` or ``@loader_path/`` + also have these items replaced with the appropriate path.) +5. Otherwise, if the dependency is an absolute file that exists, the dependency + is resolved to that file. +6. Otherwise, the dependency is unresolved. + +This function accepts several variables that determine which tool is used for +dependency resolution: + +.. variable:: CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM + + Determines which operating system and executable format the files are built + for. This could be one of several values: + + * ``linux+elf`` + * ``windows+pe`` + * ``macos+macho`` + + If this variable is not specified, it is determined automatically by system + introspection. + +.. variable:: CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL + + Determines the tool to use for dependency resolution. It could be one of + several values, depending on the value of + :variable:`CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM`: + + ================================================= ============================================= + ``CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM`` ``CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL`` + ================================================= ============================================= + ``linux+elf`` ``objdump`` + ``windows+pe`` ``dumpbin`` + ``windows+pe`` ``objdump`` + ``macos+macho`` ``otool`` + ================================================= ============================================= + + If this variable is not specified, it is determined automatically by system + introspection. + +.. variable:: CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND + + Determines the path to the tool to use for dependency resolution. This is the + actual path to ``objdump``, ``dumpbin``, or ``otool``. + + If this variable is not specified, it is determined automatically by system + introspection. + Writing ^^^^^^^ @@ -235,6 +503,11 @@ regular expressions, but much simpler. If ``RELATIVE`` flag is specified, the results will be returned as relative paths to the given path. The results will be ordered lexicographically. +On Windows and macOS, globbing is case-insensitive even if the underlying +filesystem is case-sensitive (both filenames and globbing expressions are +converted to lowercase before matching). On other platforms, globbing is +case-sensitive. + If the ``CONFIGURE_DEPENDS`` flag is specified, CMake will add logic to the main build system check target to rerun the flagged ``GLOB`` commands at build time. If any of the outputs change, CMake will regenerate the build diff --git a/Help/command/find_file.rst b/Help/command/find_file.rst index 2a14ad7..3f03f37 100644 --- a/Help/command/find_file.rst +++ b/Help/command/find_file.rst @@ -17,11 +17,10 @@ find_file .. |CMAKE_XXX_PATH| replace:: :variable:`CMAKE_INCLUDE_PATH` .. |CMAKE_XXX_MAC_PATH| replace:: :variable:`CMAKE_FRAMEWORK_PATH` -.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: Directories in ``INCLUDE``. - On Windows hosts: - ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` - is set, and |SYSTEM_ENVIRONMENT_PREFIX_PATH_XXX_SUBDIR|, and the - directories in ``PATH`` itself. +.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: The directories in ``PATH`` and ``INCLUDE``. +.. |SYSTEM_ENVIRONMENT_PATH_WINDOWS_XXX| replace:: On Windows hosts: + ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` + is set, and |SYSTEM_ENVIRONMENT_PREFIX_PATH_XXX_SUBDIR|. .. |CMAKE_SYSTEM_PREFIX_PATH_XXX| replace:: ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` diff --git a/Help/command/find_library.rst b/Help/command/find_library.rst index 0861d67..8a55aca 100644 --- a/Help/command/find_library.rst +++ b/Help/command/find_library.rst @@ -17,11 +17,10 @@ find_library .. |CMAKE_XXX_PATH| replace:: :variable:`CMAKE_LIBRARY_PATH` .. |CMAKE_XXX_MAC_PATH| replace:: :variable:`CMAKE_FRAMEWORK_PATH` -.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: Directories in ``LIB``. - On Windows hosts: - ``<prefix>/lib/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set, - and |SYSTEM_ENVIRONMENT_PREFIX_PATH_XXX_SUBDIR|, - and the directories in ``PATH`` itself. +.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: The directories in ``PATH`` and ``INCLUDE``. +.. |SYSTEM_ENVIRONMENT_PATH_WINDOWS_XXX| replace:: On Windows hosts: + ``<prefix>/lib/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` + is set, and |SYSTEM_ENVIRONMENT_PREFIX_PATH_XXX_SUBDIR|. .. |CMAKE_SYSTEM_PREFIX_PATH_XXX| replace:: ``<prefix>/lib/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set, diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst index e5e5b2c..2186bd8 100644 --- a/Help/command/find_package.rst +++ b/Help/command/find_package.rst @@ -293,13 +293,15 @@ enabled. The package root variables are maintained as a stack so if called from within a find module, root paths from the parent's find module will also be searched after paths for the current package. - This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed. + This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed or by setting + the :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` to ``FALSE``. See policy :policy:`CMP0074`. 2. Search paths specified in cmake-specific cache variables. These are intended to be used on the command line with a ``-DVAR=value``. The values are interpreted as :ref:`semicolon-separated lists <CMake Language Lists>`. - This can be skipped if ``NO_CMAKE_PATH`` is passed:: + This can be skipped if ``NO_CMAKE_PATH`` is passed or by setting the + :variable:`CMAKE_FIND_USE_CMAKE_PATH` to ``FALSE``:: CMAKE_PREFIX_PATH CMAKE_FRAMEWORK_PATH @@ -309,7 +311,8 @@ enabled. These are intended to be set in the user's shell configuration, and therefore use the host's native path separator (``;`` on Windows and ``:`` on UNIX). - This can be skipped if ``NO_CMAKE_ENVIRONMENT_PATH`` is passed:: + This can be skipped if ``NO_CMAKE_ENVIRONMENT_PATH`` is passed or by setting + the :variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH` to ``FALSE``:: <PackageName>_DIR CMAKE_PREFIX_PATH @@ -322,7 +325,8 @@ enabled. be specified with the ``PATHS`` option. 5. Search the standard system environment variables. This can be - skipped if ``NO_SYSTEM_ENVIRONMENT_PATH`` is passed. Path entries + skipped if ``NO_SYSTEM_ENVIRONMENT_PATH`` is passed or by setting the + :variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH` to ``FALSE``. Path entries ending in ``/bin`` or ``/sbin`` are automatically converted to their parent directories:: @@ -330,14 +334,17 @@ enabled. 6. Search paths stored in the CMake :ref:`User Package Registry`. This can be skipped if ``NO_CMAKE_PACKAGE_REGISTRY`` is passed or by - setting the :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY` - to ``TRUE``. + setting the variable :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY` + to ``FALSE`` or the deprecated variable + :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY` to ``TRUE``. + See the :manual:`cmake-packages(7)` manual for details on the user package registry. 7. Search cmake variables defined in the Platform files for the current system. This can be skipped if ``NO_CMAKE_SYSTEM_PATH`` is - passed:: + passed or by setting the :variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH` + to ``FALSE``:: CMAKE_SYSTEM_PREFIX_PATH CMAKE_SYSTEM_FRAMEWORK_PATH diff --git a/Help/command/find_path.rst b/Help/command/find_path.rst index 988a3fa..52ffe3c 100644 --- a/Help/command/find_path.rst +++ b/Help/command/find_path.rst @@ -17,11 +17,10 @@ find_path .. |CMAKE_XXX_PATH| replace:: :variable:`CMAKE_INCLUDE_PATH` .. |CMAKE_XXX_MAC_PATH| replace:: :variable:`CMAKE_FRAMEWORK_PATH` -.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: Directories in ``INCLUDE``. - On Windows hosts: - ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` - is set, and |SYSTEM_ENVIRONMENT_PREFIX_PATH_XXX_SUBDIR|, and the - directories in ``PATH`` itself. +.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: The directories in ``PATH`` and ``INCLUDE``. +.. |SYSTEM_ENVIRONMENT_PATH_WINDOWS_XXX| replace:: On Windows hosts: + ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` + is set, and |SYSTEM_ENVIRONMENT_PREFIX_PATH_XXX_SUBDIR|. .. |CMAKE_SYSTEM_PREFIX_PATH_XXX| replace:: ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` diff --git a/Help/command/find_program.rst b/Help/command/find_program.rst index 4f00773..e2ff693 100644 --- a/Help/command/find_program.rst +++ b/Help/command/find_program.rst @@ -15,7 +15,8 @@ find_program .. |CMAKE_XXX_PATH| replace:: :variable:`CMAKE_PROGRAM_PATH` .. |CMAKE_XXX_MAC_PATH| replace:: :variable:`CMAKE_APPBUNDLE_PATH` -.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: ``PATH`` +.. |SYSTEM_ENVIRONMENT_PATH_XXX| replace:: The directories in ``PATH`` itself. +.. |SYSTEM_ENVIRONMENT_PATH_WINDOWS_XXX| replace:: On Windows hosts no extra search paths are included .. |CMAKE_SYSTEM_PREFIX_PATH_XXX| replace:: |CMAKE_SYSTEM_PREFIX_PATH_XXX_SUBDIR| diff --git a/Help/command/if.rst b/Help/command/if.rst index d8e3a45..be992df 100644 --- a/Help/command/if.rst +++ b/Help/command/if.rst @@ -29,6 +29,8 @@ If used, it must be a verbatim repeat of the argument of the opening ``if`` command. +.. _`Condition Syntax`: + Condition Syntax ^^^^^^^^^^^^^^^^ diff --git a/Help/command/install.rst b/Help/command/install.rst index ab6fef6..5affc5b 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -126,6 +126,8 @@ project. There are several kinds of target files that may be installed: marked with the ``FRAMEWORK`` property on macOS (see ``FRAMEWORK`` below.) For DLL platforms (all Windows-based systems including Cygwin), the DLL import library is treated as an ``ARCHIVE`` target. + On AIX, the linker import file created for executables with + :prop_tgt:`ENABLE_EXPORTS` is treated as an ``ARCHIVE`` target. ``LIBRARY`` Module libraries are always treated as ``LIBRARY`` targets. For non- 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/dev/maint.rst b/Help/dev/maint.rst index 1153a09..37a1d3a 100644 --- a/Help/dev/maint.rst +++ b/Help/dev/maint.rst @@ -92,6 +92,45 @@ Publish both ``master`` and ``release`` simultaneously: .. _`CMake Review Process`: review.rst .. _`CMake CDash Page`: https://open.cdash.org/index.php?project=CMake +Create Release Version +====================== + +When the ``release`` branch is ready to create a new release, follow the +steps in the above `Maintain Current Release`_ section to checkout a local +``release-$ver`` branch, where ``$ver`` is the version number of the +current release in the form ``$major.$minor``. + +Edit ``Source/CMakeVersion.cmake`` to set the full version: + +.. code-block:: cmake + + # CMake version number components. + set(CMake_VERSION_MAJOR $major) + set(CMake_VERSION_MINOR $minor) + set(CMake_VERSION_PATCH $patch) + #set(CMake_VERSION_RC $rc) # uncomment for release candidates + +In the following we use the placeholder ``$fullver`` for the full version +number of the new release with the form ``$major.$minor.$patch[-rc$rc]``. +If the version is not a release candidate, comment out the RC version +component above and leave off the ``-rc$rc`` suffix from ``$fullver``. + +Commit the release version with the **exact** message ``CMake $fullver``: + +.. code-block:: shell + + git commit -m "CMake $fullver" + +Tag the release using an annotated tag with the same message as the +commit and named with the **exact** form ``v$fullver``: + +.. code-block:: shell + + git tag -s -m "CMake $fullver" "v$fullver" + +Follow the steps in the above `Maintain Current Release`_ section to +merge the ``release-$ver`` branch into ``master`` and publish both. + Branch a New Release ==================== @@ -178,7 +217,7 @@ Commit with a message such as:: the CMake Release Notes index page. Update ``Source/CMakeVersion.cmake`` to set the version to -``$major.$minor.0-rc1``: +``$major.$minor.0-rc0``: .. code-block:: cmake @@ -186,7 +225,7 @@ Update ``Source/CMakeVersion.cmake`` to set the version to set(CMake_VERSION_MAJOR $major) set(CMake_VERSION_MINOR $minor) set(CMake_VERSION_PATCH 0) - set(CMake_VERSION_RC 1) + set(CMake_VERSION_RC 0) Update uses of ``DEVEL_CMAKE_VERSION`` in the source tree to mention the actual version number: @@ -197,7 +236,7 @@ actual version number: Commit with a message such as:: - CMake $major.$minor.0-rc1 version update + Begin $ver release versioning Merge the ``release-$ver`` branch to ``master``: @@ -225,7 +264,7 @@ Update ``Source/CMakeVersion.cmake`` to set the version to set(CMake_VERSION_MAJOR $major) set(CMake_VERSION_MINOR $minor) set(CMake_VERSION_PATCH $date) - #set(CMake_VERSION_RC 1) + #set(CMake_VERSION_RC 0) Commit with a message such as:: diff --git a/Tests/Tutorial/MultiPackage/CMakeLists.txt b/Help/guide/tutorial/Complete/CMakeLists.txt index 067e807..eca79d9 100644 --- a/Tests/Tutorial/MultiPackage/CMakeLists.txt +++ b/Help/guide/tutorial/Complete/CMakeLists.txt @@ -1,32 +1,43 @@ -cmake_minimum_required(VERSION 3.3) -project(Tutorial) +cmake_minimum_required(VERSION 3.15) -# control how we mark up Debug libraries compared to Release libraries -set(CMAKE_DEBUG_POSTFIX "-d") +# set the project name and version +project(Tutorial VERSION 1.0) + +add_library(tutorial_compiler_flags INTERFACE) +target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11) + +# add compiler warning flags just when building this project via +# the BUILD_INTERFACE genex +set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU>") +set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") +target_compile_options(tutorial_compiler_flags INTERFACE + "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>" + "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" +) # control where the static and shared libraries are built so that on windows # we don't need to tinker with the path to run the executable set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") option(BUILD_SHARED_LIBS "Build using shared libraries" ON) -# the version number. -set(Tutorial_VERSION_MAJOR 1) -set(Tutorial_VERSION_MINOR 0) +if(APPLE) + set(CMAKE_INSTALL_RPATH "@executable_path/../lib") +elseif(UNIX) + set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib") +endif() # configure a header file to pass the version number only -configure_file( - "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" - "${PROJECT_BINARY_DIR}/TutorialConfig.h" - ) +configure_file(TutorialConfig.h.in TutorialConfig.h) # add the MathFunctions library add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial MathFunctions) +target_link_libraries(Tutorial PUBLIC MathFunctions) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h diff --git a/Help/guide/tutorial/Complete/CTestConfig.cmake b/Help/guide/tutorial/Complete/CTestConfig.cmake new file mode 100644 index 0000000..73efdb1 --- /dev/null +++ b/Help/guide/tutorial/Complete/CTestConfig.cmake @@ -0,0 +1,7 @@ +set(CTEST_PROJECT_NAME "CMakeTutorial") +set(CTEST_NIGHTLY_START_TIME "00:00:00 EST") + +set(CTEST_DROP_METHOD "http") +set(CTEST_DROP_SITE "my.cdash.org") +set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial") +set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Tests/Tutorial/MultiPackage/Config.cmake.in b/Help/guide/tutorial/Complete/Config.cmake.in index 17cbabd..17cbabd 100644 --- a/Tests/Tutorial/MultiPackage/Config.cmake.in +++ b/Help/guide/tutorial/Complete/Config.cmake.in diff --git a/Tests/Tutorial/Step9/License.txt b/Help/guide/tutorial/Complete/License.txt index c62d00b..c62d00b 100644 --- a/Tests/Tutorial/Step9/License.txt +++ b/Help/guide/tutorial/Complete/License.txt diff --git a/Tests/Tutorial/Complete/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt index 161ad64..dfa84c9 100644 --- a/Tests/Tutorial/Complete/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt @@ -1,4 +1,3 @@ - # add the library that runs add_library(MathFunctions MathFunctions.cxx) @@ -14,14 +13,11 @@ target_include_directories(MathFunctions option(USE_MYMATH "Use tutorial provided math implementation" ON) if(USE_MYMATH) - # does this system provide the log and exp functions? - include(CheckSymbolExists) - set(CMAKE_REQUIRED_LIBRARIES "m") - check_symbol_exists(log "math.h" HAVE_LOG) - check_symbol_exists(exp "math.h" HAVE_EXP) + target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") # first we add the executable that generates the table add_executable(MakeTable MakeTable.cxx) + target_link_libraries(MakeTable tutorial_compiler_flags) # add the command to generate the source code add_custom_command( @@ -41,18 +37,16 @@ if(USE_MYMATH) ${CMAKE_CURRENT_BINARY_DIR} ) + # state that SqrtLibrary need PIC when the default is shared libraries set_target_properties(SqrtLibrary PROPERTIES POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS} ) - target_compile_definitions(SqrtLibrary PRIVATE - "$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>" - "$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>" - ) + target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags) target_link_libraries(MathFunctions PRIVATE SqrtLibrary) endif() -target_compile_definitions(MathFunctions PRIVATE "$<$<BOOL:${USE_MYMATH}>:USE_MYMATH>") +target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags) # define the symbol stating we are using the declspec(dllexport) when # building on windows @@ -62,7 +56,8 @@ target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH") set_property(TARGET MathFunctions PROPERTY VERSION "1.0.0") set_property(TARGET MathFunctions PROPERTY SOVERSION "1") -install(TARGETS MathFunctions +# install rules +install(TARGETS MathFunctions tutorial_compiler_flags DESTINATION lib EXPORT MathFunctionsTargets) install(FILES MathFunctions.h DESTINATION include) diff --git a/Tests/Tutorial/Step9/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Complete/MathFunctions/MakeTable.cxx index ee58556..ee58556 100644 --- a/Tests/Tutorial/Step9/MathFunctions/MakeTable.cxx +++ b/Help/guide/tutorial/Complete/MathFunctions/MakeTable.cxx diff --git a/Tests/Tutorial/Step9/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Complete/MathFunctions/MathFunctions.cxx index 5351184..5351184 100644 --- a/Tests/Tutorial/Step9/MathFunctions/MathFunctions.cxx +++ b/Help/guide/tutorial/Complete/MathFunctions/MathFunctions.cxx diff --git a/Tests/Tutorial/Step11/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Complete/MathFunctions/MathFunctions.h index 3fb547b..3fb547b 100644 --- a/Tests/Tutorial/Step11/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Complete/MathFunctions/MathFunctions.h diff --git a/Tests/Tutorial/Complete/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Complete/MathFunctions/mysqrt.cxx index 96d9421..ff37312 100644 --- a/Tests/Tutorial/Complete/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Complete/MathFunctions/mysqrt.cxx @@ -4,8 +4,6 @@ // include the generated table #include "Table.h" -#include <cmath> - namespace mathfunctions { namespace detail { // a hack square root calculation using simple operations @@ -15,20 +13,13 @@ double mysqrt(double x) return 0; } - // if we have both log and exp then use them -#if defined(HAVE_LOG) && defined(HAVE_EXP) - double result = exp(log(x) * 0.5); - std::cout << "Computing sqrt of " << x << " to be " << result << " using log" - << std::endl; -#else // use the table to help find an initial value double result = x; if (x >= 1 && x < 10) { + std::cout << "Use the table to help find an initial value " << std::endl; result = sqrtTable[static_cast<int>(x)]; } - // if we have both log and exp then use them - // do ten iterations for (int i = 0; i < 10; ++i) { if (result <= 0) { @@ -38,7 +29,7 @@ double mysqrt(double x) result = result + 0.5 * delta / result; std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; } -#endif + return result; } } diff --git a/Tests/Tutorial/Step9/MathFunctions/mysqrt.h b/Help/guide/tutorial/Complete/MathFunctions/mysqrt.h index e1c42ef..e1c42ef 100644 --- a/Tests/Tutorial/Step9/MathFunctions/mysqrt.h +++ b/Help/guide/tutorial/Complete/MathFunctions/mysqrt.h diff --git a/Tests/Tutorial/Step2/TutorialConfig.h.in b/Help/guide/tutorial/Complete/TutorialConfig.h.in index 5395a06..7e4d7fa 100644 --- a/Tests/Tutorial/Step2/TutorialConfig.h.in +++ b/Help/guide/tutorial/Complete/TutorialConfig.h.in @@ -1,4 +1,3 @@ // the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ - diff --git a/Tests/Tutorial/Complete/tutorial.cxx b/Help/guide/tutorial/Complete/tutorial.cxx index 443d195..586d183 100644 --- a/Tests/Tutorial/Complete/tutorial.cxx +++ b/Help/guide/tutorial/Complete/tutorial.cxx @@ -10,15 +10,16 @@ int main(int argc, char* argv[]) { if (argc < 2) { std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." - << Tutorial_VERSION_MAJOR << std::endl; + << Tutorial_VERSION_MINOR << std::endl; std::cout << "Usage: " << argv[0] << " number" << std::endl; return 1; } - double inputValue = std::stod(argv[1]); + // convert input to double + const double inputValue = std::stod(argv[1]); + // calculate square root const double outputValue = mathfunctions::sqrt(inputValue); - std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; return 0; diff --git a/Tests/Tutorial/Consumer/CMakeLists.txt b/Help/guide/tutorial/Consumer/CMakeLists.txt index 4033b4d..a0e4598 100644 --- a/Tests/Tutorial/Consumer/CMakeLists.txt +++ b/Help/guide/tutorial/Consumer/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.3) +cmake_minimum_required(VERSION 3.10) if(NOT DEFINED CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 11) diff --git a/Tests/Tutorial/Consumer/Config.cmake.in b/Help/guide/tutorial/Consumer/Config.cmake.in index 0b3f1e4..0b3f1e4 100644 --- a/Tests/Tutorial/Consumer/Config.cmake.in +++ b/Help/guide/tutorial/Consumer/Config.cmake.in diff --git a/Tests/Tutorial/Consumer/consumer.cxx b/Help/guide/tutorial/Consumer/consumer.cxx index ae7877b..ae7877b 100644 --- a/Tests/Tutorial/Consumer/consumer.cxx +++ b/Help/guide/tutorial/Consumer/consumer.cxx diff --git a/Tests/Tutorial/Complete/CMakeLists.txt b/Help/guide/tutorial/MultiPackage/CMakeLists.txt index 9658e65..01d417a 100644 --- a/Tests/Tutorial/Complete/CMakeLists.txt +++ b/Help/guide/tutorial/MultiPackage/CMakeLists.txt @@ -1,5 +1,11 @@ -cmake_minimum_required(VERSION 3.3) -project(Tutorial) +cmake_minimum_required(VERSION 3.10) + +# set the project name and version +project(Tutorial VERSION 1.0) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED True) + # control where the static and shared libraries are built so that on windows # we don't need to tinker with the path to run the executable @@ -7,15 +13,8 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED True) - option(BUILD_SHARED_LIBS "Build using shared libraries" ON) -# the version number. -set(Tutorial_VERSION_MAJOR 1) -set(Tutorial_VERSION_MINOR 0) - if(APPLE) set(CMAKE_INSTALL_RPATH "@executable_path/../lib") elseif(UNIX) @@ -23,17 +22,14 @@ elseif(UNIX) endif() # configure a header file to pass the version number only -configure_file( - "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" - "${PROJECT_BINARY_DIR}/TutorialConfig.h" - ) +configure_file(TutorialConfig.h.in TutorialConfig.h) # add the MathFunctions library add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial MathFunctions) +target_link_libraries(Tutorial PUBLIC MathFunctions) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h diff --git a/Tests/Tutorial/Complete/Config.cmake.in b/Help/guide/tutorial/MultiPackage/Config.cmake.in index 17cbabd..17cbabd 100644 --- a/Tests/Tutorial/Complete/Config.cmake.in +++ b/Help/guide/tutorial/MultiPackage/Config.cmake.in diff --git a/Tests/Tutorial/Step8/License.txt b/Help/guide/tutorial/MultiPackage/License.txt index c62d00b..c62d00b 100644 --- a/Tests/Tutorial/Step8/License.txt +++ b/Help/guide/tutorial/MultiPackage/License.txt diff --git a/Tests/Tutorial/MultiPackage/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/MultiPackage/MathFunctions/CMakeLists.txt index 161ad64..a2df2a7 100644 --- a/Tests/Tutorial/MultiPackage/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/MultiPackage/MathFunctions/CMakeLists.txt @@ -1,4 +1,3 @@ - # add the library that runs add_library(MathFunctions MathFunctions.cxx) @@ -14,11 +13,7 @@ target_include_directories(MathFunctions option(USE_MYMATH "Use tutorial provided math implementation" ON) if(USE_MYMATH) - # does this system provide the log and exp functions? - include(CheckSymbolExists) - set(CMAKE_REQUIRED_LIBRARIES "m") - check_symbol_exists(log "math.h" HAVE_LOG) - check_symbol_exists(exp "math.h" HAVE_EXP) + target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") # first we add the executable that generates the table add_executable(MakeTable MakeTable.cxx) @@ -41,19 +36,14 @@ if(USE_MYMATH) ${CMAKE_CURRENT_BINARY_DIR} ) + # state that SqrtLibrary need PIC when the default is shared libraries set_target_properties(SqrtLibrary PROPERTIES POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS} ) - target_compile_definitions(SqrtLibrary PRIVATE - "$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>" - "$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>" - ) target_link_libraries(MathFunctions PRIVATE SqrtLibrary) endif() -target_compile_definitions(MathFunctions PRIVATE "$<$<BOOL:${USE_MYMATH}>:USE_MYMATH>") - # define the symbol stating we are using the declspec(dllexport) when # building on windows target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH") @@ -62,6 +52,7 @@ target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH") set_property(TARGET MathFunctions PROPERTY VERSION "1.0.0") set_property(TARGET MathFunctions PROPERTY SOVERSION "1") +# install rules install(TARGETS MathFunctions DESTINATION lib EXPORT MathFunctionsTargets) diff --git a/Tests/Tutorial/Step8/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/MultiPackage/MathFunctions/MakeTable.cxx index ee58556..ee58556 100644 --- a/Tests/Tutorial/Step8/MathFunctions/MakeTable.cxx +++ b/Help/guide/tutorial/MultiPackage/MathFunctions/MakeTable.cxx diff --git a/Tests/Tutorial/Step11/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/MultiPackage/MathFunctions/MathFunctions.cxx index 5351184..5351184 100644 --- a/Tests/Tutorial/Step11/MathFunctions/MathFunctions.cxx +++ b/Help/guide/tutorial/MultiPackage/MathFunctions/MathFunctions.cxx diff --git a/Tests/Tutorial/Step10/MathFunctions/MathFunctions.h b/Help/guide/tutorial/MultiPackage/MathFunctions/MathFunctions.h index 3fb547b..3fb547b 100644 --- a/Tests/Tutorial/Step10/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/MultiPackage/MathFunctions/MathFunctions.h diff --git a/Tests/Tutorial/MultiPackage/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/MultiPackage/MathFunctions/mysqrt.cxx index 96d9421..4c212b3 100644 --- a/Tests/Tutorial/MultiPackage/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/MultiPackage/MathFunctions/mysqrt.cxx @@ -4,8 +4,6 @@ // include the generated table #include "Table.h" -#include <cmath> - namespace mathfunctions { namespace detail { // a hack square root calculation using simple operations @@ -15,12 +13,6 @@ double mysqrt(double x) return 0; } - // if we have both log and exp then use them -#if defined(HAVE_LOG) && defined(HAVE_EXP) - double result = exp(log(x) * 0.5); - std::cout << "Computing sqrt of " << x << " to be " << result << " using log" - << std::endl; -#else // use the table to help find an initial value double result = x; if (x >= 1 && x < 10) { @@ -38,7 +30,7 @@ double mysqrt(double x) result = result + 0.5 * delta / result; std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; } -#endif + return result; } } diff --git a/Tests/Tutorial/Step11/MathFunctions/mysqrt.h b/Help/guide/tutorial/MultiPackage/MathFunctions/mysqrt.h index e1c42ef..e1c42ef 100644 --- a/Tests/Tutorial/Step11/MathFunctions/mysqrt.h +++ b/Help/guide/tutorial/MultiPackage/MathFunctions/mysqrt.h diff --git a/Tests/Tutorial/MultiPackage/MultiCPackConfig.cmake b/Help/guide/tutorial/MultiPackage/MultiCPackConfig.cmake index 403b633..403b633 100644 --- a/Tests/Tutorial/MultiPackage/MultiCPackConfig.cmake +++ b/Help/guide/tutorial/MultiPackage/MultiCPackConfig.cmake diff --git a/Tests/Tutorial/Step9/TutorialConfig.h.in b/Help/guide/tutorial/MultiPackage/TutorialConfig.h.in index 8cd2fc9..8cd2fc9 100644 --- a/Tests/Tutorial/Step9/TutorialConfig.h.in +++ b/Help/guide/tutorial/MultiPackage/TutorialConfig.h.in diff --git a/Tests/Tutorial/Step11/tutorial.cxx b/Help/guide/tutorial/MultiPackage/tutorial.cxx index 3768855..f97805b 100644 --- a/Tests/Tutorial/Step11/tutorial.cxx +++ b/Help/guide/tutorial/MultiPackage/tutorial.cxx @@ -1,5 +1,4 @@ // A simple program that computes the square root of a number -#include <cmath> #include <iostream> #include <string> @@ -10,11 +9,12 @@ int main(int argc, char* argv[]) { if (argc < 2) { std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." - << Tutorial_VERSION_MAJOR << std::endl; + << Tutorial_VERSION_MINOR << std::endl; std::cout << "Usage: " << argv[0] << " number" << std::endl; return 1; } + // convert input to double double inputValue = std::stod(argv[1]); const double outputValue = mathfunctions::sqrt(inputValue); diff --git a/Tests/Tutorial/Step1/tutorial.cxx b/Help/guide/tutorial/Step1/tutorial.cxx index f8dd0c6..08323bf 100644 --- a/Tests/Tutorial/Step1/tutorial.cxx +++ b/Help/guide/tutorial/Step1/tutorial.cxx @@ -11,9 +11,11 @@ int main(int argc, char* argv[]) return 1; } - double inputValue = atof(argv[1]); + // convert input to double + const double inputValue = atof(argv[1]); - double outputValue = sqrt(inputValue); + // calculate square root + const double outputValue = sqrt(inputValue); std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; return 0; diff --git a/Tests/Tutorial/Step10/CMakeLists.txt b/Help/guide/tutorial/Step10/CMakeLists.txt index b1d46c4..34ae70c 100644 --- a/Tests/Tutorial/Step10/CMakeLists.txt +++ b/Help/guide/tutorial/Step10/CMakeLists.txt @@ -1,5 +1,11 @@ -cmake_minimum_required(VERSION 3.3) -project(Tutorial) +cmake_minimum_required(VERSION 3.10) + +# set the project name and version +project(Tutorial VERSION 1.0) + +# specify the C++ standard +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED True) # control where the static and shared libraries are built so that on windows # we don't need to tinker with the path to run the executable @@ -7,27 +13,17 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED True) - option(BUILD_SHARED_LIBS "Build using shared libraries" ON) -# the version number. -set(Tutorial_VERSION_MAJOR 1) -set(Tutorial_VERSION_MINOR 0) - # configure a header file to pass the version number only -configure_file( - "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" - "${PROJECT_BINARY_DIR}/TutorialConfig.h" - ) +configure_file(TutorialConfig.h.in TutorialConfig.h) # add the MathFunctions library add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial MathFunctions) +target_link_libraries(Tutorial PUBLIC MathFunctions) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h @@ -42,7 +38,7 @@ install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h" ) # enable testing -enable_testing() +include(CTest) # does the application run add_test(NAME Runs COMMAND Tutorial 25) diff --git a/Help/guide/tutorial/Step10/CTestConfig.cmake b/Help/guide/tutorial/Step10/CTestConfig.cmake new file mode 100644 index 0000000..73efdb1 --- /dev/null +++ b/Help/guide/tutorial/Step10/CTestConfig.cmake @@ -0,0 +1,7 @@ +set(CTEST_PROJECT_NAME "CMakeTutorial") +set(CTEST_NIGHTLY_START_TIME "00:00:00 EST") + +set(CTEST_DROP_METHOD "http") +set(CTEST_DROP_SITE "my.cdash.org") +set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial") +set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Tests/Tutorial/Step7/License.txt b/Help/guide/tutorial/Step10/License.txt index c62d00b..c62d00b 100644 --- a/Tests/Tutorial/Step7/License.txt +++ b/Help/guide/tutorial/Step10/License.txt diff --git a/Tests/Tutorial/Step10/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt index 7a23505..e0c0621 100644 --- a/Tests/Tutorial/Step10/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt @@ -1,4 +1,3 @@ - # add the library that runs add_library(MathFunctions MathFunctions.cxx) @@ -12,11 +11,7 @@ target_include_directories(MathFunctions option(USE_MYMATH "Use tutorial provided math implementation" ON) if(USE_MYMATH) - # does this system provide the log and exp functions? - include(CheckSymbolExists) - set(CMAKE_REQUIRED_LIBRARIES "m") - check_symbol_exists(log "math.h" HAVE_LOG) - check_symbol_exists(exp "math.h" HAVE_EXP) + target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") # first we add the executable that generates the table add_executable(MakeTable MakeTable.cxx) @@ -44,12 +39,6 @@ if(USE_MYMATH) POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS} ) - target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") - if(HAVE_LOG AND HAVE_EXP) - target_compile_definitions(SqrtLibrary - PRIVATE "HAVE_LOG" "HAVE_EXP") - endif() - target_link_libraries(MathFunctions PRIVATE SqrtLibrary) endif() @@ -57,5 +46,6 @@ endif() # building on windows target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH") +# install rules install(TARGETS MathFunctions DESTINATION lib) install(FILES MathFunctions.h DESTINATION include) diff --git a/Tests/Tutorial/Step7/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step10/MathFunctions/MakeTable.cxx index ee58556..ee58556 100644 --- a/Tests/Tutorial/Step7/MathFunctions/MakeTable.cxx +++ b/Help/guide/tutorial/Step10/MathFunctions/MakeTable.cxx diff --git a/Tests/Tutorial/Step10/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.cxx index 5351184..5351184 100644 --- a/Tests/Tutorial/Step10/MathFunctions/MathFunctions.cxx +++ b/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.cxx diff --git a/Tests/Tutorial/MultiPackage/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h index 3fb547b..3fb547b 100644 --- a/Tests/Tutorial/MultiPackage/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h diff --git a/Tests/Tutorial/Step11/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx index 96d9421..ff37312 100644 --- a/Tests/Tutorial/Step11/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx @@ -4,8 +4,6 @@ // include the generated table #include "Table.h" -#include <cmath> - namespace mathfunctions { namespace detail { // a hack square root calculation using simple operations @@ -15,20 +13,13 @@ double mysqrt(double x) return 0; } - // if we have both log and exp then use them -#if defined(HAVE_LOG) && defined(HAVE_EXP) - double result = exp(log(x) * 0.5); - std::cout << "Computing sqrt of " << x << " to be " << result << " using log" - << std::endl; -#else // use the table to help find an initial value double result = x; if (x >= 1 && x < 10) { + std::cout << "Use the table to help find an initial value " << std::endl; result = sqrtTable[static_cast<int>(x)]; } - // if we have both log and exp then use them - // do ten iterations for (int i = 0; i < 10; ++i) { if (result <= 0) { @@ -38,7 +29,7 @@ double mysqrt(double x) result = result + 0.5 * delta / result; std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; } -#endif + return result; } } diff --git a/Tests/Tutorial/Step10/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step10/MathFunctions/mysqrt.h index e1c42ef..e1c42ef 100644 --- a/Tests/Tutorial/Step10/MathFunctions/mysqrt.h +++ b/Help/guide/tutorial/Step10/MathFunctions/mysqrt.h diff --git a/Tests/Tutorial/Step1/TutorialConfig.h.in b/Help/guide/tutorial/Step10/TutorialConfig.h.in index 5395a06..7e4d7fa 100644 --- a/Tests/Tutorial/Step1/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step10/TutorialConfig.h.in @@ -1,4 +1,3 @@ // the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ - diff --git a/Tests/Tutorial/Step10/tutorial.cxx b/Help/guide/tutorial/Step10/tutorial.cxx index 443d195..37a0333 100644 --- a/Tests/Tutorial/Step10/tutorial.cxx +++ b/Help/guide/tutorial/Step10/tutorial.cxx @@ -9,13 +9,15 @@ int main(int argc, char* argv[]) { if (argc < 2) { + // report version std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." - << Tutorial_VERSION_MAJOR << std::endl; + << Tutorial_VERSION_MINOR << std::endl; std::cout << "Usage: " << argv[0] << " number" << std::endl; return 1; } - double inputValue = std::stod(argv[1]); + // convert input to double + const double inputValue = std::stod(argv[1]); const double outputValue = mathfunctions::sqrt(inputValue); diff --git a/Tests/Tutorial/Step11/CMakeLists.txt b/Help/guide/tutorial/Step11/CMakeLists.txt index b1d46c4..4763951 100644 --- a/Tests/Tutorial/Step11/CMakeLists.txt +++ b/Help/guide/tutorial/Step11/CMakeLists.txt @@ -1,5 +1,19 @@ -cmake_minimum_required(VERSION 3.3) -project(Tutorial) +cmake_minimum_required(VERSION 3.15) + +# set the project name and version +project(Tutorial VERSION 1.0) + +add_library(tutorial_compiler_flags INTERFACE) +target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11) + +# add compiler warning flags just when building this project via +# the BUILD_INTERFACE genex +set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU>") +set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") +target_compile_options(tutorial_compiler_flags INTERFACE + "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>" + "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" +) # control where the static and shared libraries are built so that on windows # we don't need to tinker with the path to run the executable @@ -7,27 +21,17 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED True) - option(BUILD_SHARED_LIBS "Build using shared libraries" ON) -# the version number. -set(Tutorial_VERSION_MAJOR 1) -set(Tutorial_VERSION_MINOR 0) - # configure a header file to pass the version number only -configure_file( - "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" - "${PROJECT_BINARY_DIR}/TutorialConfig.h" - ) +configure_file(TutorialConfig.h.in TutorialConfig.h) # add the MathFunctions library add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial MathFunctions) +target_link_libraries(Tutorial PUBLIC MathFunctions) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h diff --git a/Help/guide/tutorial/Step11/CTestConfig.cmake b/Help/guide/tutorial/Step11/CTestConfig.cmake new file mode 100644 index 0000000..73efdb1 --- /dev/null +++ b/Help/guide/tutorial/Step11/CTestConfig.cmake @@ -0,0 +1,7 @@ +set(CTEST_PROJECT_NAME "CMakeTutorial") +set(CTEST_NIGHTLY_START_TIME "00:00:00 EST") + +set(CTEST_DROP_METHOD "http") +set(CTEST_DROP_SITE "my.cdash.org") +set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial") +set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Tests/Tutorial/Step11/License.txt b/Help/guide/tutorial/Step11/License.txt index c62d00b..c62d00b 100644 --- a/Tests/Tutorial/Step11/License.txt +++ b/Help/guide/tutorial/Step11/License.txt diff --git a/Tests/Tutorial/Step11/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt index 760d6a5..e6cb8ba 100644 --- a/Tests/Tutorial/Step11/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt @@ -1,4 +1,3 @@ - # add the library that runs add_library(MathFunctions MathFunctions.cxx) @@ -12,14 +11,11 @@ target_include_directories(MathFunctions option(USE_MYMATH "Use tutorial provided math implementation" ON) if(USE_MYMATH) - # does this system provide the log and exp functions? - include(CheckSymbolExists) - set(CMAKE_REQUIRED_LIBRARIES "m") - check_symbol_exists(log "math.h" HAVE_LOG) - check_symbol_exists(exp "math.h" HAVE_EXP) + target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") # first we add the executable that generates the table add_executable(MakeTable MakeTable.cxx) + target_link_libraries(MakeTable tutorial_compiler_flags) # add the command to generate the source code add_custom_command( @@ -39,22 +35,21 @@ if(USE_MYMATH) ${CMAKE_CURRENT_BINARY_DIR} ) + # state that SqrtLibrary need PIC when the default is shared libraries set_target_properties(SqrtLibrary PROPERTIES POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS} ) - target_compile_definitions(SqrtLibrary PRIVATE - "$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>" - "$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>" - ) + target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags) target_link_libraries(MathFunctions PRIVATE SqrtLibrary) endif() -target_compile_definitions(MathFunctions PRIVATE "$<$<BOOL:${USE_MYMATH}>:USE_MYMATH>") +target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags) # define the symbol stating we are using the declspec(dllexport) when #building on windows target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH") +# install rules install(TARGETS MathFunctions DESTINATION lib) install(FILES MathFunctions.h DESTINATION include) diff --git a/Tests/Tutorial/Step6/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step11/MathFunctions/MakeTable.cxx index ee58556..ee58556 100644 --- a/Tests/Tutorial/Step6/MathFunctions/MakeTable.cxx +++ b/Help/guide/tutorial/Step11/MathFunctions/MakeTable.cxx diff --git a/Tests/Tutorial/MultiPackage/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step11/MathFunctions/MathFunctions.cxx index 5351184..5351184 100644 --- a/Tests/Tutorial/MultiPackage/MathFunctions/MathFunctions.cxx +++ b/Help/guide/tutorial/Step11/MathFunctions/MathFunctions.cxx diff --git a/Tests/Tutorial/Complete/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step11/MathFunctions/MathFunctions.h index 3fb547b..3fb547b 100644 --- a/Tests/Tutorial/Complete/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step11/MathFunctions/MathFunctions.h diff --git a/Help/guide/tutorial/Step11/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step11/MathFunctions/mysqrt.cxx new file mode 100644 index 0000000..ff37312 --- /dev/null +++ b/Help/guide/tutorial/Step11/MathFunctions/mysqrt.cxx @@ -0,0 +1,36 @@ +#include "MathFunctions.h" +#include <iostream> + +// include the generated table +#include "Table.h" + +namespace mathfunctions { +namespace detail { +// a hack square root calculation using simple operations +double mysqrt(double x) +{ + if (x <= 0) { + return 0; + } + + // use the table to help find an initial value + double result = x; + if (x >= 1 && x < 10) { + std::cout << "Use the table to help find an initial value " << std::endl; + result = sqrtTable[static_cast<int>(x)]; + } + + // do ten iterations + for (int i = 0; i < 10; ++i) { + if (result <= 0) { + result = 0.1; + } + double delta = x - (result * result); + result = result + 0.5 * delta / result; + std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; + } + + return result; +} +} +} diff --git a/Tests/Tutorial/MultiPackage/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step11/MathFunctions/mysqrt.h index e1c42ef..e1c42ef 100644 --- a/Tests/Tutorial/MultiPackage/MathFunctions/mysqrt.h +++ b/Help/guide/tutorial/Step11/MathFunctions/mysqrt.h diff --git a/Help/guide/tutorial/Step11/TutorialConfig.h.in b/Help/guide/tutorial/Step11/TutorialConfig.h.in new file mode 100644 index 0000000..7e4d7fa --- /dev/null +++ b/Help/guide/tutorial/Step11/TutorialConfig.h.in @@ -0,0 +1,3 @@ +// the configured options and settings for Tutorial +#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ +#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ diff --git a/Tests/Tutorial/MultiPackage/tutorial.cxx b/Help/guide/tutorial/Step11/tutorial.cxx index 443d195..a4f44d5 100644 --- a/Tests/Tutorial/MultiPackage/tutorial.cxx +++ b/Help/guide/tutorial/Step11/tutorial.cxx @@ -1,6 +1,5 @@ // A simple program that computes the square root of a number #include <iostream> -#include <sstream> #include <string> #include "MathFunctions.h" @@ -9,13 +8,15 @@ int main(int argc, char* argv[]) { if (argc < 2) { + // report version std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." - << Tutorial_VERSION_MAJOR << std::endl; + << Tutorial_VERSION_MINOR << std::endl; std::cout << "Usage: " << argv[0] << " number" << std::endl; return 1; } - double inputValue = std::stod(argv[1]); + // convert input to double + const double inputValue = std::stod(argv[1]); const double outputValue = mathfunctions::sqrt(inputValue); diff --git a/Tests/Tutorial/Step2/CMakeLists.txt b/Help/guide/tutorial/Step2/CMakeLists.txt index 48afaa3..7aa59e9 100644 --- a/Tests/Tutorial/Step2/CMakeLists.txt +++ b/Help/guide/tutorial/Step2/CMakeLists.txt @@ -1,19 +1,15 @@ -cmake_minimum_required(VERSION 3.3) -project(Tutorial) +cmake_minimum_required(VERSION 3.10) +# set the project name and version +project(Tutorial VERSION 1.0) + +# specify the C++ standard set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) -# the version number. -set(Tutorial_VERSION_MAJOR 1) -set(Tutorial_VERSION_MINOR 0) - # configure a header file to pass some of the CMake settings # to the source code -configure_file( - "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" - "${PROJECT_BINARY_DIR}/TutorialConfig.h" - ) +configure_file(TutorialConfig.h.in TutorialConfig.h) # add the executable add_executable(Tutorial tutorial.cxx) diff --git a/Tests/Tutorial/Step9/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step2/MathFunctions/MathFunctions.h index cd36bcc..cd36bcc 100644 --- a/Tests/Tutorial/Step9/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step2/MathFunctions/MathFunctions.h diff --git a/Tests/Tutorial/Step2/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step2/MathFunctions/mysqrt.cxx index 7d9379e..1e4d97a 100644 --- a/Tests/Tutorial/Step2/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step2/MathFunctions/mysqrt.cxx @@ -1,4 +1,3 @@ -#include "MathFunctions.h" #include <iostream> // a hack square root calculation using simple operations diff --git a/Help/guide/tutorial/Step2/TutorialConfig.h.in b/Help/guide/tutorial/Step2/TutorialConfig.h.in new file mode 100644 index 0000000..7e4d7fa --- /dev/null +++ b/Help/guide/tutorial/Step2/TutorialConfig.h.in @@ -0,0 +1,3 @@ +// the configured options and settings for Tutorial +#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ +#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ diff --git a/Tests/Tutorial/Step2/tutorial.cxx b/Help/guide/tutorial/Step2/tutorial.cxx index 75b7d67..53b0810 100644 --- a/Tests/Tutorial/Step2/tutorial.cxx +++ b/Help/guide/tutorial/Step2/tutorial.cxx @@ -8,15 +8,18 @@ int main(int argc, char* argv[]) { if (argc < 2) { + // report version std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." - << Tutorial_VERSION_MAJOR << std::endl; + << Tutorial_VERSION_MINOR << std::endl; std::cout << "Usage: " << argv[0] << " number" << std::endl; return 1; } - double inputValue = std::stod(argv[1]); + // convert input to double + const double inputValue = std::stod(argv[1]); - double outputValue = sqrt(inputValue); + // calculate square root + const double outputValue = sqrt(inputValue); std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; return 0; diff --git a/Tests/Tutorial/Step3/CMakeLists.txt b/Help/guide/tutorial/Step3/CMakeLists.txt index f904ea7..1c12816 100644 --- a/Tests/Tutorial/Step3/CMakeLists.txt +++ b/Help/guide/tutorial/Step3/CMakeLists.txt @@ -1,34 +1,30 @@ -cmake_minimum_required(VERSION 3.3) -project(Tutorial) +cmake_minimum_required(VERSION 3.10) +# set the project name and version +project(Tutorial VERSION 1.0) + +# specify the C++ standard set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) -# the version number. -set(Tutorial_VERSION_MAJOR 1) -set(Tutorial_VERSION_MINOR 0) - # configure a header file to pass some of the CMake settings # to the source code -configure_file( - "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" - "${PROJECT_BINARY_DIR}/TutorialConfig.h" - ) +configure_file(TutorialConfig.h.in TutorialConfig.h) -# add the MathFunctions library? +# add the MathFunctions library if(USE_MYMATH) add_subdirectory(MathFunctions) list(APPEND EXTRA_LIBS MathFunctions) list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions") -endif(USE_MYMATH) +endif() # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial ${EXTRA_LIBS}) +target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h diff --git a/Tests/Tutorial/Step3/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt index 8b443a6..8b443a6 100644 --- a/Tests/Tutorial/Step3/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt diff --git a/Tests/Tutorial/Step8/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step3/MathFunctions/MathFunctions.h index cd36bcc..cd36bcc 100644 --- a/Tests/Tutorial/Step8/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step3/MathFunctions/MathFunctions.h diff --git a/Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step3/MathFunctions/mysqrt.cxx index 7d9379e..7d9379e 100644 --- a/Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step3/MathFunctions/mysqrt.cxx diff --git a/Tests/Tutorial/Step5/TutorialConfig.h.in b/Help/guide/tutorial/Step3/TutorialConfig.h.in index 25a0602..e23f521 100644 --- a/Tests/Tutorial/Step5/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step3/TutorialConfig.h.in @@ -2,4 +2,3 @@ #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ #cmakedefine USE_MYMATH - diff --git a/Tests/Tutorial/Step5/tutorial.cxx b/Help/guide/tutorial/Step3/tutorial.cxx index 1d5742d..b3c6a4f 100644 --- a/Tests/Tutorial/Step5/tutorial.cxx +++ b/Help/guide/tutorial/Step3/tutorial.cxx @@ -5,6 +5,7 @@ #include "TutorialConfig.h" +// should we include the MathFunctions header? #ifdef USE_MYMATH # include "MathFunctions.h" #endif @@ -12,18 +13,21 @@ int main(int argc, char* argv[]) { if (argc < 2) { + // report version std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." - << Tutorial_VERSION_MAJOR << std::endl; + << Tutorial_VERSION_MINOR << std::endl; std::cout << "Usage: " << argv[0] << " number" << std::endl; return 1; } - double inputValue = std::stod(argv[1]); + // convert input to double + const double inputValue = std::stod(argv[1]); + // which square root function should we use? #ifdef USE_MYMATH - double outputValue = mysqrt(inputValue); + const double outputValue = mysqrt(inputValue); #else - double outputValue = sqrt(inputValue); + const double outputValue = sqrt(inputValue); #endif std::cout << "The square root of " << inputValue << " is " << outputValue diff --git a/Tests/Tutorial/Step4/CMakeLists.txt b/Help/guide/tutorial/Step4/CMakeLists.txt index 34eab55..38e9b1f 100644 --- a/Tests/Tutorial/Step4/CMakeLists.txt +++ b/Help/guide/tutorial/Step4/CMakeLists.txt @@ -1,28 +1,24 @@ -cmake_minimum_required(VERSION 3.3) -project(Tutorial) +cmake_minimum_required(VERSION 3.10) +# set the project name and version +project(Tutorial VERSION 1.0) + +# specify the C++ standard set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) -# the version number. -set(Tutorial_VERSION_MAJOR 1) -set(Tutorial_VERSION_MINOR 0) - # configure a header file to pass some of the CMake settings # to the source code -configure_file( - "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" - "${PROJECT_BINARY_DIR}/TutorialConfig.h" - ) +configure_file(TutorialConfig.h.in TutorialConfig.h) -# add the MathFunctions library? +# add the MathFunctions library if(USE_MYMATH) add_subdirectory(MathFunctions) list(APPEND EXTRA_LIBS MathFunctions) -endif(USE_MYMATH) +endif() # add the executable add_executable(Tutorial tutorial.cxx) diff --git a/Tests/Tutorial/Step4/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt index 0515852..0515852 100644 --- a/Tests/Tutorial/Step4/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt diff --git a/Tests/Tutorial/Step7/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step4/MathFunctions/MathFunctions.h index cd36bcc..cd36bcc 100644 --- a/Tests/Tutorial/Step7/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step4/MathFunctions/MathFunctions.h diff --git a/Tests/Tutorial/Step4/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step4/MathFunctions/mysqrt.cxx index 7d9379e..7d9379e 100644 --- a/Tests/Tutorial/Step4/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step4/MathFunctions/mysqrt.cxx diff --git a/Tests/Tutorial/Step3/TutorialConfig.h.in b/Help/guide/tutorial/Step4/TutorialConfig.h.in index 25a0602..e23f521 100644 --- a/Tests/Tutorial/Step3/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step4/TutorialConfig.h.in @@ -2,4 +2,3 @@ #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ #cmakedefine USE_MYMATH - diff --git a/Tests/Tutorial/Step6/tutorial.cxx b/Help/guide/tutorial/Step4/tutorial.cxx index 1d5742d..b3c6a4f 100644 --- a/Tests/Tutorial/Step6/tutorial.cxx +++ b/Help/guide/tutorial/Step4/tutorial.cxx @@ -5,6 +5,7 @@ #include "TutorialConfig.h" +// should we include the MathFunctions header? #ifdef USE_MYMATH # include "MathFunctions.h" #endif @@ -12,18 +13,21 @@ int main(int argc, char* argv[]) { if (argc < 2) { + // report version std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." - << Tutorial_VERSION_MAJOR << std::endl; + << Tutorial_VERSION_MINOR << std::endl; std::cout << "Usage: " << argv[0] << " number" << std::endl; return 1; } - double inputValue = std::stod(argv[1]); + // convert input to double + const double inputValue = std::stod(argv[1]); + // which square root function should we use? #ifdef USE_MYMATH - double outputValue = mysqrt(inputValue); + const double outputValue = mysqrt(inputValue); #else - double outputValue = sqrt(inputValue); + const double outputValue = sqrt(inputValue); #endif std::cout << "The square root of " << inputValue << " is " << outputValue diff --git a/Tests/Tutorial/Step5/CMakeLists.txt b/Help/guide/tutorial/Step5/CMakeLists.txt index 63e5410..c3b375a 100644 --- a/Tests/Tutorial/Step5/CMakeLists.txt +++ b/Help/guide/tutorial/Step5/CMakeLists.txt @@ -1,24 +1,20 @@ -cmake_minimum_required(VERSION 3.3) -project(Tutorial) +cmake_minimum_required(VERSION 3.10) +# set the project name and version +project(Tutorial VERSION 1.0) + +# specify the C++ standard set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) -# the version number. -set(Tutorial_VERSION_MAJOR 1) -set(Tutorial_VERSION_MINOR 0) - # configure a header file to pass some of the CMake settings # to the source code -configure_file( - "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" - "${PROJECT_BINARY_DIR}/TutorialConfig.h" - ) +configure_file(TutorialConfig.h.in TutorialConfig.h) -# add the MathFunctions library? +# add the MathFunctions library if(USE_MYMATH) add_subdirectory(MathFunctions) list(APPEND EXTRA_LIBS MathFunctions) diff --git a/Tests/Tutorial/Step5/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt index 11cf412..b12f27d 100644 --- a/Tests/Tutorial/Step5/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt @@ -6,5 +6,6 @@ target_include_directories(MathFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} ) +# install rules install(TARGETS MathFunctions DESTINATION lib) install(FILES MathFunctions.h DESTINATION include) diff --git a/Tests/Tutorial/Step5/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step5/MathFunctions/MakeTable.cxx index ee58556..ee58556 100644 --- a/Tests/Tutorial/Step5/MathFunctions/MakeTable.cxx +++ b/Help/guide/tutorial/Step5/MathFunctions/MakeTable.cxx diff --git a/Tests/Tutorial/Step6/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step5/MathFunctions/MathFunctions.h index cd36bcc..cd36bcc 100644 --- a/Tests/Tutorial/Step6/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step5/MathFunctions/MathFunctions.h diff --git a/Tests/Tutorial/Step3/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step5/MathFunctions/mysqrt.cxx index 7d9379e..7d9379e 100644 --- a/Tests/Tutorial/Step3/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step5/MathFunctions/mysqrt.cxx diff --git a/Tests/Tutorial/Step4/TutorialConfig.h.in b/Help/guide/tutorial/Step5/TutorialConfig.h.in index 25a0602..e23f521 100644 --- a/Tests/Tutorial/Step4/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step5/TutorialConfig.h.in @@ -2,4 +2,3 @@ #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ #cmakedefine USE_MYMATH - diff --git a/Tests/Tutorial/Step3/tutorial.cxx b/Help/guide/tutorial/Step5/tutorial.cxx index 1d5742d..b3c6a4f 100644 --- a/Tests/Tutorial/Step3/tutorial.cxx +++ b/Help/guide/tutorial/Step5/tutorial.cxx @@ -5,6 +5,7 @@ #include "TutorialConfig.h" +// should we include the MathFunctions header? #ifdef USE_MYMATH # include "MathFunctions.h" #endif @@ -12,18 +13,21 @@ int main(int argc, char* argv[]) { if (argc < 2) { + // report version std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." - << Tutorial_VERSION_MAJOR << std::endl; + << Tutorial_VERSION_MINOR << std::endl; std::cout << "Usage: " << argv[0] << " number" << std::endl; return 1; } - double inputValue = std::stod(argv[1]); + // convert input to double + const double inputValue = std::stod(argv[1]); + // which square root function should we use? #ifdef USE_MYMATH - double outputValue = mysqrt(inputValue); + const double outputValue = mysqrt(inputValue); #else - double outputValue = sqrt(inputValue); + const double outputValue = sqrt(inputValue); #endif std::cout << "The square root of " << inputValue << " is " << outputValue diff --git a/Tests/Tutorial/Step6/CMakeLists.txt b/Help/guide/tutorial/Step6/CMakeLists.txt index 503a312..c3b375a 100644 --- a/Tests/Tutorial/Step6/CMakeLists.txt +++ b/Help/guide/tutorial/Step6/CMakeLists.txt @@ -1,30 +1,20 @@ -cmake_minimum_required(VERSION 3.3) -project(Tutorial) +cmake_minimum_required(VERSION 3.10) +# set the project name and version +project(Tutorial VERSION 1.0) + +# specify the C++ standard set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) -# the version number. -set(Tutorial_VERSION_MAJOR 1) -set(Tutorial_VERSION_MINOR 0) - -# does this system provide the log and exp functions? -include(CheckSymbolExists) -set(CMAKE_REQUIRED_LIBRARIES "m") -check_symbol_exists(log "math.h" HAVE_LOG) -check_symbol_exists(exp "math.h" HAVE_EXP) - # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) # configure a header file to pass some of the CMake settings # to the source code -configure_file( - "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" - "${PROJECT_BINARY_DIR}/TutorialConfig.h" - ) +configure_file(TutorialConfig.h.in TutorialConfig.h) -# add the MathFunctions library? +# add the MathFunctions library if(USE_MYMATH) add_subdirectory(MathFunctions) list(APPEND EXTRA_LIBS MathFunctions) diff --git a/Tests/Tutorial/Step6/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt index 2946075..4bf6024 100644 --- a/Tests/Tutorial/Step6/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt @@ -2,13 +2,21 @@ add_library(MathFunctions mysqrt.cxx) # state that anybody linking to us needs to include the current source dir # to find MathFunctions.h, while we don't. -# state that we depend on Tutorial_BINARY_DIR but consumers don't, as the -# TutorialConfig.h include is an implementation detail - target_include_directories(MathFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} - PRIVATE ${Tutorial_BINARY_DIR} ) +# does this system provide the log and exp functions? +include(CheckSymbolExists) +set(CMAKE_REQUIRED_LIBRARIES "m") +check_symbol_exists(log "math.h" HAVE_LOG) +check_symbol_exists(exp "math.h" HAVE_EXP) + +if(HAVE_LOG AND HAVE_EXP) + target_compile_definitions(MathFunctions + PRIVATE "HAVE_LOG" "HAVE_EXP") +endif() + +# install rules install(TARGETS MathFunctions DESTINATION lib) install(FILES MathFunctions.h DESTINATION include) diff --git a/Tests/Tutorial/Step11/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx index ee58556..ee58556 100644 --- a/Tests/Tutorial/Step11/MathFunctions/MakeTable.cxx +++ b/Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx diff --git a/Tests/Tutorial/Step5/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step6/MathFunctions/MathFunctions.h index cd36bcc..cd36bcc 100644 --- a/Tests/Tutorial/Step5/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step6/MathFunctions/MathFunctions.h diff --git a/Tests/Tutorial/Step6/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx index b9ad20a..3f23245 100644 --- a/Tests/Tutorial/Step6/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx @@ -1,5 +1,4 @@ #include "MathFunctions.h" -#include "TutorialConfig.h" #include <iostream> #include <cmath> @@ -14,8 +13,8 @@ double mysqrt(double x) // if we have both log and exp then use them #if defined(HAVE_LOG) && defined(HAVE_EXP) double result = exp(log(x) * 0.5); - std::cout << "Computing sqrt of " << x << " to be " << result << " using log" - << std::endl; + std::cout << "Computing sqrt of " << x << " to be " << result + << " using log and exp" << std::endl; #else double result = x; diff --git a/Help/guide/tutorial/Step6/TutorialConfig.h.in b/Help/guide/tutorial/Step6/TutorialConfig.h.in new file mode 100644 index 0000000..e23f521 --- /dev/null +++ b/Help/guide/tutorial/Step6/TutorialConfig.h.in @@ -0,0 +1,4 @@ +// the configured options and settings for Tutorial +#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ +#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ +#cmakedefine USE_MYMATH diff --git a/Tests/Tutorial/Step4/tutorial.cxx b/Help/guide/tutorial/Step6/tutorial.cxx index 1d5742d..b3c6a4f 100644 --- a/Tests/Tutorial/Step4/tutorial.cxx +++ b/Help/guide/tutorial/Step6/tutorial.cxx @@ -5,6 +5,7 @@ #include "TutorialConfig.h" +// should we include the MathFunctions header? #ifdef USE_MYMATH # include "MathFunctions.h" #endif @@ -12,18 +13,21 @@ int main(int argc, char* argv[]) { if (argc < 2) { + // report version std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." - << Tutorial_VERSION_MAJOR << std::endl; + << Tutorial_VERSION_MINOR << std::endl; std::cout << "Usage: " << argv[0] << " number" << std::endl; return 1; } - double inputValue = std::stod(argv[1]); + // convert input to double + const double inputValue = std::stod(argv[1]); + // which square root function should we use? #ifdef USE_MYMATH - double outputValue = mysqrt(inputValue); + const double outputValue = mysqrt(inputValue); #else - double outputValue = sqrt(inputValue); + const double outputValue = sqrt(inputValue); #endif std::cout << "The square root of " << inputValue << " is " << outputValue diff --git a/Tests/Tutorial/Step7/CMakeLists.txt b/Help/guide/tutorial/Step7/CMakeLists.txt index f2d3839..c3b375a 100644 --- a/Tests/Tutorial/Step7/CMakeLists.txt +++ b/Help/guide/tutorial/Step7/CMakeLists.txt @@ -1,34 +1,24 @@ -cmake_minimum_required(VERSION 3.3) -project(Tutorial) +cmake_minimum_required(VERSION 3.10) +# set the project name and version +project(Tutorial VERSION 1.0) + +# specify the C++ standard set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) -# the version number. -set(Tutorial_VERSION_MAJOR 1) -set(Tutorial_VERSION_MINOR 0) - -# does this system provide the log and exp functions? -include(CheckSymbolExists) -set(CMAKE_REQUIRED_LIBRARIES "m") -check_symbol_exists(log "math.h" HAVE_LOG) -check_symbol_exists(exp "math.h" HAVE_EXP) - # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) # configure a header file to pass some of the CMake settings # to the source code -configure_file( - "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" - "${PROJECT_BINARY_DIR}/TutorialConfig.h" - ) +configure_file(TutorialConfig.h.in TutorialConfig.h) -# add the MathFunctions library? +# add the MathFunctions library if(USE_MYMATH) add_subdirectory(MathFunctions) list(APPEND EXTRA_LIBS MathFunctions) -endif(USE_MYMATH) +endif() # add the executable add_executable(Tutorial tutorial.cxx) @@ -38,7 +28,7 @@ target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) # so that we will find TutorialConfig.h target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}" - ) + ) # add the install targets install(TARGETS Tutorial DESTINATION bin) diff --git a/Tests/Tutorial/Step10/License.txt b/Help/guide/tutorial/Step7/License.txt index c62d00b..c62d00b 100644 --- a/Tests/Tutorial/Step10/License.txt +++ b/Help/guide/tutorial/Step7/License.txt diff --git a/Tests/Tutorial/Step8/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt index dc3eb98..9ede4b3 100644 --- a/Tests/Tutorial/Step8/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt @@ -21,9 +21,9 @@ add_library(MathFunctions # state that we depend on our binary dir to find Table.h target_include_directories(MathFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} - PRIVATE ${Tutorial_BINARY_DIR} - ${CMAKE_CURRENT_BINARY_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ) +# install rules install(TARGETS MathFunctions DESTINATION lib) install(FILES MathFunctions.h DESTINATION include) diff --git a/Tests/Tutorial/Step10/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step7/MathFunctions/MakeTable.cxx index ee58556..ee58556 100644 --- a/Tests/Tutorial/Step10/MathFunctions/MakeTable.cxx +++ b/Help/guide/tutorial/Step7/MathFunctions/MakeTable.cxx diff --git a/Tests/Tutorial/Step4/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step7/MathFunctions/MathFunctions.h index cd36bcc..cd36bcc 100644 --- a/Tests/Tutorial/Step4/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step7/MathFunctions/MathFunctions.h diff --git a/Tests/Tutorial/Step7/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx index 5272f56..2ae60c6 100644 --- a/Tests/Tutorial/Step7/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx @@ -1,12 +1,9 @@ #include "MathFunctions.h" -#include "TutorialConfig.h" #include <iostream> // include the generated table #include "Table.h" -#include <cmath> - // a hack square root calculation using simple operations double mysqrt(double x) { @@ -17,6 +14,7 @@ double mysqrt(double x) // use the table to help find an initial value double result = x; if (x >= 1 && x < 10) { + std::cout << "Use the table to help find an initial value " << std::endl; result = sqrtTable[static_cast<int>(x)]; } diff --git a/Help/guide/tutorial/Step7/TutorialConfig.h.in b/Help/guide/tutorial/Step7/TutorialConfig.h.in new file mode 100644 index 0000000..e23f521 --- /dev/null +++ b/Help/guide/tutorial/Step7/TutorialConfig.h.in @@ -0,0 +1,4 @@ +// the configured options and settings for Tutorial +#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ +#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ +#cmakedefine USE_MYMATH diff --git a/Help/guide/tutorial/Step7/tutorial.cxx b/Help/guide/tutorial/Step7/tutorial.cxx new file mode 100644 index 0000000..b3c6a4f --- /dev/null +++ b/Help/guide/tutorial/Step7/tutorial.cxx @@ -0,0 +1,36 @@ +// A simple program that computes the square root of a number +#include <cmath> +#include <iostream> +#include <string> + +#include "TutorialConfig.h" + +// should we include the MathFunctions header? +#ifdef USE_MYMATH +# include "MathFunctions.h" +#endif + +int main(int argc, char* argv[]) +{ + if (argc < 2) { + // report version + std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." + << Tutorial_VERSION_MINOR << std::endl; + std::cout << "Usage: " << argv[0] << " number" << std::endl; + return 1; + } + + // convert input to double + const double inputValue = std::stod(argv[1]); + + // which square root function should we use? +#ifdef USE_MYMATH + const double outputValue = mysqrt(inputValue); +#else + const double outputValue = sqrt(inputValue); +#endif + + std::cout << "The square root of " << inputValue << " is " << outputValue + << std::endl; + return 0; +} diff --git a/Tests/Tutorial/Step8/CMakeLists.txt b/Help/guide/tutorial/Step8/CMakeLists.txt index c66bf96..19b9913 100644 --- a/Tests/Tutorial/Step8/CMakeLists.txt +++ b/Help/guide/tutorial/Step8/CMakeLists.txt @@ -1,34 +1,24 @@ -cmake_minimum_required(VERSION 3.3) -project(Tutorial) +cmake_minimum_required(VERSION 3.10) +# set the project name and version +project(Tutorial VERSION 1.0) + +# specify the C++ standard set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) -# the version number. -set(Tutorial_VERSION_MAJOR 1) -set(Tutorial_VERSION_MINOR 0) - -# does this system provide the log and exp functions? -include(CheckSymbolExists) -set(CMAKE_REQUIRED_LIBRARIES "m") -check_symbol_exists(log "math.h" HAVE_LOG) -check_symbol_exists(exp "math.h" HAVE_EXP) - # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) # configure a header file to pass some of the CMake settings # to the source code -configure_file( - "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" - "${PROJECT_BINARY_DIR}/TutorialConfig.h" - ) +configure_file(TutorialConfig.h.in TutorialConfig.h) -# add the MathFunctions library? +# add the MathFunctions library if(USE_MYMATH) add_subdirectory(MathFunctions) list(APPEND EXTRA_LIBS MathFunctions) -endif(USE_MYMATH) +endif() # add the executable add_executable(Tutorial tutorial.cxx) @@ -60,7 +50,7 @@ set_tests_properties(Usage # define a function to simplify adding tests function(do_test target arg result) -add_test(NAME Comp${arg} COMMAND ${target} ${arg}) + add_test(NAME Comp${arg} COMMAND ${target} ${arg}) set_tests_properties(Comp${arg} PROPERTIES PASS_REGULAR_EXPRESSION ${result} ) @@ -75,6 +65,7 @@ do_test(Tutorial 25 "25 is 5") do_test(Tutorial -25 "-25 is [-nan|nan|0]") do_test(Tutorial 0.0001 "0.0001 is 0.01") +# setup installer include(InstallRequiredSystemLibraries) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}") diff --git a/Tests/Tutorial/MultiPackage/License.txt b/Help/guide/tutorial/Step8/License.txt index c62d00b..c62d00b 100644 --- a/Tests/Tutorial/MultiPackage/License.txt +++ b/Help/guide/tutorial/Step8/License.txt diff --git a/Tests/Tutorial/Step7/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt index dc3eb98..9ede4b3 100644 --- a/Tests/Tutorial/Step7/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt @@ -21,9 +21,9 @@ add_library(MathFunctions # state that we depend on our binary dir to find Table.h target_include_directories(MathFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} - PRIVATE ${Tutorial_BINARY_DIR} - ${CMAKE_CURRENT_BINARY_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ) +# install rules install(TARGETS MathFunctions DESTINATION lib) install(FILES MathFunctions.h DESTINATION include) diff --git a/Tests/Tutorial/MultiPackage/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step8/MathFunctions/MakeTable.cxx index ee58556..ee58556 100644 --- a/Tests/Tutorial/MultiPackage/MathFunctions/MakeTable.cxx +++ b/Help/guide/tutorial/Step8/MathFunctions/MakeTable.cxx diff --git a/Tests/Tutorial/Step3/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step8/MathFunctions/MathFunctions.h index cd36bcc..cd36bcc 100644 --- a/Tests/Tutorial/Step3/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step8/MathFunctions/MathFunctions.h diff --git a/Tests/Tutorial/Step9/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx index 8b82141..2ae60c6 100644 --- a/Tests/Tutorial/Step9/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx @@ -4,8 +4,6 @@ // include the generated table #include "Table.h" -#include <cmath> - // a hack square root calculation using simple operations double mysqrt(double x) { @@ -13,20 +11,13 @@ double mysqrt(double x) return 0; } - // if we have both log and exp then use them -#if defined(HAVE_LOG) && defined(HAVE_EXP) - double result = exp(log(x) * 0.5); - std::cout << "Computing sqrt of " << x << " to be " << result << " using log" - << std::endl; -#else // use the table to help find an initial value double result = x; if (x >= 1 && x < 10) { + std::cout << "Use the table to help find an initial value " << std::endl; result = sqrtTable[static_cast<int>(x)]; } - // if we have both log and exp then use them - // do ten iterations for (int i = 0; i < 10; ++i) { if (result <= 0) { @@ -36,6 +27,6 @@ double mysqrt(double x) result = result + 0.5 * delta / result; std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; } -#endif + return result; } diff --git a/Help/guide/tutorial/Step8/TutorialConfig.h.in b/Help/guide/tutorial/Step8/TutorialConfig.h.in new file mode 100644 index 0000000..e23f521 --- /dev/null +++ b/Help/guide/tutorial/Step8/TutorialConfig.h.in @@ -0,0 +1,4 @@ +// the configured options and settings for Tutorial +#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ +#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ +#cmakedefine USE_MYMATH diff --git a/Help/guide/tutorial/Step8/tutorial.cxx b/Help/guide/tutorial/Step8/tutorial.cxx new file mode 100644 index 0000000..b3c6a4f --- /dev/null +++ b/Help/guide/tutorial/Step8/tutorial.cxx @@ -0,0 +1,36 @@ +// A simple program that computes the square root of a number +#include <cmath> +#include <iostream> +#include <string> + +#include "TutorialConfig.h" + +// should we include the MathFunctions header? +#ifdef USE_MYMATH +# include "MathFunctions.h" +#endif + +int main(int argc, char* argv[]) +{ + if (argc < 2) { + // report version + std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." + << Tutorial_VERSION_MINOR << std::endl; + std::cout << "Usage: " << argv[0] << " number" << std::endl; + return 1; + } + + // convert input to double + const double inputValue = std::stod(argv[1]); + + // which square root function should we use? +#ifdef USE_MYMATH + const double outputValue = mysqrt(inputValue); +#else + const double outputValue = sqrt(inputValue); +#endif + + std::cout << "The square root of " << inputValue << " is " << outputValue + << std::endl; + return 0; +} diff --git a/Tests/Tutorial/Step9/CMakeLists.txt b/Help/guide/tutorial/Step9/CMakeLists.txt index 309d513..d5f1cc8 100644 --- a/Tests/Tutorial/Step9/CMakeLists.txt +++ b/Help/guide/tutorial/Step9/CMakeLists.txt @@ -1,29 +1,20 @@ -cmake_minimum_required(VERSION 3.3) -project(Tutorial) +cmake_minimum_required(VERSION 3.10) +# set the project name and version +project(Tutorial VERSION 1.0) + +# specify the C++ standard set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) -# the version number. -set(Tutorial_VERSION_MAJOR 1) -set(Tutorial_VERSION_MINOR 0) - -# does this system provide the log and exp functions? -include(CheckSymbolExists) -set(CMAKE_REQUIRED_LIBRARIES "m") -check_symbol_exists(log "math.h" HAVE_LOG) -check_symbol_exists(exp "math.h" HAVE_EXP) - # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) -# configure a header file to pass the version number only -configure_file( - "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" - "${PROJECT_BINARY_DIR}/TutorialConfig.h" - ) +# configure a header file to pass some of the CMake settings +# to the source code +configure_file(TutorialConfig.h.in TutorialConfig.h) -# add the MathFunctions library? +# add the MathFunctions library if(USE_MYMATH) add_subdirectory(MathFunctions) list(APPEND EXTRA_LIBS MathFunctions) diff --git a/Help/guide/tutorial/Step9/CTestConfig.cmake b/Help/guide/tutorial/Step9/CTestConfig.cmake new file mode 100644 index 0000000..73efdb1 --- /dev/null +++ b/Help/guide/tutorial/Step9/CTestConfig.cmake @@ -0,0 +1,7 @@ +set(CTEST_PROJECT_NAME "CMakeTutorial") +set(CTEST_NIGHTLY_START_TIME "00:00:00 EST") + +set(CTEST_DROP_METHOD "http") +set(CTEST_DROP_SITE "my.cdash.org") +set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial") +set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Tests/Tutorial/Complete/License.txt b/Help/guide/tutorial/Step9/License.txt index c62d00b..c62d00b 100644 --- a/Tests/Tutorial/Complete/License.txt +++ b/Help/guide/tutorial/Step9/License.txt diff --git a/Tests/Tutorial/Step9/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt index e651a57..50f0701 100644 --- a/Tests/Tutorial/Step9/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt @@ -22,14 +22,6 @@ target_include_directories(MathFunctions PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ) -# use compile definitions to state if we have enabled USE_MYMATH -# and that anything that links to use will get this define -target_compile_definitions(MathFunctions INTERFACE "USE_MYMATH") - -if(HAVE_LOG AND HAVE_EXP) - target_compile_definitions(MathFunctions - PRIVATE "HAVE_LOG" "HAVE_EXP") -endif() - +# install rules install(TARGETS MathFunctions DESTINATION lib) install(FILES MathFunctions.h DESTINATION include) diff --git a/Tests/Tutorial/Complete/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step9/MathFunctions/MakeTable.cxx index ee58556..ee58556 100644 --- a/Tests/Tutorial/Complete/MathFunctions/MakeTable.cxx +++ b/Help/guide/tutorial/Step9/MathFunctions/MakeTable.cxx diff --git a/Tests/Tutorial/Complete/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.cxx index 5351184..5351184 100644 --- a/Tests/Tutorial/Complete/MathFunctions/MathFunctions.cxx +++ b/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.cxx diff --git a/Tests/Tutorial/Step2/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.h index cd36bcc..cd36bcc 100644 --- a/Tests/Tutorial/Step2/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.h diff --git a/Tests/Tutorial/Step8/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step9/MathFunctions/mysqrt.cxx index 5b862fb..2ae60c6 100644 --- a/Tests/Tutorial/Step8/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step9/MathFunctions/mysqrt.cxx @@ -1,12 +1,9 @@ #include "MathFunctions.h" -#include "TutorialConfig.h" #include <iostream> // include the generated table #include "Table.h" -#include <cmath> - // a hack square root calculation using simple operations double mysqrt(double x) { @@ -14,20 +11,13 @@ double mysqrt(double x) return 0; } - // if we have both log and exp then use them -#if defined(HAVE_LOG) && defined(HAVE_EXP) - double result = exp(log(x) * 0.5); - std::cout << "Computing sqrt of " << x << " to be " << result << " using log" - << std::endl; -#else // use the table to help find an initial value double result = x; if (x >= 1 && x < 10) { + std::cout << "Use the table to help find an initial value " << std::endl; result = sqrtTable[static_cast<int>(x)]; } - // if we have both log and exp then use them - // do ten iterations for (int i = 0; i < 10; ++i) { if (result <= 0) { @@ -37,6 +27,6 @@ double mysqrt(double x) result = result + 0.5 * delta / result; std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; } -#endif + return result; } diff --git a/Tests/Tutorial/Complete/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step9/MathFunctions/mysqrt.h index e1c42ef..e1c42ef 100644 --- a/Tests/Tutorial/Complete/MathFunctions/mysqrt.h +++ b/Help/guide/tutorial/Step9/MathFunctions/mysqrt.h diff --git a/Help/guide/tutorial/Step9/TutorialConfig.h.in b/Help/guide/tutorial/Step9/TutorialConfig.h.in new file mode 100644 index 0000000..e23f521 --- /dev/null +++ b/Help/guide/tutorial/Step9/TutorialConfig.h.in @@ -0,0 +1,4 @@ +// the configured options and settings for Tutorial +#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ +#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ +#cmakedefine USE_MYMATH diff --git a/Help/guide/tutorial/Step9/tutorial.cxx b/Help/guide/tutorial/Step9/tutorial.cxx new file mode 100644 index 0000000..b3c6a4f --- /dev/null +++ b/Help/guide/tutorial/Step9/tutorial.cxx @@ -0,0 +1,36 @@ +// A simple program that computes the square root of a number +#include <cmath> +#include <iostream> +#include <string> + +#include "TutorialConfig.h" + +// should we include the MathFunctions header? +#ifdef USE_MYMATH +# include "MathFunctions.h" +#endif + +int main(int argc, char* argv[]) +{ + if (argc < 2) { + // report version + std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." + << Tutorial_VERSION_MINOR << std::endl; + std::cout << "Usage: " << argv[0] << " number" << std::endl; + return 1; + } + + // convert input to double + const double inputValue = std::stod(argv[1]); + + // which square root function should we use? +#ifdef USE_MYMATH + const double outputValue = mysqrt(inputValue); +#else + const double outputValue = sqrt(inputValue); +#endif + + std::cout << "The square root of " << inputValue << " is " << outputValue + << std::endl; + return 0; +} diff --git a/Help/guide/tutorial/index.rst b/Help/guide/tutorial/index.rst new file mode 100644 index 0000000..d858c25 --- /dev/null +++ b/Help/guide/tutorial/index.rst @@ -0,0 +1,899 @@ +CMake Tutorial +************** + +.. only:: html + + .. contents:: + +The CMake tutorial provides a step-by-step guide that covers common build +system issues that CMake helps address. Seeing how various topics all +work together in an example project can be very helpful. The tutorial +documentation and source code for examples can be found in the +``Help/guide/tutorial`` directory of the CMake source code tree. Each step has +its own subdirectory containing code that may be used as a starting point. The +tutorial examples are progressive so that each step provides the complete +solution for the previous step. + +A Basic Starting Point (Step 1) +=============================== + +The most basic project is an executable built from source code files. +For simple projects, a three line CMakeLists file is all that is required. +This will be the starting point for our tutorial. Create a ``CMakeLists.txt`` +file in the ``Step1`` directory that looks like: + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.10) + + # set the project name + project(Tutorial) + + # add the executable + add_executable(Tutorial tutorial.cxx) + + +Note that this example uses lower case commands in the CMakeLists file. +Upper, lower, and mixed case commands are supported by CMake. The source +code for ``tutorial.cxx`` is provided in the ``Step1`` directory and can be +used to compute the square root of a number. + +Adding a Version Number and Configured Header File +-------------------------------------------------- + +The first feature we will add is to provide our executable and project with a +version number. While we could do this exclusively in the source code, using +CMakeLists provides more flexibility. + +First, modify the CMakeLists file to set the version number. + +.. literalinclude:: Step2/CMakeLists.txt + :language: cmake + :end-before: # specify the C++ standard + +Then, configure a header file to pass the version number to the source +code: + +.. literalinclude:: Step2/CMakeLists.txt + :language: cmake + :start-after: # to the source code + :end-before: # add the executable + +Since the configured file will be written into the binary tree, we +must add that directory to the list of paths to search for include +files. Add the following lines to the end of the CMakeLists file: + +.. literalinclude:: Step2/CMakeLists.txt + :language: cmake + :start-after: # so that we will find TutorialConfig.h + +Using your favorite editor, create ``TutorialConfig.h.in`` in the source +directory with the following contents: + +.. literalinclude:: Step2/TutorialConfig.h.in + :language: cmake + +When CMake configures this header file the values for +``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will be +replaced. + +Next modify ``tutorial.cxx`` to include the configured header file, +``TutorialConfig.h``. + +Finally, let's print out the version number by updating ``tutorial.cxx`` as +follows: + +.. literalinclude:: Step2/tutorial.cxx + :language: c++ + :start-after: { + :end-before: // convert input to double + +Specify the C++ Standard +------------------------- + +Next let's add some C++11 features to our project by replacing ``atof`` with +``std::stod`` in ``tutorial.cxx``. At the same time, remove +``#include <cstdlib>``. + +.. literalinclude:: Step2/tutorial.cxx + :language: c++ + :start-after: // convert input to double + :end-before: // calculate square root + +We will need to explicitly state in the CMake code that it should use the +correct flags. The easiest way to enable support for a specific C++ standard +in CMake is by using the ``CMAKE_CXX_STANDARD`` variable. For this tutorial, +set the ``CMAKE_CXX_STANDARD`` variable in the CMakeLists file to 11 and +``CMAKE_CXX_STANDARD_REQUIRED`` to True: + +.. literalinclude:: Step2/CMakeLists.txt + :language: cmake + :end-before: # configure a header file to pass some of the CMake settings + +Build and Test +-------------- + +Run **cmake** or **cmake-gui** to configure the project and then build it +with your chosen build tool. + +For example, from the command line we could navigate to the +``Help/guide/tutorial`` directory of the CMake source code tree and run the +following commands: + +.. code-block:: console + + mkdir Step1_build + cd Step1_build + cmake ../Step1 + cmake --build . + +Navigate to the directory where Tutorial was built (likely the make directory +or a Debug or Release build configuration subdirectory) and run these commands: + +.. code-block:: console + + Tutorial 4294967296 + Tutorial 10 + Tutorial + +Adding a Library (Step 2) +========================= + +Now we will add a library to our project. This library will contain our own +implementation for computing the square root of a number. The executable can +then use this library instead of the standard square root function provided by +the compiler. + +For this tutorial we will put the library into a subdirectory +called MathFunctions. This directory already contains a header file, +``MathFunctions.h``, and a source file ``mysqrt.cxx``. The source file has one +function called ``mysqrt`` that provides similar functionality to the +compiler's ``sqrt`` function. + +Add the following one line ``CMakeLists.txt`` file to the MathFunctions +directory: + +.. literalinclude:: Step3/MathFunctions/CMakeLists.txt + :language: cmake + +To make use of the new library we will add an ``add_subdirectory`` call in the +top-level CMakeLists file so that the library will get built. We add the new +library to the executable, and add MathFunctions as an include directory so +that the ``mqsqrt.h`` header file can be found. The last few lines of the +top-level CMakeLists file should now look like: + +.. code-block:: cmake + + # add the MathFunctions library + add_subdirectory(MathFunctions) + + # add the executable + add_executable(Tutorial tutorial.cxx) + + target_link_libraries(Tutorial PUBLIC MathFunctions) + + # add the binary tree to the search path for include files + # so that we will find TutorialConfig.h + target_include_directories(Tutorial PUBLIC + "${PROJECT_BINARY_DIR}" + "${PROJECT_SOURCE_DIR}/MathFunctions" + ) + +Now let us make the MathFunctions library optional. While for the tutorial +there really isn’t any need to do so, for larger projects this is a common +occurrence. The first step is to add an option to the top-level CMakeLists +file. + +.. literalinclude:: Step3/CMakeLists.txt + :language: cmake + :start-after: # should we use our own math functions + :end-before: # add the MathFunctions library + +This option will be displayed in the CMake GUI and ccmake with a default +value of ON that can be changed by the user. This setting will be stored in +the cache so that the user does not need to set the value each time they run +CMake on a build directory. + +The next change is to make building and linking the MathFunctions library +conditional. To do this we change the end of the top-level CMakeLists file to +look like the following: + +.. literalinclude:: Step3/CMakeLists.txt + :language: cmake + :start-after: # add the MathFunctions library + +Note the use of the variable ``EXTRA_LIBS`` to collect up any optional +libraries to later be linked into the executable. The variable +``EXTRA_INCLUDES`` is used similarly for optional header files. This is a +classic approach when dealing with many optional components, we will cover +the modern approach in the next step. + +The corresponding changes to the source code are fairly straightforward. First, +in ``tutorial.cxx``, include the MathFunctions header if we need it: + +.. literalinclude:: Step3/tutorial.cxx + :language: c++ + :start-after: // should we include the MathFunctions header + :end-before: int main + +Then, in the same file, make which square root function is used dependent on +``USE_MYMATH``: + +.. literalinclude:: Step3/tutorial.cxx + :language: c++ + :start-after: // which square root function should we use? + :end-before: std::cout << "The square root of + +Since the source code now requires ``USE_MYMATH`` we can add it to +``TutorialConfig.h.in`` with the following line: + +.. literalinclude:: Step3/TutorialConfig.h.in + :language: c + :lines: 4 + +**Exercise**: Why is it important that we configure ``TutorialConfig.h.in`` +after the option for ``USE_MYMATH``? What would happen if we inverted the two? + +Run **cmake** or **cmake-gui** to configure the project and then build it +with your chosen build tool. Then run the built Tutorial executable. + +Use ccmake or the CMake GUI to update the value of ``USE_MYMATH``. Rebuild and +run the tutorial again. Which function gives better results, sqrt or mysqrt? + +Adding Usage Requirements for Library (Step 3) +============================================== + +Usage requirements allow for far better control over a library or executable's +link and include line while also giving more control over the transitive +property of targets inside CMake. The primary commands that leverage usage +requirements are: + + - ``target_compile_definitions`` + - ``target_compile_options`` + - ``target_include_directories`` + - ``target_link_libraries`` + +Let's refactor our code from `Adding a Library (Step 2)`_ to use the modern +CMake approach of usage requirements. We first state that anybody linking to +MathFunctions needs to include the current source directory, while +MathFunctions itself doesn't. So this can become an ``INTERFACE`` usage +requirement. + +Remember ``INTERFACE`` means things that consumers require but the producer +doesn't. Add the following lines to the end of ``MathFunctions/CMakeLists.txt``: + +.. literalinclude:: Step4/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # to find MathFunctions.h + +Now that we've specified usage requirements for MathFunctions we can safely +remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level +CMakeLists, here: + +.. literalinclude:: Step4/CMakeLists.txt + :language: cmake + :start-after: # add the MathFunctions library + :end-before: # add the executable + +And here: + +.. literalinclude:: Step4/CMakeLists.txt + :language: cmake + :start-after: # so that we will find TutorialConfig.h + +Once this is done, run **cmake** or **cmake-gui** to configure the project +and then build it with your chosen build tool or by using ``cmake --build .`` +from the build directory. + +Installing and Testing (Step 4) +=============================== + +Now we can start adding install rules and testing support to our project. + +Install Rules +------------- + +The install rules are fairly simple: for MathFunctions we want to install the +library and header file and for the application we want to install the +executable and configured header. + +So to the end of ``MathFunctions/CMakeLists.txt`` we add: + +.. literalinclude:: Step5/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # install rules + +And to the end of the top-level ``CMakeLists.txt`` we add: + +.. literalinclude:: Step5/CMakeLists.txt + :language: cmake + :start-after: # add the install targets + :end-before: # enable testing + +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. Run the install step by typing +``cmake --install .`` (introduced in 3.15, older versions of CMake must use +``make install``) from the command line, or build the ``INSTALL`` target from +an IDE. This will install the appropriate header files, libraries, and +executables. + +The CMake variable ``CMAKE_INSTALL_PREFIX`` is used to determine the root of +where the files will be installed. If using ``cmake --install`` a custom +installation directory can be given via ``--prefix`` argument. For +multi-configuration tools, use the ``--config`` argument to specify the +configuration. + +Verify that the installed Tutorial runs. + +Testing Support +--------------- + +Next let's test our application. At the end of the top-level CMakeLists file we +can enable testing and then add a number of basic tests to verify that the +application is working correctly. + +.. literalinclude:: Step5/CMakeLists.txt + :language: cmake + :start-after: # enable testing + +The first test simply verifies that the application runs, does not segfault or +otherwise crash, and has a zero return value. This is the basic form of a CTest +test. + +The next test makes use of the ``PASS_REGULAR_EXPRESSION`` test property to +verify that the output of the test contains certain strings. In this case, +verifying that the the usage message is printed when an incorrect number of +arguments are provided. + +Lastly, we have a function called ``do_test`` that runs the application and +verifies that the computed square root is correct for given input. For each +invocation of ``do_test``, another test is added to the project with a name, +input, and expected results based on the passed arguments. + +Rebuild the application and then cd to the binary directory and run +``ctest -N`` and ``ctest -VV``. For multi-config generators (e.g. Visual +Studio), the configuration type must be specified. To run tests in Debug mode, +for example, use ``ctest -C Debug -VV`` from the build directory (not the +Debug subdirectory!). Alternatively, build the ``RUN_TESTS`` target from the +IDE. + +Adding System Introspection (Step 5) +==================================== + +Let us consider adding some code to our project that depends on features the +target platform may not have. For this example, we will add some code that +depends on whether or not the target platform has the ``log`` and ``exp`` +functions. Of course almost every platform has these functions but for this +tutorial assume that they are not common. + +If the platform has ``log`` and ``exp`` then we will use them to compute the +square root in the ``mysqrt`` function. We first test for the availability of +these functions using the ``CheckSymbolExists.cmake`` macro in the top-level +CMakeLists. We're going to use the new defines in ``TutorialConfig.h.in``, +so be sure to set them before that file is configured. + +.. literalinclude:: Step6/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # does this system provide the log and exp functions? + :end-before: if(HAVE_LOG AND HAVE_EXP) + +Now let's add these defines to ``TutorialConfig.h.in`` so that we can use them +from ``mysqrt.cxx``: + +.. code-block:: console + + // does the platform provide exp and log functions? + #cmakedefine HAVE_LOG + #cmakedefine HAVE_EXP + +Modify ``mysqrt.cxx`` to include cmath. Next, in that same file in the +``mysqrt`` function we can provide an alternate implementation based on +``log`` and ``exp`` if they are available on the system using the following +code (don't forget the ``#endif`` before returning the result!): + +.. literalinclude:: Step6/MathFunctions/mysqrt.cxx + :language: c++ + :start-after: // if we have both log and exp then use them + :end-before: // do ten iterations + +Run **cmake** or **cmake-gui** to configure the project and then build it +with your chosen build tool and run the Tutorial executable. + +You will notice that we're not using ``log`` and ``exp``, even if we think they +should be available. We should realize quickly that we have forgotten to include +``TutorialConfig.h`` in ``mysqrt.cxx``. + +We will also need to update MathFunctions/CMakeLists so ``mysqrt.cxx`` knows +where this file is located: + + +.. code-block:: cmake + + target_include_directories(MathFunctions + INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_BINARY_DIR} + ) + +After making this update, go ahead and build the project again and run the built +Tutorial executable. If ``log`` and ``exp`` are still not being used, open the +generated ``TutorialConfig.h`` file from the build directory. Maybe they aren't +available on the current system? + +Which function gives better results now, sqrt or mysqrt? + +Specify Compile Definition +-------------------------- + +Is there a better place for us to save the ``HAVE_LOG`` and ``HAVE_EXP`` values +other than in ``TutorialConfig.h``? Let's try to use +``target_compile_definitions``. + +First, remove the defines from ``TutorialConfig.h.in``. We no longer need to +include ``TutorialConfig.h`` from ``mysqrt.cxx`` or the extra include in +MathFunctions/CMakeLists. + +Next, we can move the check for ``HAVE_LOG`` and ``HAVE_EXP`` to +MathFunctions/CMakeLists and then add specify those values as ``PRIVATE`` +compile definitions. + +.. literalinclude:: Step6/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # does this system provide the log and exp functions? + :end-before: # install rules + +After making these updates, go ahead and build the project again. Run the +built Tutorial executable and verify that the results are same as earlier in +this step. + +Adding a Custom Command and Generated File (Step 6) +=================================================== + +Suppose, for the purpose of this tutorial, we decide that we never want to use +the platform ``log`` and ``exp`` functions and instead would like to +generate a table of precomputed values to use in the ``mysqrt`` function. +In this section, we will create the table as part of the build process, +and then compile that table into our application. + +First, let's remove the check for the ``log`` and ``exp`` functions in +MathFunctions/CMakeLists. Then remove the check for ``HAVE_LOG`` and +``HAVE_EXP`` from ``mysqrt.cxx``. At the same time, we can remove +:code:`#include <cmath>`. + +In the MathFunctions subdirectory, a new source file named ``MakeTable.cxx`` +has been provided to generate the table. + +After reviewing the file, we can see that the table is produced as valid C++ +code and that the output filename is passed in as an argument. + +The next step is to add the appropriate commands to MathFunctions CMakeLists +file to build the MakeTable executable and then run it as part of the build +process. A few commands are needed to accomplish this. + +First, at the top of MathFunctions/CMakeLists, the executable for ``MakeTable`` +is added as any other executable would be added. + +.. literalinclude:: Step7/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # first we add the executable that generates the table + :end-before: # add the command to generate the source code + +Then we add a custom command that specifies how to produce ``Table.h`` +by running MakeTable. + +.. literalinclude:: Step7/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # add the command to generate the source code + :end-before: # add the main library + +Next we have to let CMake know that ``mysqrt.cxx`` depends on the generated +file ``Table.h``. This is done by adding the generated ``Table.h`` to the list +of sources for the library MathFunctions. + +.. literalinclude:: Step7/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # add the main library + :end-before: # state that anybody linking + +We also have to add the current binary directory to the list of include +directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``. + +.. literalinclude:: Step7/MathFunctions/CMakeLists.txt + :start-after: # state that we depend on our bin + :end-before: # install rules + +Now let's use the generated table. First, modify ``mysqrt.cxx`` to include +``Table.h``. Next, we can rewrite the mysqrt function to use the table: + +.. literalinclude:: Step7/MathFunctions/mysqrt.cxx + :language: c++ + :start-after: // a hack square root calculation using simple operations + +Run **cmake** or **cmake-gui** to configure the project and then build it +with your chosen build tool. + +When this project is built it will first build the ``MakeTable`` executable. +It will then run ``MakeTable`` to produce ``Table.h``. Finally, it will +compile ``mysqrt.cxx`` which includes ``Table.h`` to produce the MathFunctions +library. + +Run the Tutorial executable and verify that it is using the table. + +Building an Installer (Step 7) +============================== + +Next suppose that we want to distribute our project to other people so that +they can use it. We want to provide both binary and source distributions on a +variety of platforms. This is a little different from the install we did +previously in `Installing and Testing (Step 4)`_ , where we were +installing the binaries that we had built from the source code. In this +example we will be building installation packages that support binary +installations and package management features. To accomplish this we will use +CPack to create platform specific installers. Specifically we need to add +a few lines to the bottom of our top-level ``CMakeLists.txt`` file. + +.. literalinclude:: Step8/CMakeLists.txt + :language: cmake + :start-after: # setup installer + +That is all there is to it. We start by including +``InstallRequiredSystemLibraries``. This module will include any runtime +libraries that are needed by the project for the current platform. Next we +set some CPack variables to where we have stored the license and version +information for this project. The version information was set earlier in this +tutorial and the ``license.txt`` has been included in the top-level source +directory for this step. + +Finally we include the CPack module which will use these variables and some +other properties of the current system to setup an installer. + +The next step is to build the project in the usual manner and then run +CPack on it. To build a binary distribution, from the binary directory run: + +.. code-block:: console + + cpack + +To specify the generator, use the ``-G`` option. For multi-config builds, use +``-C`` to specify the configuration. For example: + +.. code-block:: console + + cpack -G ZIP -C Debug + +To create a source distribution you would type: + +.. code-block:: console + + cpack --config CPackSourceConfig.cmake + +Alternatively, run ``make package`` or right click the ``Package`` target and +``Build Project`` from an IDE. + +Run the installer found in the binary directory. Then run the +installed executable and verify that it works. + +Adding Support for a Dashboard (Step 8) +======================================= + +Adding support for submitting our test results to a dashboard is very easy. We +already defined a number of tests for our project in `Testing Support`_. Now we +just have to run those tests and submit them to a dashboard. To include support +for dashboards we include the CTest module in our top-level ``CMakeLists.txt``. + +Replace: + +.. code-block:: cmake + + # enable testing + enable_testing() + +With: + +.. code-block:: cmake + + # enable dashboard scripting + include(CTest) + +The CTest module will automatically call ``enable_testing()``, so +we can remove it from our CMake files. + +We will also need to create a ``CTestConfig.cmake`` file in the top-level +directory where we can specify the name of the project and where to submit the +dashboard. + +.. literalinclude:: Step9/CTestConfig.cmake + :language: cmake + +CTest will read in this file when it runs. To create a simple dashboard you can +run **cmake** or **cmake-gui** to configure the project, but do not build it +yet. Instead, change directory to the binary tree, and then run:: + + ctest [-VV] –D Experimental + +Remember, for multi-config generators (e.g. Visual Studio), the configuration +type must be specified:: + + ctest [-VV] -C Debug –D Experimental + +Or, from an IDE, build the ``Experimental`` target. + +Ctest will build and test the project and submit the results to the Kitware +public dashboard. The results of your dashboard will be uploaded to Kitware's +public dashboard here: https://my.cdash.org/index.php?project=CMakeTutorial. + +Mixing Static and Shared (Step 9) +================================= + +In this section we will show how by using the ``BUILD_SHARED_LIBS`` variable +we can control the default behavior of ``add_library``, and allow control +over how libraries without an explicit type (STATIC/SHARED/MODULE/OBJECT) are +built. + +To accomplish this we need to add ``BUILD_SHARED_LIBS`` to the top-level +``CMakeLists.txt``. We use the ``option`` command as it allows users to +optionally select if the value should be On or Off. + +Next we are going to refactor MathFunctions to become a real library that +encapsulates using ``mysqrt`` or ``sqrt``, instead of requiring the calling +code to do this logic. This will also mean that ``USE_MYMATH`` will not control +building MathFuctions, but instead will control the behavior of this library. + +The first step is to update the starting section of the top-level +``CMakeLists.txt`` to look like: + +.. literalinclude:: Step10/CMakeLists.txt + :language: cmake + :end-before: # add the binary tree + +Now that we have made MathFunctions always be used, we will need to update +the logic of that library. So, in ``MathFunctions/CMakeLists.txt`` we need to +create a SqrtLibrary that will conditionally be built when ``USE_MYMATH`` is +enabled. Now, since this is a tutorial, we are going to explicitly require +that SqrtLibrary is built statically. + +The end result is that ``MathFunctions/CMakeLists.txt`` should look like: + +.. literalinclude:: Step10/MathFunctions/CMakeLists.txt + :language: cmake + :lines: 1-36,42- + +Next, update ``MathFunctions/mysqrt.cxx`` to use the ``mathfunctions`` and +``detail`` namespaces: + +.. literalinclude:: Step10/MathFunctions/mysqrt.cxx + :language: c++ + +We also need to make some changes in ``tutorial.cxx``, so that it no longer +uses ``USE_MYMATH``: + +#. Always include ``MathFunctions.h`` +#. Always use ``mathfunctions::sqrt`` +#. Don't include cmath + +Finally, update ``MathFunctions/MathFunctions.h`` to use dll export defines: + +.. literalinclude:: Step10/MathFunctions/MathFunctions.h + :language: c++ + +At this point, if you build everything, you will notice that linking fails +as we are combining a static library without position enabled code with a +library that has position enabled code. The solution to this is to explicitly +set the ``POSITION_INDEPENDENT_CODE`` target property of SqrtLibrary to be +True no matter the build type. + +.. literalinclude:: Step10/MathFunctions/CMakeLists.txt + :language: cmake + :lines: 37-42 + +**Exercise**: We modified ``MathFunctions.h`` to use dll export defines. +Using CMake documentation can you find a helper module to simplify this? + + +Adding Generator Expressions (Step 10) +====================================== + +Generator expressions are evaluated during build system generation to produce +information specific to each build configuration. + +Generator expressions are allowed in the context of many target properties, +such as ``LINK_LIBRARIES``, ``INCLUDE_DIRECTORIES``, ``COMPILE_DEFINITIONS`` +and others. They may also be used when using commands to populate those +properties, such as ``target_link_libraries()``, +``target_include_directories()``, +``target_compile_definitions()`` and others. + +Generator expressions may be used to enable conditional linking, conditional +definitions used when compiling, conditional include directories and more. +The conditions may be based on the build configuration, target properties, +platform information or any other queryable information. + +There are different types of generator expressions including Logical, +Informational, and Output expressions. + +Logical expressions are used to create conditional output. The basic +expressions are the 0 and 1 expressions. A ``$<0:...>`` results in the empty +string, and ``<1:...>`` results in the content of "...". They can also be +nested. + +A common usage of generator expressions is to conditionally add compiler +flags, such as those as language levels or warnings. A nice pattern is +to associate this information to an ``INTERFACE`` target allowing this +information to propagate. Lets start by constructing an ``INTERFACE`` +target and specifying the required C++ standard level of ``11`` instead +of using ``CMAKE_CXX_STANDARD``. + +So the following code: + +.. literalinclude:: Step10/CMakeLists.txt + :language: cmake + :start-after: project(Tutorial VERSION 1.0) + :end-before: # control where the static and shared libraries are built so that on windows + +Would be replaced with: + +.. literalinclude:: Step11/CMakeLists.txt + :language: cmake + :start-after: project(Tutorial VERSION 1.0) + :end-before: # add compiler warning flags just when building this project via + + +Next we add the desired compiler warning flags that we want for our +project. As warning flags vary based on the compiler we use +the ``COMPILE_LANG_AND_ID`` generator expression to control which +flags to apply given a language and a set of compiler ids as seen +below: + +.. literalinclude:: Step11/CMakeLists.txt + :language: cmake + :start-after: # the BUILD_INTERFACE genex + :end-before: # control where the static and shared libraries are built so that on windows + +Looking at this we see that the warning flags are encapsulated inside a +``BUILD_INTERFACE`` condition. This is done so that consumers of our installed +project will not inherit our warning flags. + + +**Exercise**: Modify ``MathFunctions/CMakeLists.txt`` so that +all targets have a ``target_link_libraries()`` call to ``tutorial_compiler_flags``. + + +Adding Export Configuration (Step 11) +===================================== + +During `Installing and Testing (Step 4)`_ of the tutorial we added the ability +for CMake to install the library and headers of the project. During +`Building an Installer (Step 7)`_ we added the ability to package up this +information so it could be distributed to other people. + +The next step is to add the necessary information so that other CMake projects +can use our project, be it from a build directory, a local install or when +packaged. + +The first step is to update our ``install(TARGETS)`` commands to not only +specify a ``DESTINATION`` but also an ``EXPORT``. The ``EXPORT`` keyword +generates and installs a CMake file containing code to import all targets +listed in the install command from the installation tree. So let's go ahead +and explicitly ``EXPORT`` the MathFunctions library by updating the +``install`` command in ``MathFunctions/CMakeLists.txt`` to look like: + +.. literalinclude:: Complete/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # install rules + +Now that we have MathFunctions being exported, we also need to explicitly +install the generated ``MathFunctionsTargets.cmake`` file. This is done by +adding the following to the bottom of the top-level ``CMakeLists.txt``: + +.. literalinclude:: Complete/CMakeLists.txt + :language: cmake + :start-after: # install the configuration targets + :end-before: include(CMakePackageConfigHelpers) + +At this point you should try and run CMake. If everything is setup properly +you will see that CMake will generate an error that looks like: + +.. code-block:: console + + Target "MathFunctions" INTERFACE_INCLUDE_DIRECTORIES property contains + path: + + "/Users/robert/Documents/CMakeClass/Tutorial/Step11/MathFunctions" + + which is prefixed in the source directory. + +What CMake is trying to say is that during generating the export information +it will export a path that is intrinsically tied to the current machine and +will not be valid on other machines. The solution to this is to update the +MathFunctions ``target_include_directories`` to understand that it needs +different ``INTERFACE`` locations when being used from within the build +directory and from an install / package. This means converting the +``target_include_directories`` call for MathFunctions to look like: + +.. literalinclude:: Complete/MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # to find MathFunctions.h, while we don't. + :end-before: # should we use our own math functions + +Once this has been updated, we can re-run CMake and see verify that it doesn't +warn anymore. + +At this point, we have CMake properly packaging the target information that is +required but we will still need to generate a ``MathFunctionsConfig.cmake`` so +that the CMake ``find_package command`` can find our project. So let's go +ahead and add a new file to the top-level of the project called +``Config.cmake.in`` with the following contents: + +.. literalinclude:: Complete/Config.cmake.in + +Then, to properly configure and install that file, add the following to the +bottom of the top-level CMakeLists: + +.. literalinclude:: Complete/CMakeLists.txt + :language: cmake + :start-after: # install the configuration targets + :end-before: # generate the export + +At this point, we have generated a relocatable CMake Configuration for our +project that can be used after the project has been installed or packaged. If +we want our project to also be used from a build directory we only have to add +the following to the bottom of the top level CMakeLists: + +.. literalinclude:: Complete/CMakeLists.txt + :language: cmake + :start-after: # needs to be after the install(TARGETS ) command + +With this export call we now generate a ``Targets.cmake``, allowing the +configured ``MathFunctionsConfig.cmake`` in the build directory to be used by +other projects, without needing it to be installed. + +Import a CMake Project (Consumer) +================================= + +This examples shows how a project can find other CMake packages that +generate ``Config.cmake`` files. + +It also shows how to state a project's external dependencies when generating +a ``Config.cmake``. + +Packaging Debug and Release (MultiPackage) +========================================== + +By default CMake is model is that a build directory only contains a single +configuration, be it Debug, Release, MinSizeRel, or RelWithDebInfo. + +But it is possible to setup CPack to bundle multiple build directories at the +same time to build a package that contains multiple configurations of the +same project. + +First we need to ahead and construct a directory called ``multi_config`` this +will contain all the builds that we want to package together. + +Second create a ``debug`` and ``release`` directory underneath +``multi_config``. At the end you should have a layout that looks like: + +─ multi_config + ├── debug + └── release + +Now we need to setup debug and release builds, which would roughly entail +the following: + +.. code-block:: console + + cd debug + cmake -DCMAKE_BUILD_TYPE=Debug ../../MultiPackage/ + cmake --build . + cd ../release + cmake -DCMAKE_BUILD_TYPE=Release ../../MultiPackage/ + cmake --build . + cd .. + + +Now that both the debug and release builds are complete we can now use +the custom MultiCPackConfig to package both builds into a single release. + +.. code-block:: console + + cpack --config ../../MultiPackage/MultiCPackConfig.cmake diff --git a/Help/index.rst b/Help/index.rst index a948939..cc6cee6 100644 --- a/Help/index.rst +++ b/Help/index.rst @@ -44,6 +44,16 @@ Reference Manuals /manual/cmake-variables.7 /manual/cpack-generators.7 +.. only:: not man + + Guides + ###### + + .. toctree:: + :maxdepth: 1 + + /guide/tutorial/index + .. only:: html or text Release Notes diff --git a/Help/manual/cmake-buildsystem.7.rst b/Help/manual/cmake-buildsystem.7.rst index 8cd6e68..d8142a2 100644 --- a/Help/manual/cmake-buildsystem.7.rst +++ b/Help/manual/cmake-buildsystem.7.rst @@ -811,6 +811,10 @@ An *archive* output artifact of a buildsystem target may be: executable target created by the :command:`add_executable` command when its :prop_tgt:`ENABLE_EXPORTS` target property is set. +* On AIX: the linker import file (e.g. ``.imp``) of an executable target + created by the :command:`add_executable` command when its + :prop_tgt:`ENABLE_EXPORTS` target property is set. + The :prop_tgt:`ARCHIVE_OUTPUT_DIRECTORY` and :prop_tgt:`ARCHIVE_OUTPUT_NAME` target properties may be used to control archive output artifact locations and names in the build tree. diff --git a/Help/manual/cmake-packages.7.rst b/Help/manual/cmake-packages.7.rst index f5aa42d..4b2934a 100644 --- a/Help/manual/cmake-packages.7.rst +++ b/Help/manual/cmake-packages.7.rst @@ -654,8 +654,13 @@ allows one to disable them using the following variables: :command:`export(PACKAGE)` populates the user package registry unless the :variable:`CMAKE_EXPORT_NO_PACKAGE_REGISTRY` variable explicitly disables it. -* :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY` disables the - User Package Registry in all the :command:`find_package` calls. +* :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY` disables the + User Package Registry in all the :command:`find_package` calls when + set to ``FALSE``. +* Deprecated :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY` disables the + User Package Registry in all the :command:`find_package` calls when set + to ``TRUE``. This variable is ignored when + :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY` has been set. * :variable:`CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY` disables the System Package Registry in all the :command:`find_package` calls. diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 1d023cb..44ea1a8 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -51,6 +51,16 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used to determine whether to report an error on use of deprecated macros or functions. +Policies Introduced by CMake 3.16 +================================= + +.. toctree:: + :maxdepth: 1 + + CMP0097: ExternalProject_Add with GIT_SUBMODULES "" initializes no submodules. </policy/CMP0097> + CMP0096: project() preserves leading zeros in version components. </policy/CMP0096> + CMP0095: RPATH entries are properly escaped in the intermediary CMake install script. </policy/CMP0095> + Policies Introduced by CMake 3.15 ================================= diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 77b1ae8..62d23c7 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -228,6 +228,7 @@ Properties on Targets /prop_tgt/IMPORT_SUFFIX /prop_tgt/INCLUDE_DIRECTORIES /prop_tgt/INSTALL_NAME_DIR + /prop_tgt/INSTALL_REMOVE_ENVIRONMENT_RPATH /prop_tgt/INSTALL_RPATH /prop_tgt/INSTALL_RPATH_USE_LINK_PATH /prop_tgt/INTERFACE_AUTOUIC_OPTIONS @@ -331,6 +332,7 @@ Properties on Targets /prop_tgt/VS_DOTNET_REFERENCES /prop_tgt/VS_DOTNET_REFERENCES_COPY_LOCAL /prop_tgt/VS_DOTNET_TARGET_FRAMEWORK_VERSION + /prop_tgt/VS_DPI_AWARE /prop_tgt/VS_GLOBAL_KEYWORD /prop_tgt/VS_GLOBAL_PROJECT_TYPES /prop_tgt/VS_GLOBAL_ROOTNAMESPACE @@ -406,6 +408,7 @@ Properties on Tests /prop_test/REQUIRED_FILES /prop_test/RESOURCE_LOCK /prop_test/RUN_SERIAL + /prop_test/SKIP_REGULAR_EXPRESSION /prop_test/SKIP_RETURN_CODE /prop_test/TIMEOUT /prop_test/TIMEOUT_AFTER_MATCH diff --git a/Help/manual/cmake-toolchains.7.rst b/Help/manual/cmake-toolchains.7.rst index 7435d9a..f233d08 100644 --- a/Help/manual/cmake-toolchains.7.rst +++ b/Help/manual/cmake-toolchains.7.rst @@ -399,8 +399,10 @@ Configure use of an Android NDK with the following variables: be false unless using a NDK that does not provide unified headers. :variable:`CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION` - Set to the version of the NDK toolchain to be selected as the compiler. - If not specified, the default will be the latest available GCC toolchain. + On NDK r19 or above, this variable must be unset or set to ``clang``. + On NDK r18 or below, set this to the version of the NDK toolchain to + be selected as the compiler. If not specified, the default will be + the latest available GCC toolchain. :variable:`CMAKE_ANDROID_STL_TYPE` Set to specify which C++ standard library to use. If not specified, diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index e3c2f9f..9ad1195 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 @@ -158,6 +159,7 @@ Variables that Change Behavior /variable/CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES /variable/CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT /variable/CMAKE_ECLIPSE_MAKE_ARGUMENTS + /variable/CMAKE_ECLIPSE_RESOURCE_ENCODING /variable/CMAKE_ECLIPSE_VERSION /variable/CMAKE_ERROR_DEPRECATED /variable/CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION @@ -181,6 +183,12 @@ Variables that Change Behavior /variable/CMAKE_FIND_ROOT_PATH_MODE_LIBRARY /variable/CMAKE_FIND_ROOT_PATH_MODE_PACKAGE /variable/CMAKE_FIND_ROOT_PATH_MODE_PROGRAM + /variable/CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH + /variable/CMAKE_FIND_USE_CMAKE_PATH + /variable/CMAKE_FIND_USE_CMAKE_SYSTEM_PATH + /variable/CMAKE_FIND_USE_PACKAGE_REGISTRY + /variable/CMAKE_FIND_USE_PACKAGE_ROOT_PATH + /variable/CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH /variable/CMAKE_FRAMEWORK_PATH /variable/CMAKE_IGNORE_PATH /variable/CMAKE_INCLUDE_DIRECTORIES_BEFORE @@ -345,6 +353,7 @@ Variables that Control the Build /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG /variable/CMAKE_CONFIG_POSTFIX /variable/CMAKE_CUDA_SEPARABLE_COMPILATION + /variable/CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS /variable/CMAKE_DEBUG_POSTFIX /variable/CMAKE_ENABLE_EXPORTS /variable/CMAKE_EXE_LINKER_FLAGS @@ -364,6 +373,7 @@ Variables that Control the Build /variable/CMAKE_INCLUDE_CURRENT_DIR /variable/CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE /variable/CMAKE_INSTALL_NAME_DIR + /variable/CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH /variable/CMAKE_INSTALL_RPATH /variable/CMAKE_INSTALL_RPATH_USE_LINK_PATH /variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION @@ -374,6 +384,7 @@ Variables that Control the Build /variable/CMAKE_LANG_CPPCHECK /variable/CMAKE_LANG_CPPLINT /variable/CMAKE_LANG_INCLUDE_WHAT_YOU_USE + /variable/CMAKE_LANG_LINK_LIBRARY_FLAG /variable/CMAKE_LANG_VISIBILITY_PRESET /variable/CMAKE_LIBRARY_OUTPUT_DIRECTORY /variable/CMAKE_LIBRARY_OUTPUT_DIRECTORY_CONFIG @@ -602,7 +613,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/manual/cmake.1.rst b/Help/manual/cmake.1.rst index 7b5399d..26ef904 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -238,6 +238,9 @@ Options Multiple options are allowed. +``--trace-redirect=<file>`` + Put cmake in trace mode and redirect trace output to a file instead of stderr. + ``--warn-uninitialized`` Warn about uninitialized values. @@ -604,6 +607,12 @@ Available commands are: .. note:: Path to where ``<new>`` symbolic link will be created has to exist beforehand. +``true`` + Do nothing, with an exit code of 0. + +``false`` + Do nothing, with an exit code of 1. + Windows-specific Command-Line Tools ----------------------------------- diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index 5773176..9d93bb8 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -443,7 +443,8 @@ this mode include: Specify the name of the project to build. ``--build-makeprogram`` - Override the make program chosen by CTest with a given one. + Specify the explicit make program to be used by CMake when configuring and + building the project. Only applicable for Make and Ninja based generators. ``--build-noclean`` Skip the make clean step. @@ -481,14 +482,17 @@ a `CDash`_ server. The command-line signature used to submit to `CDash`_ is:: Options for Dashboard Client include: -``--track <track>`` - Specify the track to submit dashboard to +``--group <group>`` + Specify what group you'd like to submit results to - Submit dashboard to specified track instead of default one. By + Submit dashboard to specified group instead of default one. By default, the dashboard is submitted to Nightly, Experimental, or - Continuous track, but by specifying this option, the track can be + Continuous group, but by specifying this option, the group can be arbitrary. + This replaces the deprecated option ``--track``. + Despite the name change its behavior is unchanged. + ``-A <file>, --add-notes <file>`` Add a notes file with submission. diff --git a/Help/policy/CMP0095.rst b/Help/policy/CMP0095.rst new file mode 100644 index 0000000..4c56a05 --- /dev/null +++ b/Help/policy/CMP0095.rst @@ -0,0 +1,30 @@ +CMP0095 +------- + +``RPATH`` entries are properly escaped in the intermediary CMake install script. + +In CMake 3.15 and earlier, ``RPATH`` entries set via +:variable:`CMAKE_INSTALL_RPATH` or via :prop_tgt:`INSTALL_RPATH` have not been +escaped before being inserted into the ``cmake_install.cmake`` script. Dynamic +linkers on ELF-based systems (e.g. Linux and FreeBSD) allow certain keywords in +``RPATH`` entries, such as ``${ORIGIN}`` (More details are available in the +``ld.so`` man pages on those systems). The syntax of these keywords can match +CMake's variable syntax. In order to not be substituted (usually to an empty +string) already by the intermediary ``cmake_install.cmake`` script, the user had +to double-escape such ``RPATH`` keywords, e.g. +``set(CMAKE_INSTALL_RPATH "\\\${ORIGIN}/../lib")``. Since the intermediary +``cmake_install.cmake`` script is an implementation detail of CMake, CMake 3.16 +and later will make sure ``RPATH`` entries are inserted literally by escaping +any coincidental CMake syntax. + +The ``OLD`` behavior of this policy is to not escape ``RPATH`` entries in the +intermediary ``cmake_install.cmake`` script. The ``NEW`` behavior is to properly +escape coincidental CMake syntax in ``RPATH`` entries when generating the +intermediary ``cmake_install.cmake`` script. + +This policy was introduced in CMake version 3.16. CMake version |release| warns +when the policy is not set and detected usage of CMake-like syntax and uses +``OLD`` behavior. Use the :command:`cmake_policy` command to set it to ``OLD`` +or ``NEW`` explicitly. + +.. include:: DEPRECATED.txt diff --git a/Help/policy/CMP0096.rst b/Help/policy/CMP0096.rst new file mode 100644 index 0000000..8eaf0f9 --- /dev/null +++ b/Help/policy/CMP0096.rst @@ -0,0 +1,25 @@ +CMP0096 +------- + +The :command:`project` command preserves leading zeros in version components. + +When a ``VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]`` argument is given +to the :command:`project` command, it stores the version string in the +``PROJECT_VERSION`` variable and stores individual integer version components +in ``PROJECT_VERSION_{MAJOR,MINOR,PATCH,TWEAK}`` variables (see policy +:policy:`CMP0048`). CMake 3.15 and below dropped leading zeros from each +component. CMake 3.16 and higher prefer to preserve leading zeros. This +policy provides compatibility for projects that have not been updated to +expect the new behavior. + +The ``OLD`` behavior of this policy drops leading zeros in all components, +e.g. such that version ``1.07.06`` becomes ``1.7.6``. The ``NEW`` behavior +of this policy preserves the leading zeros in all components, such that +version ``1.07.06`` remains unchanged. + +This policy was introduced in CMake version 3.16. Unlike many policies, CMake +version |release| does *not* warn when this policy is not set and simply uses +the ``OLD`` behavior. Use the :command:`cmake_policy` command to set it to +``OLD`` or ``NEW`` explicitly. + +.. include:: DEPRECATED.txt diff --git a/Help/policy/CMP0097.rst b/Help/policy/CMP0097.rst new file mode 100644 index 0000000..8a5ff88 --- /dev/null +++ b/Help/policy/CMP0097.rst @@ -0,0 +1,23 @@ +CMP0097 +------- + +:command:`ExternalProject_Add` with ``GIT_SUBMODULES ""`` initializes no +submodules. + +The module provides a ``GIT_SUBMODULES`` option which controls what submodules +to initialize and update. Starting with CMake 3.16, explicitly setting +``GIT_SUBMODULES`` to an empty string means no submodules will be initialized +or updated. + +This policy provides compatibility for projects that have not been updated +to expect the new behavior. + +The ``OLD`` behavior for this policy is for ``GIT_SUBMODULES`` when set to +an empty string to initialize and update all git submodules. +The ``New`` behavior for this policy is for ``GIT_SUBMODULES`` when set to +an empty string to initialize and update no git submodules. + +This policy was introduced in CMake version 3.16. Use the +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. +Unlike most policies, CMake version |release| does *not* warn +when this policy is not set and simply uses ``OLD`` behavior. diff --git a/Help/prop_test/SKIP_REGULAR_EXPRESSION.rst b/Help/prop_test/SKIP_REGULAR_EXPRESSION.rst new file mode 100644 index 0000000..2c6d980 --- /dev/null +++ b/Help/prop_test/SKIP_REGULAR_EXPRESSION.rst @@ -0,0 +1,17 @@ +SKIP_REGULAR_EXPRESSION +----------------------- + +If the output matches this regular expression the test will be marked as skipped. + +If set, if the output matches one of specified regular expressions, +the test will be marked as skipped. Example: + +.. code-block:: cmake + + set_property(TEST mytest PROPERTY + SKIP_REGULAR_EXPRESSION "[^a-z]Skip" "SKIP" "Skipped" + ) + +``SKIP_REGULAR_EXPRESSION`` expects a list of regular expressions. + +See also the :prop_test:`SKIP_RETURN_CODE` property. diff --git a/Help/prop_test/SKIP_RETURN_CODE.rst b/Help/prop_test/SKIP_RETURN_CODE.rst index a05fbf3..23c4c62 100644 --- a/Help/prop_test/SKIP_RETURN_CODE.rst +++ b/Help/prop_test/SKIP_RETURN_CODE.rst @@ -6,4 +6,7 @@ Return code to mark a test as skipped. Sometimes only a test itself can determine if all requirements for the test are met. If such a situation should not be considered a hard failure a return code of the process can be specified that will mark the test as -``Not Run`` if it is encountered. +``Not Run`` if it is encountered. Valid values are in the range of +0 to 255, inclusive. + +See also the :prop_test:`SKIP_REGULAR_EXPRESSION` property. diff --git a/Help/prop_tgt/BUILD_RPATH.rst b/Help/prop_tgt/BUILD_RPATH.rst index 13c9c1d..d978b94 100644 --- a/Help/prop_tgt/BUILD_RPATH.rst +++ b/Help/prop_tgt/BUILD_RPATH.rst @@ -8,3 +8,6 @@ tree. See also the :prop_tgt:`INSTALL_RPATH` target property. This property is initialized by the value of the variable :variable:`CMAKE_BUILD_RPATH` if it is set when a target is created. + +This property supports +:manual:`generator expressions <cmake-generator-expressions(7)>`. diff --git a/Help/prop_tgt/CUDA_RESOLVE_DEVICE_SYMBOLS.rst b/Help/prop_tgt/CUDA_RESOLVE_DEVICE_SYMBOLS.rst index ef74ae2..dae960f 100644 --- a/Help/prop_tgt/CUDA_RESOLVE_DEVICE_SYMBOLS.rst +++ b/Help/prop_tgt/CUDA_RESOLVE_DEVICE_SYMBOLS.rst @@ -1,12 +1,16 @@ CUDA_RESOLVE_DEVICE_SYMBOLS --------------------------- -CUDA only: Enables device linking for the specific library target - -If set this will enable device linking on the library target. Normally -device linking is deferred until a shared library or executable is generated, -allowing for multiple static libraries to resolve device symbols at the same -time when they are used by a shared library or executable. +CUDA only: Enables device linking for the specific library target where +required. + +If set, this will tell the required compilers to enable device linking +on the library target. Device linking is an additional link step +required by some CUDA compilers when :prop_tgt:`CUDA_SEPARABLE_COMPILATION` is +enabled. Normally device linking is deferred until a shared library or +executable is generated, allowing for multiple static libraries to resolve +device symbols at the same time when they are used by a shared library or +executable. By default static library targets have this property is disabled, while shared, module, and executable targets have this property enabled. diff --git a/Help/prop_tgt/ENABLE_EXPORTS.rst b/Help/prop_tgt/ENABLE_EXPORTS.rst index 581c2b9..0b1064a 100644 --- a/Help/prop_tgt/ENABLE_EXPORTS.rst +++ b/Help/prop_tgt/ENABLE_EXPORTS.rst @@ -7,16 +7,25 @@ Normally an executable does not export any symbols because it is the final program. It is possible for an executable to export symbols to be used by loadable modules. When this property is set to true CMake will allow other targets to "link" to the executable with the -:command:`TARGET_LINK_LIBRARIES` command. On all platforms a target-level +:command:`target_link_libraries` command. On all platforms a target-level dependency on the executable is created for targets that link to it. -For DLL platforms an import library will be created for the exported -symbols and then used for linking. All Windows-based systems -including Cygwin are DLL platforms. For non-DLL platforms that -require all symbols to be resolved at link time, such as macOS, the -module will "link" to the executable using a flag like -``-bundle_loader``. For other non-DLL platforms the link rule is simply -ignored since the dynamic loader will automatically bind symbols when -the module is loaded. +Handling of the executable on the link lines of the loadable modules +varies by platform: + +* On Windows-based systems (including Cygwin) an "import library" is + created along with the executable to list the exported symbols. + Loadable modules link to the import library to get the symbols. + +* On macOS, loadable modules link to the executable itself using the + ``-bundle_loader`` flag. + +* On AIX, a linker "import file" is created along with the executable + to list the exported symbols for import when linking other targets. + Loadable modules link to the import file to get the symbols. + +* On other platforms, loadable modules are simply linked without + referencing the executable since the dynamic loader will + automatically bind symbols when the module is loaded. This property is initialized by the value of the variable :variable:`CMAKE_ENABLE_EXPORTS` if it is set when a target is created. diff --git a/Help/prop_tgt/IMPORTED_IMPLIB.rst b/Help/prop_tgt/IMPORTED_IMPLIB.rst index 77fb552..c8b6fde 100644 --- a/Help/prop_tgt/IMPORTED_IMPLIB.rst +++ b/Help/prop_tgt/IMPORTED_IMPLIB.rst @@ -3,5 +3,7 @@ IMPORTED_IMPLIB Full path to the import library for an ``IMPORTED`` target. -Set this to the location of the ``.lib`` part of a Windows DLL. Ignored -for non-imported targets. +Set this to the location of the ``.lib`` part of a Windows DLL, or on +AIX set it to an import file created for executables that export symbols +(see the :prop_tgt:`ENABLE_EXPORTS` target property). +Ignored for non-imported targets. diff --git a/Help/prop_tgt/INSTALL_REMOVE_ENVIRONMENT_RPATH.rst b/Help/prop_tgt/INSTALL_REMOVE_ENVIRONMENT_RPATH.rst new file mode 100644 index 0000000..a474fc6 --- /dev/null +++ b/Help/prop_tgt/INSTALL_REMOVE_ENVIRONMENT_RPATH.rst @@ -0,0 +1,10 @@ +INSTALL_REMOVE_ENVIRONMENT_RPATH +-------------------------------- + +Removes compiler defined rpaths durimg installation. + +``INSTALL_REMOVE_ENVIRONMENT_RPATH`` is a boolean that if set to ``True`` will +remove compiler defined rpaths from the project if the user also defines rpath +with :prop_tgt:`INSTALL_RPATH`. This property is initialized by whether the +value of :variable:`CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH` is set when a +target is created. diff --git a/Help/prop_tgt/INSTALL_RPATH.rst b/Help/prop_tgt/INSTALL_RPATH.rst index 6403f4c..93b4488 100644 --- a/Help/prop_tgt/INSTALL_RPATH.rst +++ b/Help/prop_tgt/INSTALL_RPATH.rst @@ -7,3 +7,6 @@ A semicolon-separated list specifying the rpath to use in installed targets (for platforms that support it). This property is initialized by the value of the variable :variable:`CMAKE_INSTALL_RPATH` if it is set when a target is created. + +This property supports +:manual:`generator expressions <cmake-generator-expressions(7)>`. diff --git a/Help/prop_tgt/VS_DPI_AWARE.rst b/Help/prop_tgt/VS_DPI_AWARE.rst new file mode 100644 index 0000000..82640cc --- /dev/null +++ b/Help/prop_tgt/VS_DPI_AWARE.rst @@ -0,0 +1,14 @@ +VS_DPI_AWARE +------------ + +Set the Manifest Tool -> Input and Output -> DPI Awareness in the Visual Studio +target project properties. + +Valid values are ``PerMonitor``, ``ON``, or ``OFF``. + +For example: + +.. code-block:: cmake + + add_executable(myproject myproject.cpp) + set_property(TARGET myproject PROPERTY VS_DPI_AWARE "PerMonitor") diff --git a/Help/release/3.15.rst b/Help/release/3.15.rst index b0365ba..48f3aa4 100644 --- a/Help/release/3.15.rst +++ b/Help/release/3.15.rst @@ -369,3 +369,10 @@ Changes made since CMake 3.15.0 include the following. * In CMake 3.15.0 and 3.15.1 the :variable:`CMAKE_FIND_PACKAGE_PREFER_CONFIG` variable caused the :command:`find_package` command to fail on a missing package even without the ``REQUIRED`` option. This has been fixed. + +3.15.3 +------ + +* ``CrayPrgEnv`` compiler wrapper support has been updated for the 19.06 + release of the Cray Programming Environment for which the default linking + mode on XC Cray systems is now dynamic instead of static. diff --git a/Help/release/dev/0-sample-topic.rst b/Help/release/dev/0-sample-topic.rst new file mode 100644 index 0000000..e4cc01e --- /dev/null +++ b/Help/release/dev/0-sample-topic.rst @@ -0,0 +1,7 @@ +0-sample-topic +-------------- + +* This is a sample release note for the change in a topic. + Developers should add similar notes for each topic branch + making a noteworthy change. Each document should be named + and titled to match the topic name to avoid merge conflicts. diff --git a/Help/release/dev/CMP0095.rst b/Help/release/dev/CMP0095.rst new file mode 100644 index 0000000..21d0550 --- /dev/null +++ b/Help/release/dev/CMP0095.rst @@ -0,0 +1,5 @@ +CMP0095 +------- + +* ``RPATH`` entries are properly escaped in the intermediary CMake install script. + See policy :policy:`CMP0095`. diff --git a/Help/release/dev/FindPython-FIND_ABI.rst b/Help/release/dev/FindPython-FIND_ABI.rst new file mode 100644 index 0000000..19e3f71 --- /dev/null +++ b/Help/release/dev/FindPython-FIND_ABI.rst @@ -0,0 +1,5 @@ +FindPython-FIND_ABI +------------------- + +* Modules :module:`FindPython3` and :module:`FindPython` gain the capability + to control which ``ABIs`` will be searched. diff --git a/Help/release/dev/add-install-remove-environment-rpath.rst b/Help/release/dev/add-install-remove-environment-rpath.rst new file mode 100644 index 0000000..156106c --- /dev/null +++ b/Help/release/dev/add-install-remove-environment-rpath.rst @@ -0,0 +1,6 @@ +add-install-remove-environment-rpath +------------------------------------ + +* A new target property, :prop_tgt:`INSTALL_REMOVE_ENVIRONMENT_RPATH`, was + added which removes compiler-defined rpaths from a target. This property is + initialized by :variable:`CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH`. diff --git a/Help/release/dev/add_cmake_find_use_package_registry.rst b/Help/release/dev/add_cmake_find_use_package_registry.rst new file mode 100644 index 0000000..1b02bad --- /dev/null +++ b/Help/release/dev/add_cmake_find_use_package_registry.rst @@ -0,0 +1,11 @@ +add_cmake_find_use_package_registry +----------------------------------- + +* The :command:`find_package` command has learned to check the following + variables to control searching + + * :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY` - Controls the searching the + cmake user registry. + +* The :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY` has been deprecated. + Instead use :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY` diff --git a/Help/release/dev/add_skip_regular_expression_test_property.rst b/Help/release/dev/add_skip_regular_expression_test_property.rst new file mode 100644 index 0000000..20ef214 --- /dev/null +++ b/Help/release/dev/add_skip_regular_expression_test_property.rst @@ -0,0 +1,10 @@ +add_skip_regular_expression_test_property +----------------------------------------- + +* A new test property, :prop_test:`SKIP_REGULAR_EXPRESSION`, has been added. + This property is similar to :prop_test:`FAIL_REGULAR_EXPRESSION` and + :prop_test:`PASS_REGULAR_EXPRESSION`, but with the same meaning as + :prop_test:`SKIP_RETURN_CODE`. This is useful, for example, in cases where + the user has no control over the return code of the test. For example, in + Catch2, the return value is the number of assertion failed, therefore it is + impossible to use it for :prop_test:`SKIP_RETURN_CODE`. diff --git a/Help/release/dev/add_test-expand_lists.rst b/Help/release/dev/add_test-expand_lists.rst new file mode 100644 index 0000000..88d26b7 --- /dev/null +++ b/Help/release/dev/add_test-expand_lists.rst @@ -0,0 +1,6 @@ +add_test-expand_lists +--------------------- + +* The command :command:`add_test` learned the option ``COMMAND_EXPAND_LISTS`` + which causes lists in the ``COMMAND`` argument to be expanded, including + lists created by generator expressions. diff --git a/Help/release/dev/aix.rst b/Help/release/dev/aix.rst new file mode 100644 index 0000000..6919358 --- /dev/null +++ b/Help/release/dev/aix.rst @@ -0,0 +1,20 @@ +aix +--- + +* On AIX, executables using the :prop_tgt:`ENABLE_EXPORTS` target property + now produce a linker import file with a ``.imp`` extension in addition + to the executable file. Plugins (created via :command:`add_library` with + the ``MODULE`` option) that use :command:`target_link_libraries` to link + to the executable for its symbols are now linked using the import file. + The :command:`install(TARGETS)` command now installs the import file as + an ``ARCHIVE`` artifact. + +* On AIX, runtime linking is no longer enabled by default. CMake provides + the linker enough information to resolve all symbols up front. + One may manually enable runtime linking for shared libraries and/or + loadable modules by adding ``-Wl,-G`` to their link flags + (e.g. in the :variable:`CMAKE_SHARED_LINKER_FLAGS` or + :variable:`CMAKE_MODULE_LINKER_FLAGS` variable). + One may manually enable runtime linking for executables by adding + ``-Wl,-brtl`` to their link flags (e.g. in the + :variable:`CMAKE_EXE_LINKER_FLAGS` variable). diff --git a/Help/release/dev/build-install-rpath-genex.rst b/Help/release/dev/build-install-rpath-genex.rst new file mode 100644 index 0000000..644b1b2 --- /dev/null +++ b/Help/release/dev/build-install-rpath-genex.rst @@ -0,0 +1,5 @@ +build-install-rpath-genex +------------------------- + +* :prop_tgt:`BUILD_RPATH` and :prop_tgt:`INSTALL_RPATH` now support + :manual:`generator expressions <cmake-generator-expressions(7)>`. diff --git a/Help/release/dev/cmake-e-true-false.rst b/Help/release/dev/cmake-e-true-false.rst new file mode 100644 index 0000000..173fabd --- /dev/null +++ b/Help/release/dev/cmake-e-true-false.rst @@ -0,0 +1,5 @@ +cmake-e-true-false +------------------ + +* :manual:`cmake(1)` ``-E`` now supports ``true`` and ``false`` commands, which + do nothing while returning exit codes of 0 and 1, respectively. diff --git a/Help/release/dev/cmake-qch-no-version-in-filename.rst b/Help/release/dev/cmake-qch-no-version-in-filename.rst new file mode 100644 index 0000000..3c5cb04 --- /dev/null +++ b/Help/release/dev/cmake-qch-no-version-in-filename.rst @@ -0,0 +1,8 @@ +cmake-qch-no-version-in-filename +-------------------------------- + +* The Qt Compressed Help file is now named ``CMake.qch``, which no longer + contains the release version in the file name. When CMake is upgraded + in-place, the name and location of this file will remain constant. + Tools such as IDEs, help viewers, etc. should now be able to refer to this + file at a fixed location that remains valid across CMake upgrades. 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/ctest-build-makeprogram-propagated-configure-pass.rst b/Help/release/dev/ctest-build-makeprogram-propagated-configure-pass.rst new file mode 100644 index 0000000..4465de8 --- /dev/null +++ b/Help/release/dev/ctest-build-makeprogram-propagated-configure-pass.rst @@ -0,0 +1,6 @@ +ctest-build-makeprogram-propagated-configure-pass +------------------------------------------------- + +* :manual:`ctest(1)` ``--build-makeprogram`` now specifies the make program + used when configuring a project with the Ninja and Makefiles generators + in addition to building it. diff --git a/Help/release/dev/cuda-CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS.rst b/Help/release/dev/cuda-CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS.rst new file mode 100644 index 0000000..f21fddf --- /dev/null +++ b/Help/release/dev/cuda-CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS.rst @@ -0,0 +1,6 @@ +cuda-CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS +-------------------------------------- + +* Variable :variable:`CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS` has been + introduced to optionally initialize the + :prop_tgt:`CUDA_RESOLVE_DEVICE_SYMBOLS` target property. diff --git a/Help/release/dev/deprecate-policy-old.rst b/Help/release/dev/deprecate-policy-old.rst new file mode 100644 index 0000000..440efa9 --- /dev/null +++ b/Help/release/dev/deprecate-policy-old.rst @@ -0,0 +1,8 @@ +deprecate-policy-old +-------------------- + +* An explicit deprecation diagnostic was added for policy ``CMP0067`` + (``CMP0066`` and below were already deprecated). + The :manual:`cmake-policies(7)` manual explains that the OLD behaviors + of all policies are deprecated and that projects should port to the + NEW behaviors. diff --git a/Help/release/dev/eclipse-resource-encoding.rst b/Help/release/dev/eclipse-resource-encoding.rst new file mode 100644 index 0000000..6ceca0c --- /dev/null +++ b/Help/release/dev/eclipse-resource-encoding.rst @@ -0,0 +1,6 @@ +eclipse-resource-encoding +------------------------- + +* The :generator:`Eclipse CDT4` extra generator gained a new + :variable:`CMAKE_ECLIPSE_RESOURCE_ENCODING` option to specify + the resource encoding. diff --git a/Help/release/dev/external-project-support-no-git-submodules.rst b/Help/release/dev/external-project-support-no-git-submodules.rst new file mode 100644 index 0000000..1d4be66 --- /dev/null +++ b/Help/release/dev/external-project-support-no-git-submodules.rst @@ -0,0 +1,6 @@ +external-project-support-no-git-submodules +------------------------------------------ + +* The :module:`ExternalProject` module's ``ExternalProject_Add`` command + has been updated so that ``GIT_SUBMODULES ""`` initializes no submodules. See + policy :policy:`CMP0097`. diff --git a/Help/release/dev/get-runtime-dependencies.rst b/Help/release/dev/get-runtime-dependencies.rst new file mode 100644 index 0000000..b9dc6e6 --- /dev/null +++ b/Help/release/dev/get-runtime-dependencies.rst @@ -0,0 +1,9 @@ +get-runtime-dependencies +------------------------ + +* The :command:`file` command learned a new sub-command, + ``GET_RUNTIME_DEPENDENCIES``, which allows you to recursively get the list of + libraries linked by an executable or library. This sub-command is intended as + a replacement for :module:`GetPrerequisites`. +* The :module:`GetPrerequisites` module has been deprecated, as it has been + superceded by :command:`file(GET_RUNTIME_DEPENDENCIES)`. diff --git a/Help/release/dev/global-controls-over-find-locations.rst b/Help/release/dev/global-controls-over-find-locations.rst new file mode 100644 index 0000000..1c0b226 --- /dev/null +++ b/Help/release/dev/global-controls-over-find-locations.rst @@ -0,0 +1,21 @@ +global-controls-over-find-locations +----------------------------------- + +* The :command:`find_file`, :command:`find_library`, :command:`find_path`, + :command:`find_package`, and :command:`find_program` commands have learned to + check the following variables to control searching + + * :variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH` - Controls the searching + the cmake-specific environment variables. + + * :variable:`CMAKE_FIND_USE_CMAKE_PATH` - Controls the searching the + cmake-specific cache variables. + + * :variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH` - Controls the searching + cmake platform specific variables. + + * :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` - Controls the searching of + :variable:`<PackageName>_ROOT` variables. + + * :variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH` - Controls the searching + the standard system environment variables. 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/release/dev/per-lang-link-library-flag.rst b/Help/release/dev/per-lang-link-library-flag.rst new file mode 100644 index 0000000..ca1181d --- /dev/null +++ b/Help/release/dev/per-lang-link-library-flag.rst @@ -0,0 +1,7 @@ +per-lang-link-library-flag +-------------------------- + +* The new :variable:`CMAKE_<LANG>_LINK_LIBRARY_FLAG` flag allows you to now + control the flag used to specify linking to a library on a per-language basis. + This is useful for mixed-language projects where the different drivers may use + different flags. diff --git a/Help/release/dev/project-version-0.rst b/Help/release/dev/project-version-0.rst new file mode 100644 index 0000000..6525522 --- /dev/null +++ b/Help/release/dev/project-version-0.rst @@ -0,0 +1,5 @@ +project-version-0 +----------------- + +* The :command:`project` no longer strips leading zeros in version components. + See policy :policy:`CMP0096`. diff --git a/Help/release/dev/solaris_clang.rst b/Help/release/dev/solaris_clang.rst new file mode 100644 index 0000000..0b023ee --- /dev/null +++ b/Help/release/dev/solaris_clang.rst @@ -0,0 +1,4 @@ +solaris_clang +------------- + +* The ``Clang`` compiler is now supported on ``Solaris``. diff --git a/Help/release/dev/trace-redirect.rst b/Help/release/dev/trace-redirect.rst new file mode 100644 index 0000000..410021e --- /dev/null +++ b/Help/release/dev/trace-redirect.rst @@ -0,0 +1,6 @@ +trace-redirect +-------------- + +* :manual:`cmake(1)` gained a ``--trace-redirect=<file>`` command line option + that can be used to redirect ``--trace`` output to a file instead + of ``stderr``. diff --git a/Help/release/dev/vs-dpi-aware.rst b/Help/release/dev/vs-dpi-aware.rst new file mode 100644 index 0000000..f76f26c --- /dev/null +++ b/Help/release/dev/vs-dpi-aware.rst @@ -0,0 +1,6 @@ +vs-dpi-aware +------------ + +* The :prop_tgt:`VS_DPI_AWARE` target property was added to tell + :ref:`Visual Studio Generators` to set the ``EnableDpiAwareness`` + property in ``.vcxproj`` files. diff --git a/Help/release/index.rst b/Help/release/index.rst index 35a47aa..62032e6 100644 --- a/Help/release/index.rst +++ b/Help/release/index.rst @@ -7,6 +7,8 @@ CMake Release Notes This file should include the adjacent "dev.txt" file in development versions but not in release versions. +.. include:: dev.txt + Releases ======== diff --git a/Help/variable/CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION.rst b/Help/variable/CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION.rst index 5ae55d1..22808e3 100644 --- a/Help/variable/CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION.rst +++ b/Help/variable/CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION.rst @@ -3,7 +3,11 @@ CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION When :ref:`Cross Compiling for Android with the NDK`, this variable may be set to specify the version of the toolchain to be used -as the compiler. The variable must be set to one of these forms: +as the compiler. + +On NDK r19 or above, this variable must be unset or set to ``clang``. + +On NDK r18 or below, this variable must be set to one of these forms: * ``<major>.<minor>``: GCC of specified version * ``clang<major>.<minor>``: Clang of specified version diff --git a/Help/variable/CMAKE_CUDA_HOST_COMPILER.rst b/Help/variable/CMAKE_CUDA_HOST_COMPILER.rst index eea2c4f..6d34c5c 100644 --- a/Help/variable/CMAKE_CUDA_HOST_COMPILER.rst +++ b/Help/variable/CMAKE_CUDA_HOST_COMPILER.rst @@ -4,4 +4,5 @@ CMAKE_CUDA_HOST_COMPILER Executable to use when compiling host code when compiling ``CUDA`` language files. Maps to the ``nvcc -ccbin`` option. Will only be used by CMake on the first configuration to determine a valid host compiler for ``CUDA``. After a valid -host compiler has been found, this value is read-only. +host compiler has been found, this value is read-only. This variable takes +priority over the :envvar:`CUDAHOSTCXX` environment variable. diff --git a/Help/variable/CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS.rst b/Help/variable/CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS.rst new file mode 100644 index 0000000..fc835cd --- /dev/null +++ b/Help/variable/CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS.rst @@ -0,0 +1,6 @@ +CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS +--------------------------------- + +Default value for :prop_tgt:`CUDA_RESOLVE_DEVICE_SYMBOLS` target +property. This variable is used to initialize the property on each target as +it is created. diff --git a/Help/variable/CMAKE_ECLIPSE_RESOURCE_ENCODING.rst b/Help/variable/CMAKE_ECLIPSE_RESOURCE_ENCODING.rst new file mode 100644 index 0000000..314efe5 --- /dev/null +++ b/Help/variable/CMAKE_ECLIPSE_RESOURCE_ENCODING.rst @@ -0,0 +1,6 @@ +CMAKE_ECLIPSE_RESOURCE_ENCODING +------------------------------- + +This cache variable tells the :generator:`Eclipse CDT4` project generator +to set the resource encoding to the given value in generated project files. +If no value is given, no encoding will be set. diff --git a/Help/variable/CMAKE_ENABLE_EXPORTS.rst b/Help/variable/CMAKE_ENABLE_EXPORTS.rst index 7ec4d63..8848da1 100644 --- a/Help/variable/CMAKE_ENABLE_EXPORTS.rst +++ b/Help/variable/CMAKE_ENABLE_EXPORTS.rst @@ -1,22 +1,8 @@ CMAKE_ENABLE_EXPORTS -------------------- -Specify whether an executable exports symbols for loadable modules. +Specify whether executables export symbols for loadable modules. -Normally an executable does not export any symbols because it is the -final program. It is possible for an executable to export symbols to -be used by loadable modules. When this property is set to true CMake -will allow other targets to ``link`` to the executable with the -:command:`TARGET_LINK_LIBRARIES` command. On all platforms a target-level -dependency on the executable is created for targets that link to it. -For DLL platforms an import library will be created for the exported -symbols and then used for linking. All Windows-based systems -including Cygwin are DLL platforms. For non-DLL platforms that -require all symbols to be resolved at link time, such as macOS, the -module will ``link`` to the executable using a flag like -``-bundle_loader``. For other non-DLL platforms the link rule is simply -ignored since the dynamic loader will automatically bind symbols when -the module is loaded. - -This variable is used to initialize the target property -:prop_tgt:`ENABLE_EXPORTS` for executable targets. +This variable is used to initialize the :prop_tgt:`ENABLE_EXPORTS` target +property for executable targets when they are created by calls to the +:command:`add_executable` command. See the property documentation for details. diff --git a/Help/variable/CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY.rst b/Help/variable/CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY.rst index 9058471..ffb8a2c 100644 --- a/Help/variable/CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY.rst +++ b/Help/variable/CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY.rst @@ -1,12 +1,23 @@ CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY -------------------------------------- -Skip :ref:`User Package Registry` in :command:`find_package` calls. +.. deprecated:: 3.16 + + Use the :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY` variable instead. + +By default this variable is not set. If neither +:variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY` nor +``CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY`` is set, then +:command:`find_package()` will use the `User Package Registry` unless the +`NO_CMAKE_PACKAGE_REGISTRY` option is provided. + +``CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY`` is ignored if +:variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY` is set. In some cases, for example to locate only system wide installations, it is not desirable to use the :ref:`User Package Registry` when searching for packages. If the :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY` -variable is enabled, all the :command:`find_package` commands will skip +variable is ``TRUE``, all the :command:`find_package` commands will skip the :ref:`User Package Registry` as if they were called with the ``NO_CMAKE_PACKAGE_REGISTRY`` argument. diff --git a/Help/variable/CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH.rst b/Help/variable/CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH.rst new file mode 100644 index 0000000..2db5081 --- /dev/null +++ b/Help/variable/CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH.rst @@ -0,0 +1,18 @@ +CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH +------------------------------------- + +Controls the searching the cmake-specific environment variables by the +:command:`find_program`, :command:`find_library`, :command:`find_file`, +:command:`find_path`, and command:`find_package` commands. +This is useful in cross-compiling environments. + +By default this variable is not set, which is equivalent to it having +a value of ``TRUE``. Explicit options given to the :command:`find_program`, +:command:`find_library`, :command:`find_file`, and :command:`find_path` +commands take precedence over this variable. + +See also the :variable:`CMAKE_FIND_USE_CMAKE_PATH`, +:variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`, +:variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH`, +:variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY`, +and :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` variables. diff --git a/Help/variable/CMAKE_FIND_USE_CMAKE_PATH.rst b/Help/variable/CMAKE_FIND_USE_CMAKE_PATH.rst new file mode 100644 index 0000000..4ca7ad1 --- /dev/null +++ b/Help/variable/CMAKE_FIND_USE_CMAKE_PATH.rst @@ -0,0 +1,18 @@ +CMAKE_FIND_USE_CMAKE_PATH +------------------------- + +Controls the searching the cmake-specific cache variables by the +:command:`find_program`, :command:`find_library`, :command:`find_file`, +:command:`find_path`, and command:`find_package` commands. +This is useful in cross-compiling environments. + +By default this variable is not set, which is equivalent to it having +a value of ``TRUE``. Explicit options given to the :command:`find_program`, +:command:`find_library`, :command:`find_file`, and :command:`find_path` +commands take precedence over this variable. + +See also the :variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH`, +:variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`, +:variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH`, +:variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY`, +and :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` variables. diff --git a/Help/variable/CMAKE_FIND_USE_CMAKE_SYSTEM_PATH.rst b/Help/variable/CMAKE_FIND_USE_CMAKE_SYSTEM_PATH.rst new file mode 100644 index 0000000..d3259ae --- /dev/null +++ b/Help/variable/CMAKE_FIND_USE_CMAKE_SYSTEM_PATH.rst @@ -0,0 +1,18 @@ +CMAKE_FIND_USE_CMAKE_SYSTEM_PATH +-------------------------------- + +Controls the searching cmake platform specific variables by the +:command:`find_program`, :command:`find_library`, :command:`find_file`, +:command:`find_path`, and command:`find_package` commands. +This is useful in cross-compiling environments. + +By default this variable is not set, which is equivalent to it having +a value of ``TRUE``. Explicit options given to the :command:`find_program`, +:command:`find_library`, :command:`find_file`, and :command:`find_path` +commands take precedence over this variable. + +See also the :variable:`CMAKE_FIND_USE_CMAKE_PATH`, +:variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH`, +:variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH`, +:variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY`, +and :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` variables. diff --git a/Help/variable/CMAKE_FIND_USE_PACKAGE_REGISTRY.rst b/Help/variable/CMAKE_FIND_USE_PACKAGE_REGISTRY.rst new file mode 100644 index 0000000..75e910f --- /dev/null +++ b/Help/variable/CMAKE_FIND_USE_PACKAGE_REGISTRY.rst @@ -0,0 +1,29 @@ +CMAKE_FIND_USE_PACKAGE_REGISTRY +------------------------------- + +Controls the searching the :ref:`User Package Registry` by the :command:`find_package` +command. + +By default this variable is not set and the behavior will fall back +to that determined by the deprecated :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY` +variable. If that is also not set, then `find_package()` will use the +`User Package Registry` unless the `NO_CMAKE_PACKAGE_REGISTRY` option +is provided. + +This variable takes precedence over :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY` +when both are set. + +In some cases, for example to locate only system wide installations, it +is not desirable to use the :ref:`User Package Registry` when searching +for packages. If the :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY` +variable is ``FALSE``, all the :command:`find_package` commands will skip +the :ref:`User Package Registry` as if they were called with the +``NO_CMAKE_PACKAGE_REGISTRY`` argument. + +See also :ref:`Disabling the Package Registry`. + +See also the :variable:`CMAKE_FIND_USE_CMAKE_PATH`, +:variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH`, +:variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`, +:variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH`, +and :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` variables. diff --git a/Help/variable/CMAKE_FIND_USE_PACKAGE_ROOT_PATH.rst b/Help/variable/CMAKE_FIND_USE_PACKAGE_ROOT_PATH.rst new file mode 100644 index 0000000..e17fdcc --- /dev/null +++ b/Help/variable/CMAKE_FIND_USE_PACKAGE_ROOT_PATH.rst @@ -0,0 +1,18 @@ +CMAKE_FIND_USE_PACKAGE_ROOT_PATH +-------------------------------- + +Controls the searching of :variable:`<PackageName>_ROOT` variables by the +:command:`find_program`, :command:`find_library`, :command:`find_file`, +:command:`find_path`, and command:`find_package` commands. +This is useful in cross-compiling environments. + +By default this variable is not set, which is equivalent to it having +a value of ``TRUE``. Explicit options given to the :command:`find_program`, +:command:`find_library`, :command:`find_file`, and :command:`find_path` +commands take precedence over this variable. + +See also the :variable:`CMAKE_FIND_USE_CMAKE_PATH`, +:variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH`, +:variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`, +:variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH`, +and :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY` variables. diff --git a/Help/variable/CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH.rst b/Help/variable/CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH.rst new file mode 100644 index 0000000..71432f6 --- /dev/null +++ b/Help/variable/CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH.rst @@ -0,0 +1,18 @@ +CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH +-------------------------------------- + +Controls the searching the standard system environment variables by the +:command:`find_program`, :command:`find_library`, :command:`find_file`, +:command:`find_path`, and command:`find_package` commands. +This is useful in cross-compiling environments. + +By default this variable is not set, which is equivalent to it having +a value of ``TRUE``. Explicit options given to the :command:`find_program`, +:command:`find_library`, :command:`find_file`, and :command:`find_path` +commands take precedence over this variable. + +See also the :variable:`CMAKE_FIND_USE_CMAKE_PATH`, +:variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH`, +:variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`, +:variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY`, +and :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` variables. diff --git a/Help/variable/CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH.rst b/Help/variable/CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH.rst new file mode 100644 index 0000000..19ae5f3 --- /dev/null +++ b/Help/variable/CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH.rst @@ -0,0 +1,9 @@ +CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH +-------------------------------------- + +Removes compiler defined rpaths durimg installation. + +``CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH`` is a boolean that if set to ``true`` +removes compiler defined rpaths from the project if the user also defines rpath +with :prop_tgt:`INSTALL_RPATH`. This is used to initialize the target property +:prop_tgt:`INSTALL_REMOVE_ENVIRONMENT_RPATH` for all targets. diff --git a/Help/variable/CMAKE_LANG_LINK_LIBRARY_FLAG.rst b/Help/variable/CMAKE_LANG_LINK_LIBRARY_FLAG.rst new file mode 100644 index 0000000..d7bb0d8 --- /dev/null +++ b/Help/variable/CMAKE_LANG_LINK_LIBRARY_FLAG.rst @@ -0,0 +1,7 @@ +CMAKE_<LANG>_LINK_LIBRARY_FLAG +------------------------------ + +Flag to be used to link a library into a shared library or executable. + +This flag will be used to specify a library to link to a shared library or an +executable for the specific language. On most compilers this is ``-l``. diff --git a/Help/variable/CMAKE_MESSAGE_INDENT.rst b/Help/variable/CMAKE_MESSAGE_INDENT.rst new file mode 100644 index 0000000..7e44a4c --- /dev/null +++ b/Help/variable/CMAKE_MESSAGE_INDENT.rst @@ -0,0 +1,32 @@ +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: + +.. code-block:: none + + -- Collected items in the "listVar": + -- one + -- two + -- three + -- 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/BundleUtilities.cmake b/Modules/BundleUtilities.cmake index f94fc5c..2f3b9e1 100644 --- a/Modules/BundleUtilities.cmake +++ b/Modules/BundleUtilities.cmake @@ -243,11 +243,13 @@ if(DEFINED CMAKE_GENERATOR) endif() endif() +cmake_policy(PUSH) +cmake_policy(SET CMP0057 NEW) # if IN_LIST + # The functions defined in this file depend on the get_prerequisites function # (and possibly others) found in: # -get_filename_component(BundleUtilities_cmake_dir "${CMAKE_CURRENT_LIST_FILE}" PATH) -include("${BundleUtilities_cmake_dir}/GetPrerequisites.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/GetPrerequisites.cmake") function(get_bundle_main_executable bundle result_var) @@ -280,7 +282,7 @@ function(get_bundle_main_executable bundle result_var) endif() endforeach() - if(NOT "${bundle_executable}" STREQUAL "") + if(NOT bundle_executable STREQUAL "") if(EXISTS "${bundle}/Contents/MacOS/${bundle_executable}") set(result "${bundle}/Contents/MacOS/${bundle_executable}") else() @@ -600,17 +602,9 @@ function(get_bundle_keys app libs dirs keys_var) set_bundle_key_values(${keys_var} "${lib}" "${lib}" "${exepath}" "${dirs}" 0 "${main_rpaths}") set(prereqs "") - set(ignoreFile FALSE) get_filename_component(prereq_filename ${lib} NAME) - if(NOT "${CFG_IGNORE_ITEM}" STREQUAL "" ) - foreach(item ${CFG_IGNORE_ITEM}) - if("${item}" STREQUAL "${prereq_filename}") - set(ignoreFile TRUE) - endif() - endforeach() - endif() - if(NOT ignoreFile) + if(NOT prereq_filename IN_LIST CFG_IGNORE_ITEM) get_prerequisites("${lib}" prereqs 1 1 "${exepath}" "${dirs}" "${main_rpaths}") foreach(pr ${prereqs}) set_bundle_key_values(${keys_var} "${lib}" "${pr}" "${exepath}" "${dirs}" 1 "${main_rpaths}") @@ -627,7 +621,7 @@ function(get_bundle_keys app libs dirs keys_var) foreach(exe ${exes}) # Main executable is scanned first above: # - if(NOT "${exe}" STREQUAL "${executable}") + if(NOT exe STREQUAL executable) # Add the exe itself to the keys: # set_bundle_key_values(${keys_var} "${exe}" "${exe}" "${exepath}" "${dirs}" 0 "${main_rpaths}") @@ -643,17 +637,9 @@ function(get_bundle_keys app libs dirs keys_var) # Add each prerequisite to the keys: # set(prereqs "") - set(ignoreFile FALSE) get_filename_component(prereq_filename ${exe} NAME) - if(NOT "${CFG_IGNORE_ITEM}" STREQUAL "" ) - foreach(item ${CFG_IGNORE_ITEM}) - if("${item}" STREQUAL "${prereq_filename}") - set(ignoreFile TRUE) - endif() - endforeach() - endif() - if(NOT ignoreFile) + if(NOT prereq_filename IN_LIST CFG_IGNORE_ITEM) get_prerequisites("${exe}" prereqs 1 1 "${exepath}" "${dirs}" "${exe_rpaths}") foreach(pr ${prereqs}) set_bundle_key_values(${keys_var} "${exe}" "${pr}" "${exepath}" "${dirs}" 1 "${exe_rpaths}") @@ -665,7 +651,7 @@ function(get_bundle_keys app libs dirs keys_var) # preserve library symlink structure foreach(key ${${keys_var}}) - if("${${key}_COPYFLAG}" STREQUAL 1) + if("${${key}_COPYFLAG}" STREQUAL "1") if(IS_SYMLINK "${${key}_RESOLVED_ITEM}") get_filename_component(target "${${key}_RESOLVED_ITEM}" REALPATH) set_bundle_key_values(${keys_var} "${exe}" "${target}" "${exepath}" "${dirs}" 1 "${exe_rpaths}") @@ -682,7 +668,7 @@ function(get_bundle_keys app libs dirs keys_var) get_filename_component(resolved_item_compare "${resolved_item_compare}" NAME) get_filename_component(resolved_embedded_item_compare "${resolved_embedded_item_compare}" NAME) - if(NOT "${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}") + if(NOT resolved_item_compare STREQUAL resolved_embedded_item_compare) set(${key}_COPYFLAG "2") set(${key}_RESOLVED_ITEM "${${targetkey}_RESOLVED_EMBEDDED_ITEM}") endif() @@ -716,7 +702,7 @@ function(link_resolved_item_into_bundle resolved_item resolved_embedded_item) set(resolved_embedded_item_compare "${resolved_embedded_item}") endif() - if("${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}") + if(resolved_item_compare STREQUAL resolved_embedded_item_compare) message(STATUS "warning: resolved_item == resolved_embedded_item - not linking...") else() get_filename_component(target_dir "${resolved_embedded_item}" DIRECTORY) @@ -738,7 +724,7 @@ function(copy_resolved_item_into_bundle resolved_item resolved_embedded_item) set(resolved_embedded_item_compare "${resolved_embedded_item}") endif() - if("${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}") + if(resolved_item_compare STREQUAL resolved_embedded_item_compare) message(STATUS "warning: resolved_item == resolved_embedded_item - not copying...") else() #message(STATUS "copying COMMAND ${CMAKE_COMMAND} -E copy ${resolved_item} ${resolved_embedded_item}") @@ -761,7 +747,7 @@ function(copy_resolved_framework_into_bundle resolved_item resolved_embedded_ite set(resolved_embedded_item_compare "${resolved_embedded_item}") endif() - if("${resolved_item_compare}" STREQUAL "${resolved_embedded_item_compare}") + if(resolved_item_compare STREQUAL resolved_embedded_item_compare) message(STATUS "warning: resolved_item == resolved_embedded_item - not copying...") else() if(BU_COPY_FULL_FRAMEWORK_CONTENTS) @@ -841,12 +827,12 @@ function(fixup_bundle_item resolved_embedded_item exepath dirs) string(LENGTH "${resolved_embedded_item}" resolved_embedded_item_length) set(path_too_short 0) set(is_embedded 0) - if(${resolved_embedded_item_length} LESS ${exe_dotapp_dir_length}) + if(resolved_embedded_item_length LESS exe_dotapp_dir_length) set(path_too_short 1) endif() if(NOT path_too_short) string(SUBSTRING "${resolved_embedded_item}" 0 ${exe_dotapp_dir_length} item_substring) - if("${exe_dotapp_dir}/" STREQUAL "${item_substring}") + if("${exe_dotapp_dir}/" STREQUAL item_substring) set(is_embedded 1) endif() endif() @@ -1032,18 +1018,9 @@ function(verify_bundle_prerequisites bundle result_var info_var) message(STATUS "executable file ${count}: ${f}") set(prereqs "") - set(ignoreFile FALSE) get_filename_component(prereq_filename ${f} NAME) - if(NOT "${CFG_IGNORE_ITEM}" STREQUAL "" ) - foreach(item ${CFG_IGNORE_ITEM}) - if("${item}" STREQUAL "${prereq_filename}") - set(ignoreFile TRUE) - endif() - endforeach() - endif() - - if(NOT ignoreFile) + if(NOT prereq_filename IN_LIST CFG_IGNORE_ITEM) get_item_rpaths(${f} _main_exe_rpaths) get_prerequisites("${f}" prereqs 1 1 "${exepath}" "${_main_exe_rpaths}") @@ -1063,11 +1040,11 @@ function(verify_bundle_prerequisites bundle result_var info_var) gp_file_type("${f}" "${p}" p_type) if(APPLE) - if(NOT "${p_type}" STREQUAL "embedded" AND NOT "${p_type}" STREQUAL "system") + if(NOT p_type STREQUAL "embedded" AND NOT p_type STREQUAL "system") set(external_prereqs ${external_prereqs} "${p}") endif() else() - if(NOT "${p_type}" STREQUAL "local" AND NOT "${p_type}" STREQUAL "system") + if(NOT p_type STREQUAL "local" AND NOT p_type STREQUAL "system") set(external_prereqs ${external_prereqs} "${p}") endif() endif() @@ -1142,3 +1119,5 @@ function(verify_app app) message(FATAL_ERROR "error: verify_app failed") endif() endfunction() + +cmake_policy(POP) diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake index 43ae989..b0d80d1 100644 --- a/Modules/CMakeCUDAInformation.cmake +++ b/Modules/CMakeCUDAInformation.cmake @@ -171,7 +171,8 @@ if(NOT CMAKE_CUDA_LINK_EXECUTABLE) "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_LINKS}") endif() -if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0") +if( CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA" AND + CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0") set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "-Wno-deprecated-gpu-targets") else() set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "") diff --git a/Modules/CMakeDependentOption.cmake b/Modules/CMakeDependentOption.cmake index 6046d85..99d5070 100644 --- a/Modules/CMakeDependentOption.cmake +++ b/Modules/CMakeDependentOption.cmake @@ -12,7 +12,7 @@ conditions are true. When the option is not presented a default value is used, but any value set by the user is preserved for when the option is presented again. Example invocation: -:: +.. code-block:: cmake CMAKE_DEPENDENT_OPTION(USE_FOO "Use Foo" ON "USE_BAR;NOT USE_ZOT" OFF) @@ -21,7 +21,8 @@ If USE_BAR is true and USE_ZOT is false, this provides an option called USE_FOO that defaults to ON. Otherwise, it sets USE_FOO to OFF. If the status of USE_BAR or USE_ZOT ever changes, any value for the USE_FOO option is saved so that when the option is re-enabled it -retains its old value. +retains its old value. Each element in the fourth parameter is +evaluated as an if-condition, so :ref:`Condition Syntax` can be used. #]=======================================================================] macro(CMAKE_DEPENDENT_OPTION option doc default depends force) diff --git a/Modules/CMakeDetermineCSharpCompiler.cmake b/Modules/CMakeDetermineCSharpCompiler.cmake index dab9414..da860a8 100644 --- a/Modules/CMakeDetermineCSharpCompiler.cmake +++ b/Modules/CMakeDetermineCSharpCompiler.cmake @@ -18,7 +18,6 @@ if(NOT CMAKE_CSharp_COMPILER_ID_RUN) set(CMAKE_CSharp_COMPILER_ID_RUN 1) # Try to identify the compiler. - set(CMAKE_CSharp_COMPILER_ID_STRINGS_PARAMETERS ENCODING UTF-16LE) set(CMAKE_CSharp_COMPILER_ID) include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake) CMAKE_DETERMINE_COMPILER_ID(CSharp CSFLAGS CMakeCSharpCompilerId.cs) diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 02bc14b..0fcbbb7 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -640,10 +640,14 @@ function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file) set(ARCHITECTURE_ID) set(SIMULATE_ID) set(SIMULATE_VERSION) - file(STRINGS ${file} - CMAKE_${lang}_COMPILER_ID_STRINGS LIMIT_COUNT 38 - ${CMAKE_${lang}_COMPILER_ID_STRINGS_PARAMETERS} - REGEX ".?I.?N.?F.?O.?:.?[A-Za-z0-9_]+\\[[^]]*\\]") + foreach(encoding "" "ENCODING;UTF-16LE" "ENCODING;UTF-16BE") + file(STRINGS "${file}" CMAKE_${lang}_COMPILER_ID_STRINGS + LIMIT_COUNT 38 ${encoding} + REGEX ".?I.?N.?F.?O.?:.?[A-Za-z0-9_]+\\[[^]]*\\]") + if(NOT CMAKE_${lang}_COMPILER_ID_STRINGS STREQUAL "") + break() + endif() + endforeach() set(COMPILER_ID_TWICE) # With the IAR Compiler, some strings are found twice, first time as incomplete # list like "?<Constant "INFO:compiler[IAR]">". Remove the incomplete copies. diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index 0e84116..773ee53 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -72,7 +72,7 @@ if(("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC" AND find_program(CMAKE_LINKER NAMES link HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) find_program(CMAKE_MT NAMES mt HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) - list(APPEND _CMAKE_TOOL_VARS CMAKE_LINKER CMAKE_MT) + list(APPEND _CMAKE_TOOL_VARS LINKER MT) # in all other cases search for ar, ranlib, etc. else() @@ -84,27 +84,36 @@ else() endif() if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL Clang) - set(LLVM_OBJDUMP "llvm-objdump") - set(LLVM_LLD "ld.lld") - set(LLVM_RANLIB "llvm-ranlib") - set(LLVM_AR "llvm-ar") + set(_CMAKE_ADDITIONAL_AR_NAMES "llvm-ar") + set(_CMAKE_ADDITIONAL_RANLIB_NAMES "llvm-ranlib") + set(_CMAKE_ADDITIONAL_STRIP_NAMES "llvm-strip") + set(_CMAKE_ADDITIONAL_LINKER_NAMES "ld.lld") + set(_CMAKE_ADDITIONAL_NM_NAMES "llvm-nm") + set(_CMAKE_ADDITIONAL_OBJDUMP_NAMES "llvm-objdump") + set(_CMAKE_ADDITIONAL_OBJCOPY_NAMES "llvm-objcopy") + set(_CMAKE_ADDITIONAL_READELF_NAMES "llvm-readelf") + set(_CMAKE_ADDITIONAL_DLLTOOL_NAMES "llvm-dlltool") + set(_CMAKE_ADDITIONAL_ADDR2LINE_NAMES "llvm-addr2line") endif() - find_program(CMAKE_AR NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ar${_CMAKE_TOOLCHAIN_SUFFIX} ${LLVM_AR} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) + find_program(CMAKE_AR NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ar${_CMAKE_TOOLCHAIN_SUFFIX} ${_CMAKE_ADDITIONAL_AR_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) - find_program(CMAKE_RANLIB NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ranlib ${LLVM_RANLIB} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) + find_program(CMAKE_RANLIB NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ranlib ${_CMAKE_ADDITIONAL_RANLIB_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) if(NOT CMAKE_RANLIB) set(CMAKE_RANLIB : CACHE INTERNAL "noop for ranlib") endif() - find_program(CMAKE_STRIP NAMES ${_CMAKE_TOOLCHAIN_PREFIX}strip${_CMAKE_TOOLCHAIN_SUFFIX} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) - find_program(CMAKE_LINKER NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ld ${LLVM_LLD} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) - find_program(CMAKE_NM NAMES ${_CMAKE_TOOLCHAIN_PREFIX}nm HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) - find_program(CMAKE_OBJDUMP NAMES ${_CMAKE_TOOLCHAIN_PREFIX}objdump ${LLVM_OBJDUMP} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) - find_program(CMAKE_OBJCOPY NAMES ${_CMAKE_TOOLCHAIN_PREFIX}objcopy HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) + find_program(CMAKE_STRIP NAMES ${_CMAKE_TOOLCHAIN_PREFIX}strip${_CMAKE_TOOLCHAIN_SUFFIX} ${_CMAKE_ADDITIONAL_STRIP_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) + find_program(CMAKE_LINKER NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ld ${_CMAKE_ADDITIONAL_LINKER_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) + find_program(CMAKE_NM NAMES ${_CMAKE_TOOLCHAIN_PREFIX}nm ${_CMAKE_ADDITIONAL_NM_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) + find_program(CMAKE_OBJDUMP NAMES ${_CMAKE_TOOLCHAIN_PREFIX}objdump ${_CMAKE_ADDITIONAL_OBJDUMP_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) + find_program(CMAKE_OBJCOPY NAMES ${_CMAKE_TOOLCHAIN_PREFIX}objcopy ${_CMAKE_ADDITIONAL_OBJCOPY_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) + find_program(CMAKE_READELF NAMES ${_CMAKE_TOOLCHAIN_PREFIX}readelf ${_CMAKE_ADDITIONAL_READELF_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) + find_program(CMAKE_DLLTOOL NAMES ${_CMAKE_TOOLCHAIN_PREFIX}dlltool ${_CMAKE_ADDITIONAL_DLLTOOL_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) + find_program(CMAKE_ADDR2LINE NAMES ${_CMAKE_TOOLCHAIN_PREFIX}addr2line ${_CMAKE_ADDITIONAL_ADDR2LINE_NAMES} HINTS ${_CMAKE_TOOLCHAIN_LOCATION}) - list(APPEND _CMAKE_TOOL_VARS CMAKE_AR CMAKE_RANLIB CMAKE_STRIP CMAKE_LINKER CMAKE_NM CMAKE_OBJDUMP CMAKE_OBJCOPY) + list(APPEND _CMAKE_TOOL_VARS AR RANLIB STRIP LINKER NM OBJDUMP OBJCOPY READELF DLLTOOL ADDR2LINE) endif() @@ -115,15 +124,16 @@ if(CMAKE_PLATFORM_HAS_INSTALLNAME) message(FATAL_ERROR "Could not find install_name_tool, please check your installation.") endif() - list(APPEND _CMAKE_TOOL_VARS CMAKE_INSTALL_NAME_TOOL) + list(APPEND _CMAKE_TOOL_VARS INSTALL_NAME_TOOL) endif() # Mark any tool cache entries as advanced. foreach(var IN LISTS _CMAKE_TOOL_VARS) - get_property(_CMAKE_TOOL_CACHED CACHE ${var} PROPERTY TYPE) + get_property(_CMAKE_TOOL_CACHED CACHE CMAKE_${var} PROPERTY TYPE) if(_CMAKE_TOOL_CACHED) - mark_as_advanced(${var}) + mark_as_advanced(CMAKE_${var}) endif() + unset(_CMAKE_ADDITIONAL_${var}_NAMES) endforeach() unset(_CMAKE_TOOL_VARS) unset(_CMAKE_TOOL_CACHED) diff --git a/Modules/CMakeRCInformation.cmake b/Modules/CMakeRCInformation.cmake index 7bf6567..7c3a5ab 100644 --- a/Modules/CMakeRCInformation.cmake +++ b/Modules/CMakeRCInformation.cmake @@ -17,6 +17,17 @@ set(CMAKE_SYSTEM_AND_RC_COMPILER_INFO_FILE ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}.cmake) include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL) +# This should be included before the _INIT variables are +# used to initialize the cache. Since the rule variables +# have if blocks on them, users can still define them here. +# But, it should still be after the platform file so changes can +# be made to those values. +if(CMAKE_USER_MAKE_RULES_OVERRIDE) + # Save the full path of the file so try_compile can use it. + include(${CMAKE_USER_MAKE_RULES_OVERRIDE} RESULT_VARIABLE _override) + set(CMAKE_USER_MAKE_RULES_OVERRIDE "${_override}") +endif() + set(CMAKE_RC_FLAGS_INIT "$ENV{RCFLAGS} ${CMAKE_RC_FLAGS_INIT}") cmake_initialize_per_config_variable(CMAKE_RC_FLAGS "Flags for Windows Resource Compiler") diff --git a/Modules/CMakeSwiftInformation.cmake b/Modules/CMakeSwiftInformation.cmake index f6510b9..4f1d4f0 100644 --- a/Modules/CMakeSwiftInformation.cmake +++ b/Modules/CMakeSwiftInformation.cmake @@ -18,16 +18,25 @@ if(CMAKE_Swift_COMPILER_ID) endif() set(CMAKE_INCLUDE_FLAG_Swift "-I ") -if(NOT CMAKE_SYSTEM_NAME STREQUAL Windows AND NOT CMAKE_SYSTEM_NAME STREQUAL Darwin) +if(CMAKE_SYSTEM_NAME STREQUAL Darwin) + set(CMAKE_SHARED_LIBRARY_SONAME_Swift_FLAG "-Xlinker -install_name -Xlinker ") +elseif(NOT CMAKE_SYSTEM_NAME STREQUAL Windows) set(CMAKE_SHARED_LIBRARY_SONAME_Swift_FLAG "-Xlinker -soname -Xlinker ") endif() set(CMAKE_Swift_COMPILE_OPTIONS_TARGET "-target ") -set(CMAKE_Swift_COMPILER_ARG1 -frontend) +set(CMAKE_Swift_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN "-tools-directory ") +# NOTE(compnerd) the `-sdk` support is not yet ready in the compiler; when that +# is fully working, we should be able to enable this. +# set(CMAKE_Swift_COMPILE_OPTIONS_SYSROOT "-sdk ") +# NOTE(compnerd) do not setup `-frontend` as we use the compiler as the driver +# during the link phase and use that to drive the compilation +set(CMAKE_Swift_COMPILER_ARG1 "") set(CMAKE_Swift_DEFINE_FLAG -D) set(CMAKE_Swift_FRAMEWORK_SEARCH_FLAG "-F ") set(CMAKE_Swift_LIBRARY_PATH_FLAG "-L ") set(CMAKE_Swift_LIBRARY_PATH_TERMINATOR "") +set(CMAKE_Swift_LINK_LIBRARY_FLAG "-l") set(CMAKE_Swift_LINKER_WRAPPER_FLAG "-Xlinker" " ") set(CMAKE_Swift_RESPONSE_FILE_LINK_FLAG @) @@ -47,6 +56,8 @@ set(CMAKE_Swift_FLAGS_RELEASE_INIT "-O") set(CMAKE_Swift_FLAGS_RELWITHDEBINFO_INIT "-O -g") set(CMAKE_Swift_FLAGS_MINSIZEREL_INIT "-Osize") +cmake_initialize_per_config_variable(CMAKE_Swift_FLAGS "Swift Compiler Flags") + # NOTE(compnerd) we do not have an object compile rule since we build the objects as part of the link step if(NOT CMAKE_Swift_COMPILE_OBJECT) set(CMAKE_Swift_COMPILE_OBJECT ":") @@ -56,12 +67,12 @@ if(NOT CMAKE_Swift_NUM_THREADS MATCHES "^[0-9]+$") cmake_host_system_information(RESULT CMAKE_Swift_NUM_THREADS QUERY NUMBER_OF_LOGICAL_CORES) endif() +if(CMAKE_SYSTEM_NAME STREQUAL Windows) + set(CMAKE_Swift_IMPLIB_LINKER_FLAGS "-Xlinker -implib:<TARGET_IMPLIB>") +endif() + if(NOT CMAKE_Swift_CREATE_SHARED_LIBRARY) - if(CMAKE_Swift_COMPILER_TARGET) - set(CMAKE_Swift_CREATE_SHARED_LIBRARY "${CMAKE_Swift_COMPILER} -target <CMAKE_Swift_COMPILER_TARGET> -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-library -o <TARGET> -module-name <SWIFT_MODULE_NAME> -module-link-name <SWIFT_LIBRARY_NAME> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> <SONAME_FLAG> <TARGET_SONAME> <LINK_LIBRARIES>") - else() - set(CMAKE_Swift_CREATE_SHARED_LIBRARY "${CMAKE_Swift_COMPILER} -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-library -o <TARGET> -module-name <SWIFT_MODULE_NAME> -module-link-name <SWIFT_LIBRARY_NAME> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> <SONAME_FLAG> <TARGET_SONAME> <LINK_LIBRARIES>") - endif() + set(CMAKE_Swift_CREATE_SHARED_LIBRARY "<CMAKE_Swift_COMPILER> -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-library -o <TARGET> -module-name <SWIFT_MODULE_NAME> -module-link-name <SWIFT_LIBRARY_NAME> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> <SONAME_FLAG> <TARGET_SONAME> ${CMAKE_Swift_IMPLIB_LINKER_FLAGS} <LINK_LIBRARIES>") endif() if(NOT CMAKE_Swift_CREATE_SHARED_MODULE) @@ -69,19 +80,11 @@ if(NOT CMAKE_Swift_CREATE_SHARED_MODULE) endif() if(NOT CMAKE_Swift_LINK_EXECUTABLE) - if(CMAKE_Swift_COMPILER_TARGET) - set(CMAKE_Swift_LINK_EXECUTABLE "${CMAKE_Swift_COMPILER} -target <CMAKE_Swift_COMPILER_TARGET> -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-executable -o <TARGET> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> <LINK_LIBRARIES>") - else() - set(CMAKE_Swift_LINK_EXECUTABLE "${CMAKE_Swift_COMPILER} -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-executable -o <TARGET> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> <LINK_LIBRARIES>") - endif() + set(CMAKE_Swift_LINK_EXECUTABLE "<CMAKE_Swift_COMPILER> -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-executable -o <TARGET> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> ${CMAKE_Swift_IMPLIB_LINKER_FLAGS} <LINK_LIBRARIES>") endif() if(NOT CMAKE_Swift_CREATE_STATIC_LIBRARY) - if(CMAKE_Swift_COMPILER_TARGET) - set(CMAKE_Swift_CREATE_STATIC_LIBRARY "${CMAKE_Swift_COMPILER} -target <CMAKE_Swift_COMPILER_TARGET> -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-library -static -o <TARGET> -module-name <SWIFT_MODULE_NAME> -module-link-name <SWIFT_LIBRARY_NAME> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> <LINK_LIBRARIES>") - else() - set(CMAKE_Swift_CREATE_STATIC_LIBRARY "${CMAKE_Swift_COMPILER} -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-library -static -o <TARGET> -module-name <SWIFT_MODULE_NAME> -module-link-name <SWIFT_LIBRARY_NAME> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> <LINK_LIBRARIES>") - endif() + set(CMAKE_Swift_CREATE_STATIC_LIBRARY "<CMAKE_Swift_COMPILER> -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -num-threads ${CMAKE_Swift_NUM_THREADS} -emit-library -static -o <TARGET> -module-name <SWIFT_MODULE_NAME> -module-link-name <SWIFT_LIBRARY_NAME> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <DEFINES> <FLAGS> <INCLUDES> <SWIFT_SOURCES> <LINK_FLAGS> <LINK_LIBRARIES>") set(CMAKE_Swift_ARCHIVE_CREATE "<CMAKE_AR> crs <TARGET> <OBJECTS>") set(CMAKE_Swift_ARCHIVE_FINISH "") 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/Modules/CheckCXXSymbolExists.cmake b/Modules/CheckCXXSymbolExists.cmake index 2cccd09..5c9079d 100644 --- a/Modules/CheckCXXSymbolExists.cmake +++ b/Modules/CheckCXXSymbolExists.cmake @@ -5,26 +5,38 @@ CheckCXXSymbolExists -------------------- -Check if a symbol exists as a function, variable, or macro in C++ +Check if a symbol exists as a function, variable, or macro in ``C++``. -.. command:: CHECK_CXX_SYMBOL_EXISTS +.. command:: check_cxx_symbol_exists .. code-block:: cmake - CHECK_CXX_SYMBOL_EXISTS(<symbol> <files> <variable>) + 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``. + ``check_cxx_symbol_exists()`` can be used to check for symbols as seen by + the C++ compiler, as opposed to :command:`check_symbol_exists`, which always + uses the ``C`` compiler. If the header files define the symbol as a macro it is considered available and assumed to work. If the header files declare the symbol as a function or variable then the symbol must also be available for - linking. If the symbol is a type or enum value it will not be - recognized (consider using :module:`CheckTypeSize` - or :module:`CheckCXXSourceCompiles`). + linking. If the symbol is a type, enum value, or C++ template it will + not be recognized: consider using the :module:`CheckTypeSize` + or :module:`CheckCXXSourceCompiles` module instead. + +.. note:: + + This command is unreliable when ``<symbol>`` is (potentially) an overloaded + function. Since there is no reliable way to predict whether a given function + in the system environment may be defined as an overloaded function or may be + an overloaded function on other systems or will become so in the future, it + is generally advised to use the :module:`CheckCXXSourceCompiles` module for + checking any function symbol (unless somehow you surely know the checked + function is not overloaded on other systems or will not be so in the + future). The following variables may be set before calling this macro to modify the way the check is run: @@ -43,6 +55,17 @@ the way the check is run: command. See policy :policy:`CMP0075`. ``CMAKE_REQUIRED_QUIET`` execute quietly without messages. + +For example: + +.. code-block:: cmake + + include(CheckCXXSymbolExists) + + # Check for macro SEEK_SET + check_cxx_symbol_exists(SEEK_SET "cstdio" HAVE_SEEK_SET) + # Check for function std::fopen + check_cxx_symbol_exists(std::fopen "cstdio" HAVE_STD_FOPEN) #]=======================================================================] include_guard(GLOBAL) diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake index b9ef808..1053383 100644 --- a/Modules/CheckSymbolExists.cmake +++ b/Modules/CheckSymbolExists.cmake @@ -45,6 +45,17 @@ the way the check is run: command. See policy :policy:`CMP0075`. ``CMAKE_REQUIRED_QUIET`` execute quietly without messages. + +For example: + +.. code-block:: cmake + + include(CheckSymbolExists) + + # Check for macro SEEK_SET + check_symbol_exists(SEEK_SET "stdio.h" HAVE_SEEK_SET) + # Check for function fopen + check_symbol_exists(fopen "stdio.h" HAVE_FOPEN) #]=======================================================================] include_guard(GLOBAL) @@ -88,8 +99,28 @@ macro(__CHECK_SYMBOL_EXISTS_IMPL SOURCEFILE SYMBOL FILES VARIABLE) string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "#include <${FILE}>\n") endforeach() - string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT - "\nint main(int argc, char** argv)\n{\n (void)argv;\n#ifndef ${SYMBOL}\n return ((int*)(&${SYMBOL}))[argc];\n#else\n (void)argc;\n return 0;\n#endif\n}\n") + string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT " +int main(int argc, char** argv) +{ + (void)argv;") + set(_CSE_CHECK_NON_MACRO "return ((int*)(&${SYMBOL}))[argc];") + if("${SYMBOL}" MATCHES "^[a-zA-Z_][a-zA-Z0-9_]*$") + # The SYMBOL has a legal macro name. Test whether it exists as a macro. + string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT " +#ifndef ${SYMBOL} + ${_CSE_CHECK_NON_MACRO} +#else + (void)argc; + return 0; +#endif") + else() + # The SYMBOL cannot be a macro (e.g., a template function). + string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT " + ${_CSE_CHECK_NON_MACRO}") + endif() + string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT " +}") + unset(_CSE_CHECK_NON_MACRO) configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in" "${SOURCEFILE}" @ONLY) @@ -128,6 +159,7 @@ macro(__CHECK_SYMBOL_EXISTS_IMPL SOURCEFILE SYMBOL FILES VARIABLE) "${OUTPUT}\nFile ${SOURCEFILE}:\n" "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n") endif() + unset(CMAKE_CONFIGURABLE_FILE_CONTENT) endif() endmacro() diff --git a/Modules/Compiler/CrayPrgEnv.cmake b/Modules/Compiler/CrayPrgEnv.cmake index e55e587..f6e46ac 100644 --- a/Modules/Compiler/CrayPrgEnv.cmake +++ b/Modules/Compiler/CrayPrgEnv.cmake @@ -69,13 +69,27 @@ endfunction() # note that cmake applies both CMAKE_${lang}_FLAGS and CMAKE_EXE_LINKER_FLAGS # (in that order) to the linking command, so -dynamic can appear in either # variable. +# +# Note: As of CrayPE v19.06 (which translates to the craype/2.6.0 module) +# the default has changed and is now dynamic by default. This is handled +# accordingly function(__cmake_craype_linktype lang rv) # start with ENV, but allow flags to override - if("$ENV{CRAYPE_LINK_TYPE}" STREQUAL "dynamic") - set(linktype dynamic) + if(("$ENV{CRAYPE_VERSION}" STREQUAL "") OR + ("$ENV{CRAYPE_VERSION}" VERSION_LESS "2.6")) + if("$ENV{CRAYPE_LINK_TYPE}" STREQUAL "dynamic") + set(linktype dynamic) + else() + set(linktype static) + endif() else() - set(linktype static) + if("$ENV{CRAYPE_LINK_TYPE}" STREQUAL "static") + set(linktype static) + else() + set(linktype dynamic) + endif() endif() + # combine flags and convert to a list so we can apply the flags in order set(linkflags "${CMAKE_${lang}_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}") string(REPLACE " " ";" linkflags "${linkflags}") diff --git a/Modules/Compiler/GNU-CXX-FeatureTests.cmake b/Modules/Compiler/GNU-CXX-FeatureTests.cmake index d18adaf..45c5470 100644 --- a/Modules/Compiler/GNU-CXX-FeatureTests.cmake +++ b/Modules/Compiler/GNU-CXX-FeatureTests.cmake @@ -18,18 +18,18 @@ set(_cmake_feature_test_cxx_attribute_deprecated "${GNU49_CXX14}") set(_cmake_feature_test_cxx_decltype_auto "${GNU49_CXX14}") set(_cmake_feature_test_cxx_digit_separators "${GNU49_CXX14}") set(_cmake_feature_test_cxx_generic_lambdas "${GNU49_CXX14}") -set(_cmake_feature_test_cxx_lambda_init_captures "${GNU49_CXX14}") # GNU 4.3 supports binary literals as an extension, but may warn about # use of extensions prior to GNU 4.9 # http://stackoverflow.com/questions/16334024/difference-between-gcc-binary-literals-and-c14-ones set(_cmake_feature_test_cxx_binary_literals "${GNU49_CXX14}") -# The feature below is documented as available in GNU 4.8 (by implementing an +# The features below are documented as available in GNU 4.8 (by implementing an # earlier draft of the standard paper), but that version of the compiler # does not set __cplusplus to a value greater than 201103L until GNU 4.9: # http://gcc.gnu.org/onlinedocs/gcc-4.8.2/cpp/Standard-Predefined-Macros.html#Standard-Predefined-Macros # http://gcc.gnu.org/onlinedocs/gcc-4.9.0/cpp/Standard-Predefined-Macros.html#Standard-Predefined-Macros # So, CMake only reports availability for it with GNU 4.9 or later. set(_cmake_feature_test_cxx_return_type_deduction "${GNU49_CXX14}") +set(_cmake_feature_test_cxx_lambda_init_captures "${GNU49_CXX14}") # Introduced in GCC 4.8.1 set(GNU481_CXX11 "((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40801) && __cplusplus >= 201103L") diff --git a/Modules/Compiler/IAR-C.cmake b/Modules/Compiler/IAR-C.cmake index 18a4a75..e03ce3f 100644 --- a/Modules/Compiler/IAR-C.cmake +++ b/Modules/Compiler/IAR-C.cmake @@ -15,7 +15,7 @@ if(CMAKE_C_COMPILER_VERSION_INTERNAL VERSION_GREATER 7) set(CMAKE_C90_EXTENSION_COMPILE_OPTION --c89 -e) set(CMAKE_C99_STANDARD_COMPILE_OPTION "") set(CMAKE_C99_EXTENSION_COMPILE_OPTION -e) -elseif() +else() set(CMAKE_C90_STANDARD_COMPILE_OPTION "") set(CMAKE_C90_EXTENSION_COMPILE_OPTION -e) endif() diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake index c0ccb71..b59deda 100644 --- a/Modules/Compiler/NVIDIA-CUDA.cmake +++ b/Modules/Compiler/NVIDIA-CUDA.cmake @@ -1,3 +1,4 @@ +set(CMAKE_CUDA_COMPILER_HAS_DEVICE_LINK_PHASE True) set(CMAKE_CUDA_VERBOSE_FLAG "-v") set(CMAKE_CUDA_VERBOSE_COMPILE_FLAG "-Xcompiler=-v") diff --git a/Modules/Compiler/XL.cmake b/Modules/Compiler/XL.cmake index a9cec11..fc71ab4 100644 --- a/Modules/Compiler/XL.cmake +++ b/Modules/Compiler/XL.cmake @@ -18,6 +18,8 @@ macro(__compiler_xl lang) set(CMAKE_${lang}_RESPONSE_FILE_FLAG "-qoptfile=") set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "-qoptfile=") + set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-qmkshrobj") + set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,") set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",") diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 20b37d2..e55ed46 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -261,7 +261,9 @@ External Project Definition ``GIT_SUBMODULES <module>...`` Specific git submodules that should also be updated. If this option is - not provided, all git submodules will be updated. + not provided, all git submodules will be updated. When :policy:`CMP0097` + is set to ``NEW`` if this value is set to an empty string then no submodules + are initialized or updated. ``GIT_SHALLOW <bool>`` When this option is enabled, the ``git clone`` operation will be given @@ -1016,6 +1018,9 @@ function(_ep_parse_arguments f name ns args) endif() else() set(key "${arg}") + if(key MATCHES GIT) + get_property(have_key TARGET ${name} PROPERTY ${ns}${key} SET) + endif() endif() endforeach() endfunction() @@ -1060,7 +1065,7 @@ define_property(DIRECTORY PROPERTY "EP_UPDATE_DISCONNECTED" INHERITED "ExternalProject module." ) -function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git_repository git_tag git_remote_name git_submodules git_shallow git_progress git_config src_name work_dir gitclone_infofile gitclone_stampfile tls_verify) +function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git_repository git_tag git_remote_name init_submodules git_submodules git_shallow git_progress git_config src_name work_dir gitclone_infofile gitclone_stampfile tls_verify) if(NOT GIT_VERSION_STRING VERSION_LESS 1.8.5) # Use `git checkout <tree-ish> --` to avoid ambiguity with a local path. set(git_checkout_explicit-- "--") @@ -1074,7 +1079,7 @@ function(_ep_write_gitclone_script script_filename source_dir git_EXECUTABLE git message(FATAL_ERROR "Tag for git checkout should not be empty.") endif() - set(git_clone_options) + set(git_clone_options "--no-checkout") if(git_shallow) if(NOT GIT_VERSION_STRING VERSION_LESS 1.7.10) list(APPEND git_clone_options "--depth 1 --no-single-branch") @@ -1145,11 +1150,14 @@ if(error_code) message(FATAL_ERROR \"Failed to checkout tag: '${git_tag}'\") endif() -execute_process( - COMMAND \"${git_EXECUTABLE}\" ${git_options} submodule update --recursive --init ${git_submodules} - WORKING_DIRECTORY \"${work_dir}/${src_name}\" - RESULT_VARIABLE error_code - ) +set(init_submodules ${init_submodules}) +if(init_submodules) + execute_process( + COMMAND \"${git_EXECUTABLE}\" ${git_options} submodule update --recursive --init ${git_submodules} + WORKING_DIRECTORY \"${work_dir}/${src_name}\" + RESULT_VARIABLE error_code + ) +endif() if(error_code) message(FATAL_ERROR \"Failed to update submodules in: '${work_dir}/${src_name}'\") endif() @@ -1226,7 +1234,7 @@ endif() endfunction() -function(_ep_write_gitupdate_script script_filename git_EXECUTABLE git_tag git_remote_name git_submodules git_repository work_dir) +function(_ep_write_gitupdate_script script_filename git_EXECUTABLE git_tag git_remote_name init_submodules git_submodules git_repository work_dir) if("${git_tag}" STREQUAL "") message(FATAL_ERROR "Tag for git checkout should not be empty.") endif() @@ -1383,11 +1391,14 @@ if(error_code OR is_remote_ref OR NOT (\"\${tag_sha}\" STREQUAL \"\${head_sha}\" endif() endif() - execute_process( - COMMAND \"${git_EXECUTABLE}\" submodule update --recursive --init ${git_submodules} - WORKING_DIRECTORY \"${work_dir}/${src_name}\" - RESULT_VARIABLE error_code - ) + set(init_submodules ${init_submodules}) + if(init_submodules) + execute_process( + COMMAND \"${git_EXECUTABLE}\" submodule update --recursive --init ${git_submodules} + WORKING_DIRECTORY \"${work_dir}/${src_name}\" + RESULT_VARIABLE error_code + ) + endif() if(error_code) message(FATAL_ERROR \"Failed to update submodules in: '${work_dir}/${src_name}'\") endif() @@ -1972,7 +1983,7 @@ endif() set(stderr_log "${logbase}-err.log") endif() set(code " -cmake_minimum_required(VERSION 3.13) +cmake_minimum_required(VERSION 3.15) ${code_cygpath_make} set(command \"${command}\") set(log_merged \"${log_merged}\") @@ -2420,7 +2431,15 @@ function(_ep_add_download_command name) if(NOT git_tag) set(git_tag "master") endif() - get_property(git_submodules TARGET ${name} PROPERTY _EP_GIT_SUBMODULES) + + set(git_init_submodules TRUE) + get_property(git_submodules_set TARGET ${name} PROPERTY _EP_GIT_SUBMODULES SET) + if(git_submodules_set) + get_property(git_submodules TARGET ${name} PROPERTY _EP_GIT_SUBMODULES) + if(git_submodules STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW") + set(git_init_submodules FALSE) + endif() + endif() get_property(git_remote_name TARGET ${name} PROPERTY _EP_GIT_REMOTE_NAME) if(NOT git_remote_name) @@ -2458,7 +2477,7 @@ function(_ep_add_download_command name) # The script will delete the source directory and then call git clone. # _ep_write_gitclone_script(${tmp_dir}/${name}-gitclone.cmake ${source_dir} - ${GIT_EXECUTABLE} ${git_repository} ${git_tag} ${git_remote_name} "${git_submodules}" "${git_shallow}" "${git_progress}" "${git_config}" ${src_name} ${work_dir} + ${GIT_EXECUTABLE} ${git_repository} ${git_tag} ${git_remote_name} ${git_init_submodules} "${git_submodules}" "${git_shallow}" "${git_progress}" "${git_config}" ${src_name} ${work_dir} ${stamp_dir}/${name}-gitinfo.txt ${stamp_dir}/${name}-gitclone-lastrun.txt "${tls_verify}" ) set(comment "Performing download step (git clone) for '${name}'") @@ -2723,9 +2742,18 @@ function(_ep_add_update_command name) if(NOT git_remote_name) set(git_remote_name "origin") endif() - get_property(git_submodules TARGET ${name} PROPERTY _EP_GIT_SUBMODULES) + + set(git_init_submodules TRUE) + get_property(git_submodules_set TARGET ${name} PROPERTY _EP_GIT_SUBMODULES SET) + if(git_submodules_set) + get_property(git_submodules TARGET ${name} PROPERTY _EP_GIT_SUBMODULES) + if(git_submodules STREQUAL "" AND _EP_CMP0097 STREQUAL "NEW") + set(git_init_submodules FALSE) + endif() + endif() + _ep_write_gitupdate_script(${tmp_dir}/${name}-gitupdate.cmake - ${GIT_EXECUTABLE} ${git_tag} ${git_remote_name} "${git_submodules}" ${git_repository} ${work_dir} + ${GIT_EXECUTABLE} ${git_tag} ${git_remote_name} ${git_init_submodules} "${git_submodules}" ${git_repository} ${work_dir} ) set(cmd ${CMAKE_COMMAND} -P ${tmp_dir}/${name}-gitupdate.cmake) set(always 1) @@ -3138,6 +3166,10 @@ endfunction() function(ExternalProject_Add name) + cmake_policy(GET CMP0097 _EP_CMP0097 + PARENT_SCOPE # undocumented, do not use outside of CMake + ) + _ep_get_configuration_subdir_suffix(cfgdir) # Add a custom target for the external project. diff --git a/Modules/FindBZip2.cmake b/Modules/FindBZip2.cmake index 309b971..98ab72c 100644 --- a/Modules/FindBZip2.cmake +++ b/Modules/FindBZip2.cmake @@ -45,8 +45,8 @@ set(_BZIP2_PATHS PATHS find_path(BZIP2_INCLUDE_DIR bzlib.h ${_BZIP2_PATHS} PATH_SUFFIXES include) if (NOT BZIP2_LIBRARIES) - find_library(BZIP2_LIBRARY_RELEASE NAMES bz2 bzip2 ${_BZIP2_PATHS} PATH_SUFFIXES lib) - find_library(BZIP2_LIBRARY_DEBUG NAMES bz2d bzip2d ${_BZIP2_PATHS} PATH_SUFFIXES lib) + find_library(BZIP2_LIBRARY_RELEASE NAMES bz2 bzip2 libbz2 libbzip2 ${_BZIP2_PATHS} PATH_SUFFIXES lib) + find_library(BZIP2_LIBRARY_DEBUG NAMES bz2d bzip2d libbz2d libbzip2d ${_BZIP2_PATHS} PATH_SUFFIXES lib) include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) SELECT_LIBRARY_CONFIGURATIONS(BZIP2) diff --git a/Modules/FindBacktrace.cmake b/Modules/FindBacktrace.cmake index cf1632a..3d8ce88 100644 --- a/Modules/FindBacktrace.cmake +++ b/Modules/FindBacktrace.cmake @@ -74,7 +74,7 @@ else() if(Backtrace_INCLUDE_DIR) # OpenBSD has libbacktrace renamed to libexecinfo find_library(Backtrace_LIBRARY "execinfo") - elseif() # respect user wishes + else() # respect user wishes set(_Backtrace_HEADER_TRY "backtrace.h") find_path(Backtrace_INCLUDE_DIR ${_Backtrace_HEADER_TRY}) find_library(Backtrace_LIBRARY "backtrace") diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake index 25dd397..1f9477b 100644 --- a/Modules/FindBoost.cmake +++ b/Modules/FindBoost.cmake @@ -1981,7 +1981,8 @@ foreach(COMPONENT ${Boost_FIND_COMPONENTS}) endif() else() set(Boost_${UPPERCOMPONENT}_HEADER ON) - message(WARNING "No header defined for ${COMPONENT}; skipping header check") + message(WARNING "No header defined for ${COMPONENT}; skipping header check " + "(note: header-only libraries have no designated component)") endif() # diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake index 3315505..b6859aa 100644 --- a/Modules/FindCUDA.cmake +++ b/Modules/FindCUDA.cmake @@ -375,6 +375,11 @@ The script defines the following variables:: CUDA_nvcuvid_LIBRARY -- CUDA Video Decoder library. Only available for CUDA version 3.2+. Windows only. + CUDA_nvToolsExt_LIBRARY + -- NVIDA CUDA Tools Extension library. + Available for CUDA version 5+. + CUDA_OpenCL_LIBRARY -- NVIDA CUDA OpenCL library. + Available for CUDA version 5+. #]=======================================================================] @@ -642,6 +647,8 @@ macro(cuda_unset_include_and_libraries) unset(CUDA_npps_LIBRARY CACHE) unset(CUDA_nvcuvenc_LIBRARY CACHE) unset(CUDA_nvcuvid_LIBRARY CACHE) + unset(CUDA_nvToolsExt_LIBRARY CACHE) + unset(CUDA_OpenCL_LIBRARY CACHE) unset(CUDA_GPU_DETECT_OUTPUT CACHE) endmacro() @@ -973,6 +980,11 @@ if(CUDA_VERSION VERSION_GREATER "5.0" AND CUDA_VERSION VERSION_LESS "9.2") find_cuda_helper_libs(cublas_device) endif() +if(NOT CUDA_VERSION VERSION_LESS "5.0") + find_cuda_helper_libs(nvToolsExt) + find_cuda_helper_libs(OpenCL) +endif() + if(NOT CUDA_VERSION VERSION_LESS "9.0") # In CUDA 9.0 NPP was nppi was removed find_cuda_helper_libs(nppc) diff --git a/Modules/FindCUDA/run_nvcc.cmake b/Modules/FindCUDA/run_nvcc.cmake index 6fc2439..af15d55 100644 --- a/Modules/FindCUDA/run_nvcc.cmake +++ b/Modules/FindCUDA/run_nvcc.cmake @@ -75,7 +75,8 @@ set(CUDA_NVCC_EXECUTABLE "@CUDA_NVCC_EXECUTABLE@") # path set(CUDA_NVCC_FLAGS @CUDA_NVCC_FLAGS@ ;; @CUDA_WRAP_OPTION_NVCC_FLAGS@) # list @CUDA_NVCC_FLAGS_CONFIG@ set(nvcc_flags @nvcc_flags@) # list -set(CUDA_NVCC_INCLUDE_DIRS "@CUDA_NVCC_INCLUDE_DIRS@") # list (needs to be in quotes to handle spaces properly). +set(CUDA_NVCC_INCLUDE_DIRS [==[@CUDA_NVCC_INCLUDE_DIRS@]==]) # list (needs to be in lua quotes to address backslashes) +string(REPLACE "\\" "/" CUDA_NVCC_INCLUDE_DIRS "${CUDA_NVCC_INCLUDE_DIRS}") set(CUDA_NVCC_COMPILE_DEFINITIONS [==[@CUDA_NVCC_COMPILE_DEFINITIONS@]==]) # list (needs to be in lua quotes see #16510 ). set(format_flag "@format_flag@") # string set(cuda_language_flag @cuda_language_flag@) # list diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index c9c3cce..844d36d 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -173,11 +173,15 @@ if(_libraries_work) #message("DEBUG: ${LIBRARIES} = ${${LIBRARIES}}") endif() -if(_libraries_work) - set(${LIBRARIES} ${${LIBRARIES}} ${_blas} ${_threads}) -else() - set(${LIBRARIES} FALSE) -endif() + if(_libraries_work) + if("${_list}" STREQUAL "") + set(${LIBRARIES} "${LIBRARIES}-PLACEHOLDER-FOR-EMPTY-LIBRARIES") + else() + set(${LIBRARIES} ${${LIBRARIES}} ${_blas} ${_threads}) + endif() + else() + set(${LIBRARIES} FALSE) + endif() endmacro() @@ -206,6 +210,7 @@ if(BLAS_FOUND) #intel lapack if (BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") + if(NOT LAPACK_LIBRARIES) if (NOT WIN32) set(LAPACK_mkl_LM "-lm") set(LAPACK_mkl_LDL "-ldl") @@ -280,6 +285,7 @@ if (BLA_VENDOR MATCHES "Intel" OR BLA_VENDOR STREQUAL "All") unset(LAPACK_mkl_LM) unset(LAPACK_mkl_LDL) endif () + endif() endif() if (BLA_VENDOR STREQUAL "Goto" OR BLA_VENDOR STREQUAL "All") @@ -426,5 +432,11 @@ else() endif() endif() +# On compilers that implicitly link LAPACK (such as ftn, cc, and CC on Cray HPC machines) +# we used a placeholder for empty LAPACK_LIBRARIES to get through our logic above. +if (LAPACK_LIBRARIES STREQUAL "LAPACK_LIBRARIES-PLACEHOLDER-FOR-EMPTY-LIBRARIES") + set(LAPACK_LIBRARIES "") +endif() + cmake_pop_check_state() set(CMAKE_FIND_LIBRARY_SUFFIXES ${_lapack_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) diff --git a/Modules/FindLibLZMA.cmake b/Modules/FindLibLZMA.cmake index fc97655..200d6bf 100644 --- a/Modules/FindLibLZMA.cmake +++ b/Modules/FindLibLZMA.cmake @@ -42,7 +42,14 @@ This module will set the following variables in your project: #]=======================================================================] find_path(LIBLZMA_INCLUDE_DIR lzma.h ) -find_library(LIBLZMA_LIBRARY NAMES lzma liblzma) +if(NOT LIBLZMA_LIBRARY) + find_library(LIBLZMA_LIBRARY_RELEASE NAMES lzma liblzma PATH_SUFFIXES lib) + find_library(LIBLZMA_LIBRARY_DEBUG NAMES lzmad liblzmad PATH_SUFFIXES lib) + include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) + select_library_configurations(LIBLZMA) +else() + file(TO_CMAKE_PATH "${LIBLZMA_LIBRARY}" LIBLZMA_LIBRARY) +endif() if(LIBLZMA_INCLUDE_DIR AND EXISTS "${LIBLZMA_INCLUDE_DIR}/lzma/version.h") file(STRINGS "${LIBLZMA_INCLUDE_DIR}/lzma/version.h" LIBLZMA_HEADER_CONTENTS REGEX "#define LZMA_VERSION_[A-Z]+ [0-9]+") @@ -62,9 +69,17 @@ if (LIBLZMA_LIBRARY) include(${CMAKE_CURRENT_LIST_DIR}/CheckLibraryExists.cmake) set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET}) set(CMAKE_REQUIRED_QUIET ${LibLZMA_FIND_QUIETLY}) - CHECK_LIBRARY_EXISTS(${LIBLZMA_LIBRARY} lzma_auto_decoder "" LIBLZMA_HAS_AUTO_DECODER) - CHECK_LIBRARY_EXISTS(${LIBLZMA_LIBRARY} lzma_easy_encoder "" LIBLZMA_HAS_EASY_ENCODER) - CHECK_LIBRARY_EXISTS(${LIBLZMA_LIBRARY} lzma_lzma_preset "" LIBLZMA_HAS_LZMA_PRESET) + if(NOT LIBLZMA_LIBRARY_RELEASE AND NOT LIBLZMA_LIBRARY_DEBUG) + set(LIBLZMA_LIBRARY_check ${LIBLZMA_LIBRARY}) + elseif(LIBLZMA_LIBRARY_RELEASE) + set(LIBLZMA_LIBRARY_check ${LIBLZMA_LIBRARY_RELEASE}) + elseif(LIBLZMA_LIBRARY_DEBUG) + set(LIBLZMA_LIBRARY_check ${LIBLZMA_LIBRARY_DEBUG}) + endif() + CHECK_LIBRARY_EXISTS(${LIBLZMA_LIBRARY_check} lzma_auto_decoder "" LIBLZMA_HAS_AUTO_DECODER) + CHECK_LIBRARY_EXISTS(${LIBLZMA_LIBRARY_check} lzma_easy_encoder "" LIBLZMA_HAS_EASY_ENCODER) + CHECK_LIBRARY_EXISTS(${LIBLZMA_LIBRARY_check} lzma_lzma_preset "" LIBLZMA_HAS_LZMA_PRESET) + unset(LIBLZMA_LIBRARY_check) set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_SAVE}) endif () @@ -85,7 +100,25 @@ if (LIBLZMA_FOUND) add_library(LibLZMA::LibLZMA UNKNOWN IMPORTED) set_target_properties(LibLZMA::LibLZMA PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${LIBLZMA_INCLUDE_DIR} - IMPORTED_LINK_INTERFACE_LANGUAGES C - IMPORTED_LOCATION ${LIBLZMA_LIBRARY}) + IMPORTED_LINK_INTERFACE_LANGUAGES C) + + if(LIBLZMA_LIBRARY_RELEASE) + set_property(TARGET LibLZMA::LibLZMA APPEND PROPERTY + IMPORTED_CONFIGURATIONS RELEASE) + set_target_properties(LibLZMA::LibLZMA PROPERTIES + IMPORTED_LOCATION_RELEASE "${LIBLZMA_LIBRARY_RELEASE}") + endif() + + if(LIBLZMA_LIBRARY_DEBUG) + set_property(TARGET LibLZMA::LibLZMA APPEND PROPERTY + IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(LibLZMA::LibLZMA PROPERTIES + IMPORTED_LOCATION_DEBUG "${LIBLZMA_LIBRARY_DEBUG}") + endif() + + if(NOT LIBLZMA_LIBRARY_RELEASE AND NOT LIBLZMA_LIBRARY_DEBUG) + set_target_properties(LibLZMA::LibLZMA PROPERTIES + IMPORTED_LOCATION "${LIBLZMA_LIBRARY}") + endif() endif() endif () diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index 9471be8..2779032 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -310,11 +310,15 @@ foreach (LANG IN ITEMS C CXX Fortran) set(_MPI_${LANG}_COMPILER_NAMES "") foreach (id IN ITEMS GNU Intel MSVC PGI XL) if (NOT CMAKE_${LANG}_COMPILER_ID OR CMAKE_${LANG}_COMPILER_ID STREQUAL id) - list(APPEND _MPI_${LANG}_COMPILER_NAMES ${_MPI_${id}_${LANG}_COMPILER_NAMES}${MPI_EXECUTABLE_SUFFIX}) + foreach(_COMPILER_NAME IN LISTS _MPI_${id}_${LANG}_COMPILER_NAMES) + list(APPEND _MPI_${LANG}_COMPILER_NAMES ${_COMPILER_NAME}${MPI_EXECUTABLE_SUFFIX}) + endforeach() endif() unset(_MPI_${id}_${LANG}_COMPILER_NAMES) endforeach() - list(APPEND _MPI_${LANG}_COMPILER_NAMES ${_MPI_${LANG}_GENERIC_COMPILER_NAMES}${MPI_EXECUTABLE_SUFFIX}) + foreach(_COMPILER_NAME IN LISTS _MPI_${LANG}_GENERIC_COMPILER_NAMES) + list(APPEND _MPI_${LANG}_COMPILER_NAMES ${_COMPILER_NAME}${MPI_EXECUTABLE_SUFFIX}) + endforeach() unset(_MPI_${LANG}_GENERIC_COMPILER_NAMES) endforeach() @@ -1698,7 +1702,7 @@ foreach(LANG IN ITEMS C CXX Fortran) set(MPI_${LANG}_INCLUDE_PATH "${MPI_${LANG}_INCLUDE_DIRS}") unset(MPI_${LANG}_COMPILE_FLAGS) if(MPI_${LANG}_COMPILE_OPTIONS) - list(JOIN MPI_${LANG}_COMPILE_FLAGS " " MPI_${LANG}_COMPILE_OPTIONS) + list(JOIN MPI_${LANG}_COMPILE_OPTIONS " " MPI_${LANG}_COMPILE_FLAGS) endif() if(MPI_${LANG}_COMPILE_DEFINITIONS) foreach(_MPI_DEF IN LISTS MPI_${LANG}_COMPILE_DEFINITIONS) diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake index 3547642..c8cae2e 100644 --- a/Modules/FindMatlab.cmake +++ b/Modules/FindMatlab.cmake @@ -224,6 +224,9 @@ Reference this list. #]=======================================================================] +cmake_policy(PUSH) +cmake_policy(SET CMP0057 NEW) # if IN_LIST + set(_FindMatlab_SELF_DIR "${CMAKE_CURRENT_LIST_DIR}") include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) @@ -395,7 +398,7 @@ function(matlab_extract_all_installed_versions_from_registry win64 matlab_versio ) - if(${resultMatlab} EQUAL 0) + if(resultMatlab EQUAL 0) string( REGEX MATCHALL "MATLAB\\\\([0-9]+(\\.[0-9]+)?)" @@ -606,15 +609,25 @@ function(matlab_get_mex_suffix matlab_root mex_suffix) set(devnull INPUT_FILE NUL) endif() + if(WIN32) + # this environment variable is used to determine the arch on Windows + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(ENV{MATLAB_ARCH} "win64") + else() + set(ENV{MATLAB_ARCH} "win32") + endif() + endif() + # this is the preferred way. If this does not work properly (eg. MCR on Windows), then we use our own knowledge execute_process( COMMAND ${Matlab_MEXEXTENSIONS_PROG} OUTPUT_VARIABLE _matlab_mex_extension - #RESULT_VARIABLE _matlab_mex_extension_call ERROR_VARIABLE _matlab_mex_extension_error + OUTPUT_STRIP_TRAILING_WHITESPACE ${devnull}) + unset(ENV{MATLAB_ARCH}) - if(NOT "${_matlab_mex_extension_error}" STREQUAL "") + if(_matlab_mex_extension_error) if(WIN32) # this is only for intel architecture if(CMAKE_SIZEOF_VOID_P EQUAL 8) @@ -627,7 +640,7 @@ function(matlab_get_mex_suffix matlab_root mex_suffix) string(STRIP "${_matlab_mex_extension}" _matlab_mex_extension) if(MATLAB_FIND_DEBUG) - message(STATUS "[MATLAB] '${Matlab_MEXEXTENSIONS_PROG}' : returned '${_matlab_mex_extension_call}', determined extension '${_matlab_mex_extension}' and error string is '${_matlab_mex_extension_error}'") + message(STATUS "[MATLAB] '${Matlab_MEXEXTENSIONS_PROG}' : determined extension '${_matlab_mex_extension}' and error string is '${_matlab_mex_extension_error}'") endif() unset(Matlab_MEXEXTENSIONS_PROG CACHE) @@ -700,7 +713,7 @@ function(matlab_get_version_from_matlab_run matlab_binary_program matlab_list_ve ${devnull} ) - if("${_matlab_result_version_call}" MATCHES "timeout") + if(_matlab_result_version_call MATCHES "timeout") if(MATLAB_FIND_DEBUG) message(WARNING "[MATLAB] Unable to determine the version of Matlab." " Matlab call timed out after 120 seconds.") @@ -885,6 +898,7 @@ endfunction() [DOCUMENTATION file.txt] [LINK_TO target1 target2 ...] [R2017b | R2018a] + [EXCLUDE_FROM_ALL] [...] ) @@ -914,6 +928,10 @@ endfunction() ``MODULE`` or ``SHARED`` may be given to specify the type of library to be created. ``EXECUTABLE`` may be given to create an executable instead of a library. If no type is given explicitly, the type is ``SHARED``. + ``EXCLUDE_FROM_ALL`` + This option has the same meaning as for :prop_tgt:`EXCLUDE_FROM_ALL` and + is forwarded to :command:`add_library` or :command:`add_executable` + commands. The documentation file is not processed and should be in the following format: @@ -940,7 +958,7 @@ function(matlab_add_mex) endif() - set(options EXECUTABLE MODULE SHARED R2017b R2018a) + set(options EXECUTABLE MODULE SHARED R2017b R2018a EXCLUDE_FROM_ALL) set(oneValueArgs NAME DOCUMENTATION OUTPUT_NAME) set(multiValueArgs LINK_TO SRC) @@ -955,14 +973,14 @@ function(matlab_add_mex) set(${prefix}_OUTPUT_NAME ${${prefix}_NAME}) endif() - if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, add version source file + if(NOT Matlab_VERSION_STRING VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, add version source file # TODO: check the file extensions in ${${prefix}_SRC} to see if they're C or C++ files # Currently, the C and C++ versions of the version files are identical, so this doesn't matter. set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/c_mexapi_version.c") #set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/cpp_mexapi_version.cpp") endif() - if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.4") # For 9.4 (R2018a) and newer, add API macro + if(NOT Matlab_VERSION_STRING VERSION_LESS "9.4") # For 9.4 (R2018a) and newer, add API macro if(${${prefix}_R2018a}) set(MEX_API_MACRO "MATLAB_DEFAULT_RELEASE=R2018a") else() @@ -970,8 +988,14 @@ function(matlab_add_mex) endif() endif() + set(_option_EXCLUDE_FROM_ALL) + if(${prefix}_EXCLUDE_FROM_ALL) + set(_option_EXCLUDE_FROM_ALL "EXCLUDE_FROM_ALL") + endif() + if(${prefix}_EXECUTABLE) add_executable(${${prefix}_NAME} + ${_option_EXCLUDE_FROM_ALL} ${${prefix}_SRC} ${MEX_VERSION_FILE} ${${prefix}_DOCUMENTATION} @@ -985,6 +1009,7 @@ function(matlab_add_mex) add_library(${${prefix}_NAME} ${type} + ${_option_EXCLUDE_FROM_ALL} ${${prefix}_SRC} ${MEX_VERSION_FILE} ${${prefix}_DOCUMENTATION} @@ -1023,18 +1048,13 @@ function(matlab_add_mex) if (MSVC) set(_link_flags "${_link_flags} /EXPORT:mexFunction") - if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, export version + if(NOT Matlab_VERSION_STRING VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, export version set(_link_flags "${_link_flags} /EXPORT:mexfilerequiredapiversion") endif() - if(Matlab_HAS_CPP_API) - set(_link_flags "${_link_flags} /EXPORT:mexCreateMexFunction /EXPORT:mexDestroyMexFunction /EXPORT:mexFunctionAdapter") - #TODO: Is this necessary? - endif() - set_property(TARGET ${${prefix}_NAME} APPEND PROPERTY LINK_FLAGS ${_link_flags}) - endif() # TODO: what if there's a different compiler on Windows? + endif() # No other compiler currently supported on Windows. set_target_properties(${${prefix}_NAME} PROPERTIES @@ -1042,18 +1062,18 @@ function(matlab_add_mex) else() - if(${Matlab_VERSION_STRING} VERSION_LESS "9.1") # For versions prior to 9.1 (R2016b) + if(Matlab_VERSION_STRING VERSION_LESS "9.1") # For versions prior to 9.1 (R2016b) set(_ver_map_files ${Matlab_EXTERN_LIBRARY_DIR}/mexFunction.map) else() # For 9.1 (R2016b) and newer set(_ver_map_files ${Matlab_EXTERN_LIBRARY_DIR}/c_exportsmexfileversion.map) endif() - if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.5") # For 9.5 (R2018b) (and newer?) + if(NOT Matlab_VERSION_STRING VERSION_LESS "9.5") # For 9.5 (R2018b) (and newer?) target_compile_options(${${prefix}_NAME} PRIVATE "-fvisibility=default") # This one is weird, it might be a bug in <mex.h> for R2018b. When compiling with # -fvisibility=hidden, the symbol `mexFunction` cannot be exported. Reading the # source code for <mex.h>, it seems that the preprocessor macro `MW_NEEDS_VERSION_H` - # needs to be defined for `__attribute__ ((visibility("default")))` to be added + # needs to be defined for `__attribute__((visibility("default")))` to be added # in front of the declaration of `mexFunction`. In previous versions of MATLAB this # was not the case, there `DLL_EXPORT_SYM` needed to be defined. # Adding `-fvisibility=hidden` to the `mex` command causes the build to fail. @@ -1089,11 +1109,13 @@ function(matlab_add_mex) set(_link_flags "${_link_flags} -Wl,${_export_flag_name},${_file}") endforeach() + # The `mex` command doesn't add this define. It is specified here in order + # to export the symbol in case the client code decides to hide its symbols set_target_properties(${${prefix}_NAME} PROPERTIES - DEFINE_SYMBOL "DLL_EXPORT_SYM=__attribute__ ((visibility (\"default\")))" + DEFINE_SYMBOL "DLL_EXPORT_SYM=__attribute__((visibility(\"default\")))" LINK_FLAGS "${_link_flags}" - ) # The `mex` command doesn't add this define. Is it necessary? + ) endif() @@ -1112,14 +1134,14 @@ function(_Matlab_get_version_from_root matlab_root matlab_or_mcr matlab_known_ve # set(Matlab_PROG_VERSION_STRING_AUTO_DETECT "" CACHE INTERNAL "internal matlab location for the discovered version") #endif() - if(NOT ${matlab_known_version} STREQUAL "NOTFOUND") + if(NOT matlab_known_version STREQUAL "NOTFOUND") # the version is known, we just return it set(${matlab_final_version} ${matlab_known_version} PARENT_SCOPE) set(Matlab_VERSION_STRING_INTERNAL ${matlab_known_version} CACHE INTERNAL "Matlab version (automatically determined)" FORCE) return() endif() - if("${matlab_or_mcr}" STREQUAL "UNKNOWN") + if(matlab_or_mcr STREQUAL "UNKNOWN") if(MATLAB_FIND_DEBUG) message(WARNING "[MATLAB] Determining Matlab or MCR") endif() @@ -1134,10 +1156,10 @@ function(_Matlab_get_version_from_root matlab_root matlab_or_mcr matlab_known_ve # default fallback to Matlab set(matlab_or_mcr "MATLAB") - if(NOT "${CMAKE_MATCH_1}" STREQUAL "") + if(NOT CMAKE_MATCH_1 STREQUAL "") string(TOLOWER "${CMAKE_MATCH_1}" product_reg_match) - if("${product_reg_match}" STREQUAL "matlab runtime") + if(product_reg_match STREQUAL "matlab runtime") set(matlab_or_mcr "MCR") endif() endif() @@ -1151,7 +1173,7 @@ function(_Matlab_get_version_from_root matlab_root matlab_or_mcr matlab_known_ve # UNKNOWN is the default behaviour in case we # - have an erroneous matlab_root # - have an initial 'UNKNOWN' - if("${matlab_or_mcr}" STREQUAL "MATLAB" OR "${matlab_or_mcr}" STREQUAL "UNKNOWN") + if(matlab_or_mcr STREQUAL "MATLAB" OR matlab_or_mcr STREQUAL "UNKNOWN") # MATLAB versions set(_matlab_current_program ${Matlab_MAIN_PROGRAM}) @@ -1203,7 +1225,7 @@ function(_Matlab_get_version_from_root matlab_root matlab_or_mcr matlab_known_ve matlab_get_version_from_matlab_run("${Matlab_PROG_VERSION_STRING_AUTO_DETECT}" matlab_list_of_all_versions) list(LENGTH matlab_list_of_all_versions list_of_all_versions_length) - if(${list_of_all_versions_length} GREATER 0) + if(list_of_all_versions_length GREATER 0) list(GET matlab_list_of_all_versions 0 _matlab_version_tmp) else() set(_matlab_version_tmp "unknown") @@ -1213,7 +1235,7 @@ function(_Matlab_get_version_from_root matlab_root matlab_or_mcr matlab_known_ve set(Matlab_VERSION_STRING_INTERNAL ${_matlab_version_tmp} CACHE INTERNAL "Matlab version (automatically determined)" FORCE) # warning, just in case several versions found (should not happen) - if((${list_of_all_versions_length} GREATER 1) AND MATLAB_FIND_DEBUG) + if((list_of_all_versions_length GREATER 1) AND MATLAB_FIND_DEBUG) message(WARNING "[MATLAB] Found several versions, taking the first one (versions found ${matlab_list_of_all_versions})") endif() @@ -1233,10 +1255,8 @@ function(_Matlab_get_version_from_root matlab_root matlab_or_mcr matlab_known_ve ${versioninfo_string} ) - if(NOT "${version_reg_match}" STREQUAL "") - if("${CMAKE_MATCH_1}" MATCHES "(([0-9])\\.([0-9]))[\\.0-9]*") - set(_matlab_version_tmp "${CMAKE_MATCH_1}") - endif() + if(CMAKE_MATCH_1 MATCHES "(([0-9])\\.([0-9]))[\\.0-9]*") + set(_matlab_version_tmp "${CMAKE_MATCH_1}") endif() endif() set(${matlab_final_version} "${_matlab_version_tmp}" PARENT_SCOPE) @@ -1442,14 +1462,28 @@ list(LENGTH _matlab_possible_roots _numbers_of_matlab_roots) set(Matlab_VERSION_STRING "NOTFOUND") set(Matlab_Or_MCR "UNKNOWN") if(_numbers_of_matlab_roots GREATER 0) - list(GET _matlab_possible_roots 0 Matlab_Or_MCR) - list(GET _matlab_possible_roots 1 Matlab_VERSION_STRING) - list(GET _matlab_possible_roots 2 Matlab_ROOT_DIR) - - # adding a warning in case of ambiguity - if(_numbers_of_matlab_roots GREATER 3 AND MATLAB_FIND_DEBUG) - message(WARNING "[MATLAB] Found several distributions of Matlab. Setting the current version to ${Matlab_VERSION_STRING} (located ${Matlab_ROOT_DIR})." - " If this is not the desired behaviour, provide the -DMatlab_ROOT_DIR=... on the command line") + if(Matlab_FIND_VERSION_EXACT) + list(FIND _matlab_possible_roots ${Matlab_FIND_VERSION} _list_index) + if(_list_index LESS 0) + set(_list_index 1) + endif() + + math(EXPR _matlab_or_mcr_index "${_list_index} - 1") + math(EXPR _matlab_root_dir_index "${_list_index} + 1") + + list(GET _matlab_possible_roots ${_matlab_or_mcr_index} Matlab_Or_MCR) + list(GET _matlab_possible_roots ${_list_index} Matlab_VERSION_STRING) + list(GET _matlab_possible_roots ${_matlab_root_dir_index} Matlab_ROOT_DIR) + else() + list(GET _matlab_possible_roots 0 Matlab_Or_MCR) + list(GET _matlab_possible_roots 1 Matlab_VERSION_STRING) + list(GET _matlab_possible_roots 2 Matlab_ROOT_DIR) + + # adding a warning in case of ambiguity + if(_numbers_of_matlab_roots GREATER 3 AND MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Found several distributions of Matlab. Setting the current version to ${Matlab_VERSION_STRING} (located ${Matlab_ROOT_DIR})." + " If this is not the desired behaviour, use the EXACT keyword or provide the -DMatlab_ROOT_DIR=... on the command line") + endif() endif() endif() @@ -1503,7 +1537,9 @@ if(MATLAB_FIND_DEBUG) message(STATUS "[MATLAB] Current version is ${Matlab_VERSION_STRING} located ${Matlab_ROOT_DIR}") endif() -if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.4") # MATLAB 9.4 (R2018a) and newer have a new C++ API +# MATLAB 9.4 (R2018a) and newer have a new C++ API +# This API pulls additional required libraries. +if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.4") set(Matlab_HAS_CPP_API 1) endif() @@ -1589,6 +1625,10 @@ endfunction() set(_matlab_required_variables) +# Order is as follow: +# - unconditionally required libraries/headers first +# - then library components +# - then program components # the MEX library/header are required find_path( @@ -1614,38 +1654,6 @@ list(APPEND _matlab_required_variables Matlab_MEX_EXTENSION) # the matlab root is required list(APPEND _matlab_required_variables Matlab_ROOT_DIR) -# component Mex Compiler -list(FIND Matlab_FIND_COMPONENTS MEX_COMPILER _matlab_find_mex_compiler) -if(_matlab_find_mex_compiler GREATER -1) - find_program( - Matlab_MEX_COMPILER - "mex" - PATHS ${Matlab_BINARIES_DIR} - DOC "Matlab MEX compiler" - NO_DEFAULT_PATH - ) - if(Matlab_MEX_COMPILER) - set(Matlab_MEX_COMPILER_FOUND TRUE) - endif() -endif() -unset(_matlab_find_mex_compiler) - -# component Matlab program -list(FIND Matlab_FIND_COMPONENTS MAIN_PROGRAM _matlab_find_matlab_program) -if(_matlab_find_matlab_program GREATER -1) - find_program( - Matlab_MAIN_PROGRAM - matlab - PATHS ${Matlab_ROOT_DIR} ${Matlab_ROOT_DIR}/bin - DOC "Matlab main program" - NO_DEFAULT_PATH - ) - if(Matlab_MAIN_PROGRAM) - set(Matlab_MAIN_PROGRAM_FOUND TRUE) - endif() -endif() -unset(_matlab_find_matlab_program) - # The MX library is required _Matlab_find_library( ${_matlab_lib_prefix_for_search} @@ -1659,9 +1667,40 @@ if(Matlab_MX_LIBRARY) set(Matlab_MX_LIBRARY_FOUND TRUE) endif() +if(Matlab_HAS_CPP_API) + + # The MatlabEngine library is required for R2018a+ + _Matlab_find_library( + ${_matlab_lib_prefix_for_search} + Matlab_ENGINE_LIBRARY + MatlabEngine + PATHS ${_matlab_lib_dir_for_search} + DOC "MatlabEngine Library" + NO_DEFAULT_PATH + ) + list(APPEND _matlab_required_variables Matlab_ENGINE_LIBRARY) + if(Matlab_ENGINE_LIBRARY) + set(Matlab_ENGINE_LIBRARY_FOUND TRUE) + endif() + + # The MatlabDataArray library is required for R2018a+ + _Matlab_find_library( + ${_matlab_lib_prefix_for_search} + Matlab_DATAARRAY_LIBRARY + MatlabDataArray + PATHS ${_matlab_lib_dir_for_search} + DOC "MatlabDataArray Library" + NO_DEFAULT_PATH + ) + list(APPEND _matlab_required_variables Matlab_DATAARRAY_LIBRARY) + if(Matlab_DATAARRAY_LIBRARY) + set(Matlab_DATAARRAY_LIBRARY_FOUND TRUE) + endif() + +endif() + # Component ENG library -list(FIND Matlab_FIND_COMPONENTS ENG_LIBRARY _matlab_find_eng) -if(_matlab_find_eng GREATER -1) +if("ENG_LIBRARY" IN_LIST Matlab_FIND_COMPONENTS) _Matlab_find_library( ${_matlab_lib_prefix_for_search} Matlab_ENG_LIBRARY @@ -1673,11 +1712,9 @@ if(_matlab_find_eng GREATER -1) set(Matlab_ENG_LIBRARY_FOUND TRUE) endif() endif() -unset(_matlab_find_eng) # Component MAT library -list(FIND Matlab_FIND_COMPONENTS MAT_LIBRARY _matlab_find_mat) -if(_matlab_find_mat GREATER -1) +if("MAT_LIBRARY" IN_LIST Matlab_FIND_COMPONENTS) _Matlab_find_library( ${_matlab_lib_prefix_for_search} Matlab_MAT_LIBRARY @@ -1689,11 +1726,9 @@ if(_matlab_find_mat GREATER -1) set(Matlab_MAT_LIBRARY_FOUND TRUE) endif() endif() -unset(_matlab_find_mat) # Component Simulink -list(FIND Matlab_FIND_COMPONENTS SIMULINK _matlab_find_simulink) -if(_matlab_find_simulink GREATER -1) +if("SIMULINK" IN_LIST Matlab_FIND_COMPONENTS) find_path( Matlab_SIMULINK_INCLUDE_DIR simstruc.h @@ -1705,58 +1740,49 @@ if(_matlab_find_simulink GREATER -1) list(APPEND Matlab_INCLUDE_DIRS "${Matlab_SIMULINK_INCLUDE_DIR}") endif() endif() -unset(_matlab_find_simulink) -# component MCC Compiler -list(FIND Matlab_FIND_COMPONENTS MCC_COMPILER _matlab_find_mcc_compiler) -if(_matlab_find_mcc_compiler GREATER -1) +# component Matlab program +if("MAIN_PROGRAM" IN_LIST Matlab_FIND_COMPONENTS) find_program( - Matlab_MCC_COMPILER - "mcc" - PATHS ${Matlab_BINARIES_DIR} - DOC "Matlab MCC compiler" + Matlab_MAIN_PROGRAM + matlab + PATHS ${Matlab_ROOT_DIR} ${Matlab_ROOT_DIR}/bin + DOC "Matlab main program" NO_DEFAULT_PATH ) - if(Matlab_MCC_COMPILER) - set(Matlab_MCC_COMPILER_FOUND TRUE) + if(Matlab_MAIN_PROGRAM) + set(Matlab_MAIN_PROGRAM_FOUND TRUE) endif() endif() -unset(_matlab_find_mcc_compiler) - -if(Matlab_HAS_CPP_API) - # The MatlabEngine library is required for R2018a+ - _Matlab_find_library( - ${_matlab_lib_prefix_for_search} - Matlab_ENGINE_LIBRARY - MatlabEngine - PATHS ${_matlab_lib_dir_for_search} - DOC "MatlabEngine Library" +# component Mex Compiler +if("MEX_COMPILER" IN_LIST Matlab_FIND_COMPONENTS) + find_program( + Matlab_MEX_COMPILER + "mex" + PATHS ${Matlab_BINARIES_DIR} + DOC "Matlab MEX compiler" NO_DEFAULT_PATH ) - list(APPEND _matlab_required_variables Matlab_ENGINE_LIBRARY) - if(Matlab_ENGINE_LIBRARY) - set(Matlab_ENGINE_LIBRARY_FOUND TRUE) + if(Matlab_MEX_COMPILER) + set(Matlab_MEX_COMPILER_FOUND TRUE) endif() +endif() - # The MatlabDataArray library is required for R2018a+ - _Matlab_find_library( - ${_matlab_lib_prefix_for_search} - Matlab_DATAARRAY_LIBRARY - MatlabDataArray - PATHS ${_matlab_lib_dir_for_search} - DOC "MatlabDataArray Library" +# component MCC Compiler +if("MCC_COMPILER" IN_LIST Matlab_FIND_COMPONENTS) + find_program( + Matlab_MCC_COMPILER + "mcc" + PATHS ${Matlab_BINARIES_DIR} + DOC "Matlab MCC compiler" NO_DEFAULT_PATH ) - list(APPEND _matlab_required_variables Matlab_DATAARRAY_LIBRARY) - if(Matlab_DATAARRAY_LIBRARY) - set(Matlab_DATAARRAY_LIBRARY_FOUND TRUE) + if(Matlab_MCC_COMPILER) + set(Matlab_MCC_COMPILER_FOUND TRUE) endif() - endif() -unset(_matlab_lib_dir_for_search) - set(Matlab_LIBRARIES ${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY} ${Matlab_ENG_LIBRARY} ${Matlab_MAT_LIBRARY} @@ -1792,3 +1818,5 @@ if(Matlab_INCLUDE_DIRS AND Matlab_LIBRARIES) Matlab_MEX_EXTENSION ) endif() + +cmake_policy(POP) diff --git a/Modules/FindOpenACC.cmake b/Modules/FindOpenACC.cmake index dc8321d..743e0e2 100644 --- a/Modules/FindOpenACC.cmake +++ b/Modules/FindOpenACC.cmake @@ -22,6 +22,14 @@ project, where ``<lang>`` is one of C, CXX, or Fortran: Variable indicating if OpenACC support for ``<lang>`` was detected. ``OpenACC_<lang>_FLAGS`` OpenACC compiler flags for ``<lang>``, separated by spaces. +``OpenACC_<lang>_OPTIONS`` + OpenACC compiler flags for ``<lang>``, as a list. Suitable for usage + with target_compile_options or target_link_options. + +Additionally, the module provides :prop_tgt:`IMPORTED` targets: + +``OpenACC::OpenACC_<lang>`` + Target for using OpenACC from ``<lang>``. The module will also try to provide the OpenACC version variables: @@ -60,9 +68,7 @@ int main(){ set(OpenACC_Fortran_TEST_SOURCE " program test -#ifdef _OPENACC - return 0; -#else +#ifndef _OPENACC breaks_on_purpose #endif endprogram test @@ -241,6 +247,9 @@ foreach (LANG IN ITEMS C CXX Fortran) if(NOT DEFINED OpenACC_${LANG}_FLAGS) _OPENACC_GET_FLAGS("${LANG}" OpenACC_${LANG}_FLAGS) endif() + if(NOT DEFINED OpenACC_${LANG}_OPTIONS) + separate_arguments(OpenACC_${LANG}_OPTIONS NATIVE_COMMAND "${OpenACC_${LANG}_FLAGS}") + endif() _OPENACC_GET_SPEC_DATE("${LANG}" OpenACC_${LANG}_SPEC_DATE) _OPENACC_SET_VERSION_BY_SPEC_DATE("${LANG}") @@ -251,6 +260,23 @@ foreach (LANG IN ITEMS C CXX Fortran) endif() endforeach() +foreach (LANG IN ITEMS C CXX Fortran) + if(OpenACC_${LANG}_FOUND AND NOT TARGET OpenACC::OpenACC_${LANG}) + add_library(OpenACC::OpenACC_${LANG} INTERFACE IMPORTED) + endif() + if(OpenACC_${LANG}_LIBRARIES) + set_property(TARGET OpenACC::OpenACC_${LANG} PROPERTY + INTERFACE_LINK_LIBRARIES "${OpenACC_${LANG}_LIBRARIES}") + endif() + if(OpenACC_${LANG}_FLAGS) + set_property(TARGET OpenACC::OpenACC_${LANG} PROPERTY + INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:${OpenACC_${LANG}_OPTIONS}>") + set_property(TARGET OpenACC::OpenACC_${LANG} PROPERTY + INTERFACE_LINK_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:${OpenACC_${LANG}_OPTIONS}>") + unset(_OpenACC_${LANG}_OPTIONS) + endif() +endforeach() + unset(OpenACC_C_CXX_TEST_SOURCE) unset(OpenACC_Fortran_TEST_SOURCE) unset(OpenACC_C_CXX_CHECK_VERSION_SOURCE) diff --git a/Modules/FindPNG.cmake b/Modules/FindPNG.cmake index a7908c5..bd400c7 100644 --- a/Modules/FindPNG.cmake +++ b/Modules/FindPNG.cmake @@ -69,8 +69,8 @@ if(ZLIB_FOUND) unset(_PNG_VERSION_SUFFIX_MIN) endif () foreach(v IN LISTS _PNG_VERSION_SUFFIXES) - list(APPEND PNG_NAMES png${v} libpng${v}) - list(APPEND PNG_NAMES_DEBUG png${v}d libpng${v}d) + list(APPEND PNG_NAMES png${v} libpng${v} libpng${v}_static) + list(APPEND PNG_NAMES_DEBUG png${v}d libpng${v}d libpng${v}_staticd) endforeach() unset(_PNG_VERSION_SUFFIXES) # For compatibility with versions prior to this multi-config search, honor diff --git a/Modules/FindPackageHandleStandardArgs.cmake b/Modules/FindPackageHandleStandardArgs.cmake index 1722d6a..a2999fc 100644 --- a/Modules/FindPackageHandleStandardArgs.cmake +++ b/Modules/FindPackageHandleStandardArgs.cmake @@ -264,14 +264,14 @@ function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG) if(${_NAME}_${comp}_FOUND) if(NOT DEFINED FOUND_COMPONENTS_MSG) - set(FOUND_COMPONENTS_MSG "found components: ") + set(FOUND_COMPONENTS_MSG "found components:") endif() string(APPEND FOUND_COMPONENTS_MSG " ${comp}") else() if(NOT DEFINED MISSING_COMPONENTS_MSG) - set(MISSING_COMPONENTS_MSG "missing components: ") + set(MISSING_COMPONENTS_MSG "missing components:") endif() string(APPEND MISSING_COMPONENTS_MSG " ${comp}") diff --git a/Modules/FindProtobuf.cmake b/Modules/FindProtobuf.cmake index 76bc873..2d45965 100644 --- a/Modules/FindProtobuf.cmake +++ b/Modules/FindProtobuf.cmake @@ -521,6 +521,16 @@ if(Protobuf_INCLUDE_DIR) set_target_properties(protobuf::libprotobuf PROPERTIES IMPORTED_LOCATION_DEBUG "${Protobuf_LIBRARY_DEBUG}") endif() + if (Protobuf_VERSION VERSION_GREATER_EQUAL "3.6") + set_property(TARGET protobuf::libprotobuf APPEND PROPERTY + INTERFACE_COMPILE_FEATURES cxx_std_11 + ) + endif() + if (MSVC AND NOT Protobuf_USE_STATIC_LIBS) + set_property(TARGET protobuf::libprotobuf APPEND PROPERTY + INTERFACE_COMPILE_DEFINITIONS "PROTOBUF_USE_DLLS" + ) + endif() if(UNIX AND TARGET Threads::Threads) set_property(TARGET protobuf::libprotobuf APPEND PROPERTY INTERFACE_LINK_LIBRARIES Threads::Threads) @@ -549,6 +559,11 @@ if(Protobuf_INCLUDE_DIR) set_target_properties(protobuf::libprotobuf-lite PROPERTIES IMPORTED_LOCATION_DEBUG "${Protobuf_LITE_LIBRARY_DEBUG}") endif() + if (MSVC AND NOT Protobuf_USE_STATIC_LIBS) + set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY + INTERFACE_COMPILE_DEFINITIONS "PROTOBUF_USE_DLLS" + ) + endif() if(UNIX AND TARGET Threads::Threads) set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY INTERFACE_LINK_LIBRARIES Threads::Threads) @@ -577,6 +592,16 @@ if(Protobuf_INCLUDE_DIR) set_target_properties(protobuf::libprotoc PROPERTIES IMPORTED_LOCATION_DEBUG "${Protobuf_PROTOC_LIBRARY_DEBUG}") endif() + if (Protobuf_VERSION VERSION_GREATER_EQUAL "3.6") + set_property(TARGET protobuf::libprotoc APPEND PROPERTY + INTERFACE_COMPILE_FEATURES cxx_std_11 + ) + endif() + if (MSVC AND NOT Protobuf_USE_STATIC_LIBS) + set_property(TARGET protobuf::libprotoc APPEND PROPERTY + INTERFACE_COMPILE_DEFINITIONS "PROTOBUF_USE_DLLS" + ) + endif() if(UNIX AND TARGET Threads::Threads) set_property(TARGET protobuf::libprotoc APPEND PROPERTY INTERFACE_LINK_LIBRARIES Threads::Threads) diff --git a/Modules/FindPython.cmake b/Modules/FindPython.cmake index e2f3bf3..2056e93 100644 --- a/Modules/FindPython.cmake +++ b/Modules/FindPython.cmake @@ -137,6 +137,51 @@ Hints * If set to TRUE, search **only** for static libraries. * If set to FALSE, search **only** for shared libraries. +``Python_FIND_ABI`` + This variable defines which ABIs, as defined in + `PEP 3149 <https://www.python.org/dev/peps/pep-3149/>`_, should be searched. + + .. note:: + + This hint will be honored only when searched for ``Python`` version 3. + + .. note:: + + If ``Python_FIND_ABI`` is not defined, any ABI will be searched. + + The ``Python_FIND_ABI`` variable is a 3-tuple specifying, in that order, + ``pydebug`` (``d``), ``pymalloc`` (``m``) and ``unicode`` (``u``) flags. + Each element can be set to one of the following: + + * ``ON``: Corresponding flag is selected. + * ``OFF``: Corresponding flag is not selected. + * ``ANY``: The two posibilties (``ON`` and ``OFF``) will be searched. + + From this 3-tuple, various ABIs will be searched starting from the most + specialized to the most general. Moreover, ``debug`` versions will be + searched **after** ``non-debug`` ones. + + For example, if we have:: + + set (Python_FIND_ABI "ON" "ANY" "ANY") + + The following flags combinations will be appended, in that order, to the + artifact names: ``dmu``, ``dm``, ``du``, and ``d``. + + And to search any possible ABIs:: + + set (Python_FIND_ABI "ANY" "ANY" "ANY") + + The following combinations, in that order, will be used: ``mu``, ``m``, + ``u``, ``<empty>``, ``dmu``, ``dm``, ``du`` and ``d``. + + .. note:: + + This hint is useful only on ``POSIX`` systems. So, on ``Windows`` systems, + when ``Python_FIND_ABI`` is defined, ``Python`` distributions from + `python.org <https://www.python.org/>`_ will be found only if value for + each flag is ``OFF`` or ``ANY``. + ``Python_FIND_STRATEGY`` This variable defines how lookup will be done. The ``Python_FIND_STRATEGY`` variable can be set to empty or one of the @@ -192,6 +237,12 @@ Hints ``NEVER`` to select preferably the interpreter from the virtual environment. + .. note:: + + If the component ``Development`` is requested, it is **strongly** + recommended to also include the component ``Interpreter`` to get expected + result. + Commands ^^^^^^^^ diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake index 590c7af..90a8264 100644 --- a/Modules/FindPython/Support.cmake +++ b/Modules/FindPython/Support.cmake @@ -96,51 +96,228 @@ function (_PYTHON_GET_REGISTRIES _PYTHON_PGR_REGISTRY_PATHS _PYTHON_VERSION) PARENT_SCOPE) endfunction() -function (_PYTHON_GET_PATH_SUFFIXES _PYTHON_PGPS_PATH_SUFFIXES _PYTHON_VERSION _PYTHON_TYPE) - set (path_suffixes) - if (_PYTHON_TYPE STREQUAL "LIBRARY") +function (_PYTHON_GET_ABIFLAGS _PGABIFLAGS) + set (abiflags) + list (GET _${_PYTHON_PREFIX}_FIND_ABI 0 pydebug) + list (GET _${_PYTHON_PREFIX}_FIND_ABI 1 pymalloc) + list (GET _${_PYTHON_PREFIX}_FIND_ABI 2 unicode) + + if (pymalloc STREQUAL "ANY" AND unicode STREQUAL "ANY") + set (abiflags "mu" "m" "u" "") + elseif (pymalloc STREQUAL "ANY" AND unicode STREQUAL "ON") + set (abiflags "mu" "u") + elseif (pymalloc STREQUAL "ANY" AND unicode STREQUAL "OFF") + set (abiflags "m" "") + elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ANY") + set (abiflags "mu" "m") + elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ON") + set (abiflags "mu") + elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "OFF") + set (abiflags "m") + elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ANY") + set (abiflags "u" "") + elseif (pymalloc STREQUAL "OFF" AND unicode STREQUAL "ON") + set (abiflags "u") + endif() + + if (pydebug STREQUAL "ON") + if (abiflags) + list (TRANSFORM abiflags PREPEND "d") + else() + set (abiflags "d") + endif() + elseif (pydebug STREQUAL "ANY") + if (abiflags) + set (flags "${abiflags}") + list (TRANSFORM flags PREPEND "d") + list (APPEND abiflags "${flags}") + else() + set (abiflags "" "d") + endif() + endif() + + set (${_PGABIFLAGS} "${abiflags}" PARENT_SCOPE) +endfunction() + +function (_PYTHON_GET_PATH_SUFFIXES _PYTHON_PGPS_PATH_SUFFIXES) + cmake_parse_arguments (PARSE_ARGV 1 _PGPS "LIBRARY;INCLUDE" "VERSION" "") + + if (DEFINED _${_PYTHON_PREFIX}_ABIFLAGS) + set (abi "${_${_PYTHON_PREFIX}_ABIFLAGS}") + else() + set (abi "mu" "m" "u" "") + endif() + + set (path_suffixes) + if (_PGPS_LIBRARY) if (CMAKE_LIBRARY_ARCHITECTURE) list (APPEND path_suffixes lib/${CMAKE_LIBRARY_ARCHITECTURE}) endif() list (APPEND path_suffixes lib libs) if (CMAKE_LIBRARY_ARCHITECTURE) - list (APPEND path_suffixes lib/python${_PYTHON_VERSION}/config-${_PYTHON_VERSION}mu-${CMAKE_LIBRARY_ARCHITECTURE} - lib/python${_PYTHON_VERSION}/config-${_PYTHON_VERSION}m-${CMAKE_LIBRARY_ARCHITECTURE} - lib/python${_PYTHON_VERSION}/config-${CMAKE_MATCH_1}u-${CMAKE_LIBRARY_ARCHITECTURE} - lib/python${_PYTHON_VERSION}/config-${CMAKE_MATCH_1}-${CMAKE_LIBRARY_ARCHITECTURE}) + set (suffixes "${abi}") + if (suffixes) + list (TRANSFORM suffixes PREPEND "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}") + list (TRANSFORM suffixes APPEND "-${CMAKE_LIBRARY_ARCHITECTURE}") + else() + set (suffixes "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}-${CMAKE_LIBRARY_ARCHITECTURE}") + endif() + list (APPEND path_suffixes ${suffixes}) endif() - list (APPEND path_suffixes lib/python${_PYTHON_VERSION}/config-${_PYTHON_VERSION}mu - lib/python${_PYTHON_VERSION}/config-${_PYTHON_VERSION}m - lib/python${_PYTHON_VERSION}/config-${_PYTHON_VERSION}u - lib/python${_PYTHON_VERSION}/config-${_PYTHON_VERSION} - lib/python${_PYTHON_VERSION}/config) - - elseif (_PYTHON_TYPE STREQUAL "INCLUDE") - list (APPEND path_suffixes include/python${_PYTHON_VERSION}mu - include/python${_PYTHON_VERSION}m - include/python${_PYTHON_VERSION}u - include/python${_PYTHON_VERSION} - include) + set (suffixes "${abi}") + if (suffixes) + list (TRANSFORM suffixes PREPEND "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}") + else() + set (suffixes "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}") + endif() + list (APPEND path_suffixes ${suffixes}) + elseif (_PGPS_INCLUDE) + set (suffixes "${abi}") + if (suffixes) + list (TRANSFORM suffixes PREPEND "include/python${_PGPS_VERSION}") + else() + set (suffixes "include/python${_PGPS_VERSION}") + endif() + list (APPEND path_suffixes ${suffixes} include) endif() set (${_PYTHON_PGPS_PATH_SUFFIXES} ${path_suffixes} PARENT_SCOPE) endfunction() -function (_PYTHON_GET_LIB_NAMES _PYTHON_PGLN_NAMES _PYTHON_VERSION) - string (REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${_PYTHON_VERSION}) +function (_PYTHON_GET_NAMES _PYTHON_PGN_NAMES) + cmake_parse_arguments (PARSE_ARGV 1 _PGN "POSIX;EXECUTABLE;CONFIG;LIBRARY;WIN32;DEBUG" "VERSION" "") - if (ARGC EQUAL 3 AND ARGV2 STREQUAL "DEBUG") - set (${_PYTHON_PGLN_NAMES} python${_PYTHON_VERSION_NO_DOTS}_d PARENT_SCOPE) - else() - set (${_PYTHON_PGLN_NAMES} python${_PYTHON_VERSION_NO_DOTS} - python${_PYTHON_VERSION}mu - python${_PYTHON_VERSION}m - python${_PYTHON_VERSION}u - python${_PYTHON_VERSION} - PARENT_SCOPE) + set (names) + + if (_PGN_WIN32) + string (REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${_PGN_VERSION}) + + set (name python${_PYTHON_VERSION_NO_DOTS}) + if (_PGN_DEBUG) + string (APPEND name "_d") + endif() + + list (APPEND names "${name}") + endif() + + if (_PGN_POSIX) + if (DEFINED _${_PYTHON_PREFIX}_ABIFLAGS) + set (abi "${_${_PYTHON_PREFIX}_ABIFLAGS}") + else() + if (_PGN_EXECUTABLE OR _PGN_CONFIG) + set (abi "") + else() + set (abi "mu" "m" "u" "") + endif() + endif() + + if (abi) + if (_PGN_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE) + set (abinames "${abi}") + list (TRANSFORM abinames PREPEND "${CMAKE_LIBRARY_ARCHITECTURE}-python${_PGN_VERSION}") + list (TRANSFORM abinames APPEND "-config") + list (APPEND names ${abinames}) + endif() + set (abinames "${abi}") + list (TRANSFORM abinames PREPEND "python${_PGN_VERSION}") + if (_PGN_CONFIG) + list (TRANSFORM abinames APPEND "-config") + endif() + list (APPEND names ${abinames}) + else() + if (_PGN_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE) + set (abinames "${CMAKE_LIBRARY_ARCHITECTURE}-python${_PGN_VERSION}") + endif() + list (APPEND abinames "python${_PGN_VERSION}") + if (_PGN_CONFIG) + list (TRANSFORM abinames APPEND "-config") + endif() + list (APPEND names ${abinames}) + endif() + endif() + + set (${_PYTHON_PGN_NAMES} ${names} PARENT_SCOPE) +endfunction() + +function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) + unset (${_PYTHON_PGCV_VALUE} PARENT_SCOPE) + + if (NOT NAME MATCHES "^(PREFIX|ABIFLAGS|CONFIGDIR|INCLUDES|LIBS)$") + return() + endif() + + if (_${_PYTHON_PREFIX}_CONFIG) + set (config_flag "--${NAME}") + string (TOLOWER "${config_flag}" config_flag) + execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" ${config_flag} + RESULT_VARIABLE _result + OUTPUT_VARIABLE _values + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (_result) + unset (_values) + else() + if (NAME STREQUAL "INCLUDES") + # do some clean-up + string (REGEX MATCHALL "-I[^ ]+" _values "${_values}") + string (REPLACE "-I" "" _values "${_values}") + list (REMOVE_DUPLICATES _values) + endif() + endif() + endif() + + if (${_PYTHON_PREFIX}_EXECUTABLE AND NOT CMAKE_CROSSCOMPILING) + if (NAME STREQUAL "PREFIX") + execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig; sys.stdout.write(';'.join([sysconfig.PREFIX,sysconfig.EXEC_PREFIX,sysconfig.BASE_EXEC_PREFIX]))" + RESULT_VARIABLE _result + OUTPUT_VARIABLE _values + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (_result) + unset (_values) + else() + list (REMOVE_DUPLICATES _values) + endif() + elseif (NAME STREQUAL "INCLUDES") + execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig; sys.stdout.write(';'.join([sysconfig.get_python_inc(plat_specific=True),sysconfig.get_python_inc(plat_specific=False)]))" + RESULT_VARIABLE _result + OUTPUT_VARIABLE _values + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (_result) + unset (_values) + endif() + else() + set (config_flag "${NAME}") + if (NAME STREQUAL "CONFIGDIR") + set (config_flag "LIBPL") + endif() + execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.get_config_var('${config_flag}'))" + RESULT_VARIABLE _result + OUTPUT_VARIABLE _values + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (_result) + unset (_values) + endif() + endif() endif() + + if (NOT _values OR _values STREQUAL "None") + return() + endif() + + if (NAME STREQUAL "LIBS") + # do some clean-up + string (REGEX MATCHALL "-[l][^ ]+" _values "${_values}") + # remove elements relative to python library itself + list (FILTER _values EXCLUDE REGEX "-lpython") + list (REMOVE_DUPLICATES _values) + endif() + + set (${_PYTHON_PGCV_VALUE} "${_values}" PARENT_SCOPE) endfunction() @@ -149,16 +326,35 @@ function (_PYTHON_VALIDATE_INTERPRETER) return() endif() - cmake_parse_arguments (_PVI "EXACT" "" "" ${ARGN}) + cmake_parse_arguments (PARSE_ARGV 0 _PVI "EXACT" "" "") if (_PVI_UNPARSED_ARGUMENTS) set (expected_version ${_PVI_UNPARSED_ARGUMENTS}) else() unset (expected_version) endif() + # validate ABI compatibility + if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI) + execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c + "import sys; sys.stdout.write(sys.abiflags)" + RESULT_VARIABLE result + OUTPUT_VARIABLE abi + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (result) + # assume ABI is not supported + set (abi "") + endif() + if (NOT abi IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) + # incompatible ABI + set_property (CACHE ${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") + return() + endif() + endif() + get_filename_component (python_name "${${_PYTHON_PREFIX}_EXECUTABLE}" NAME) - if (expected_version AND NOT python_name STREQUAL "python${expected_version}${CMAKE_EXECUTABLE_SUFFIX}") + if (expected_version AND NOT python_name STREQUAL "python${expected_version}${abi}${CMAKE_EXECUTABLE_SUFFIX}") # executable found must have a specific version execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:2]]))" @@ -168,7 +364,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) OUTPUT_STRIP_TRAILING_WHITESPACE) if (result OR (_PVI_EXACT AND NOT version VERSION_EQUAL expected_version) OR (version VERSION_LESS expected_version)) # interpreter not usable or has wrong major version - set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE) + set_property (CACHE ${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() endif() else() @@ -183,7 +379,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) OUTPUT_STRIP_TRAILING_WHITESPACE) if (result OR NOT version EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) # interpreter not usable or has wrong major version - set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE) + set_property (CACHE ${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() endif() endif() @@ -200,7 +396,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) OUTPUT_STRIP_TRAILING_WHITESPACE) if (result OR NOT size EQUAL CMAKE_SIZEOF_VOID_P) # interpreter not usable or has wrong architecture - set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE) + set_property (CACHE ${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() endif() endif() @@ -244,7 +440,7 @@ function (_PYTHON_VALIDATE_COMPILER expected_version) if (result OR (_PVC_EXACT AND NOT version VERSION_EQUAL expected_version) OR (version VERSION_LESS expected_version)) # Compiler not usable or has wrong version - set (${_PYTHON_PREFIX}_COMPILER ${_PYTHON_PREFIX}_COMPILER-NOTFOUND CACHE INTERNAL "" FORCE) + set_property (CACHE ${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND") endif() endfunction() @@ -321,6 +517,28 @@ if (${_PYTHON_PREFIX}_FIND_VERSION_COUNT GREATER 1) endif() endif() +# Set ABIs to search +## default: search any ABI +if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_LESS 3) + # ABI not supported + unset (_${_PYTHON_PREFIX}_FIND_ABI) + set (_${_PYTHON_PREFIX}_ABIFLAGS "") +else() + unset (_${_PYTHON_PREFIX}_FIND_ABI) + unset (_${_PYTHON_PREFIX}_ABIFLAGS) + if (DEFINED ${_PYTHON_PREFIX}_FIND_ABI) + # normalization + string (TOUPPER "${${_PYTHON_PREFIX}_FIND_ABI}" _${_PYTHON_PREFIX}_FIND_ABI) + list (TRANSFORM _${_PYTHON_PREFIX}_FIND_ABI REPLACE "^(TRUE|Y(ES)?|1)$" "ON") + list (TRANSFORM _${_PYTHON_PREFIX}_FIND_ABI REPLACE "^(FALSE|N(O)?|0)$" "OFF") + if (NOT _${_PYTHON_PREFIX}_FIND_ABI MATCHES "^(ON|OFF|ANY);(ON|OFF|ANY);(ON|OFF|ANY)$") + message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_ABI}: invalid value for '${_PYTHON_PREFIX}_FIND_ABI'. Ignore it") + unset (_${_PYTHON_PREFIX}_FIND_ABI) + endif() + _python_get_abiflags (_${_PYTHON_PREFIX}_ABIFLAGS) + endif() +endif() + # Define lookup strategy if (_${_PYTHON_PREFIX}_LOOKUP_POLICY STREQUAL "NEW") set (_${_PYTHON_PREFIX}_FIND_STRATEGY "LOCATION") @@ -446,7 +664,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) # build all executable names - list (APPEND _${_PYTHON_PREFIX}_NAMES python${_${_PYTHON_PREFIX}_VERSION}) + _python_get_names (_${_PYTHON_PREFIX}_VERSION_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} POSIX EXECUTABLE) + list (APPEND _${_PYTHON_PREFIX}_NAMES ${_${_PYTHON_PREFIX}_VERSION_NAMES}) # Framework Paths _python_get_frameworks (_${_PYTHON_PREFIX}_VERSION_PATHS ${_${_PYTHON_PREFIX}_VERSION}) @@ -516,12 +735,24 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) endif() endif() - # try using HINTS and standard paths + # try using HINTS find_program (${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES} ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} + PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION}) + if (${_PYTHON_PREFIX}_EXECUTABLE) + break() + endif() + # try using standard paths + find_program (${_PYTHON_PREFIX}_EXECUTABLE + NAMES ${_${_PYTHON_PREFIX}_NAMES} + ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} + NAMES_PER_DIR PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}) _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION}) if (${_PYTHON_PREFIX}_EXECUTABLE) @@ -561,9 +792,9 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) else() # look-up for various versions and locations foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) - set (_${_PYTHON_PREFIX}_NAMES python${_${_PYTHON_PREFIX}_VERSION} - python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} - python) + _python_get_names (_${_PYTHON_PREFIX}_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} POSIX EXECUTABLE) + list (APPEND _${_PYTHON_PREFIX}_NAMES python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} + python) _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION}) _python_get_registries (_${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_VERSION}) @@ -643,12 +874,12 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # systematically 'python' (i.e. version 2) even if version 3 is searched. if (CMAKE_HOST_WIN32) find_program (${_PYTHON_PREFIX}_EXECUTABLE - NAMES python${_${_PYTHON_PREFIX}_VERSION} + NAMES ${_${_PYTHON_PREFIX}_NAMES} python ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}) else() find_program (${_PYTHON_PREFIX}_EXECUTABLE - NAMES python${_${_PYTHON_PREFIX}_VERSION}) + NAMES ${_${_PYTHON_PREFIX}_NAMES}) endif() _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION} EXACT) if (${_PYTHON_PREFIX}_EXECUTABLE) @@ -715,7 +946,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) list (GET _${_PYTHON_PREFIX}_VERSIONS 2 ${_PYTHON_PREFIX}_VERSION_PATCH) else() # Interpreter is not usable - set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE) + set_property (CACHE ${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") unset (${_PYTHON_PREFIX}_VERSION) endif() endif() @@ -723,8 +954,17 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) if (${_PYTHON_PREFIX}_EXECUTABLE AND ${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) set (${_PYTHON_PREFIX}_Interpreter_FOUND TRUE) - # Use interpreter version for future searches to ensure consistency + # Use interpreter version and ABI for future searches to ensure consistency set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR}) + execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; sys.stdout.write(sys.abiflags)" + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE _${_PYTHON_PREFIX}_ABIFLAGS + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (_${_PYTHON_PREFIX}_RESULT) + # assunme ABI is not supported + set (_${_PYTHON_PREFIX}_ABIFLAGS "") + endif() endif() if (${_PYTHON_PREFIX}_Interpreter_FOUND) @@ -932,7 +1172,7 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) endif() else() # compiler not usable - set (${_PYTHON_PREFIX}_COMPILER ${_PYTHON_PREFIX}_COMPILER-NOTFOUND CACHE INTERNAL "" FORCE) + set_property (CACHE ${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND") endif() file (REMOVE_RECURSE "${_${_PYTHON_PREFIX}_VERSION_DIR}") endif() @@ -986,87 +1226,90 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() endif() - # if python interpreter is found, use its location and version to ensure consistency - # between interpreter and development environment - unset (_${_PYTHON_PREFIX}_PREFIX) - unset (_${_PYTHON_PREFIX}_EXEC_PREFIX) - unset (_${_PYTHON_PREFIX}_BASE_EXEC_PREFIX) - if (${_PYTHON_PREFIX}_Interpreter_FOUND) - execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.EXEC_PREFIX)" - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE _${_PYTHON_PREFIX}_EXEC_PREFIX - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (_${_PYTHON_PREFIX}_RESULT) - unset (_${_PYTHON_PREFIX}_EXEC_PREFIX) - endif() - - if (NOT ${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "STANDARD") - execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.BASE_EXEC_PREFIX)" - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE _${_PYTHON_PREFIX}_BASE_EXEC_PREFIX - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (_${_PYTHON_PREFIX}_RESULT) - unset (_${_PYTHON_PREFIX}_BASE_EXEC_PREFIX) - endif() + # if python interpreter is found, use it to ensure consistency + # between interpreter and development environment. + # If not, try to locate a compatible config tool + if (NOT ${_PYTHON_PREFIX}_Interpreter_FOUND OR CMAKE_CROSSCOMPILING) + set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR) + unset (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS) + if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$") + set (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS ENV VIRTUAL_ENV) endif() - endif() - set (_${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_EXEC_PREFIX}" "${_${_PYTHON_PREFIX}_BASE_EXEC_PREFIX}" "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR) + unset (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS) - if (_${_PYTHON_PREFIX}_FIND_STRATEGY STREQUAL "LOCATION") - set (_${_PYTHON_PREFIX}_CONFIG_NAMES) + if (_${_PYTHON_PREFIX}_FIND_STRATEGY STREQUAL "LOCATION") + set (_${_PYTHON_PREFIX}_CONFIG_NAMES) - foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) - if (DEFINED CMAKE_LIBRARY_ARCHITECTURE) - list (APPEND _${_PYTHON_PREFIX}_CONFIG_NAMES "${CMAKE_LIBRARY_ARCHITECTURE}-python${_${_PYTHON_PREFIX}_VERSION}-config") - endif() - list (APPEND _${_PYTHON_PREFIX}_CONFIG_NAMES "python${_${_PYTHON_PREFIX}_VERSION}-config") - endforeach() + foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) + _python_get_names (_${_PYTHON_PREFIX}_VERSION_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} POSIX CONFIG) + list (APPEND _${_PYTHON_PREFIX}_CONFIG_NAMES ${_${_PYTHON_PREFIX}_VERSION_NAMES}) - find_program (_${_PYTHON_PREFIX}_CONFIG - NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES} - NAMES_PER_DIR - HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATH_SUFFIXES bin) + # Framework Paths + _python_get_frameworks (_${_PYTHON_PREFIX}_VERSION_PATHS ${_${_PYTHON_PREFIX}_VERSION}) + list (APPEND _${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION_PATHS}) + endforeach() - if (_${_PYTHON_PREFIX}_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE) - # check that config tool match library architecture - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --configdir - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE _${_PYTHON_PREFIX}_CONFIGDIR - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (_${_PYTHON_PREFIX}_RESULT) - unset (_${_PYTHON_PREFIX}_CONFIG CACHE) - else() - string(FIND "${_${_PYTHON_PREFIX}_CONFIGDIR}" "${CMAKE_LIBRARY_ARCHITECTURE}" _${_PYTHON_PREFIX}_RESULT) - if (_${_PYTHON_PREFIX}_RESULT EQUAL -1) - unset (_${_PYTHON_PREFIX}_CONFIG CACHE) - endif() - endif() - endif() - else() - foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) - # try to use pythonX.Y-config tool - set (_${_PYTHON_PREFIX}_CONFIG_NAMES) - if (DEFINED CMAKE_LIBRARY_ARCHITECTURE) - set (_${_PYTHON_PREFIX}_CONFIG_NAMES "${CMAKE_LIBRARY_ARCHITECTURE}-python${_${_PYTHON_PREFIX}_VERSION}-config") + # Apple frameworks handling + if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") + find_program (${_PYTHON_PREFIX}_CONFIG + NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES} + NAMES_PER_DIR + HINTS ${_${_PYTHON_PREFIX}_HINTS} + PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} + ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} + PATH_SUFFIXES bin + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) endif() - list (APPEND _${_PYTHON_PREFIX}_CONFIG_NAMES "python${_${_PYTHON_PREFIX}_VERSION}-config") + find_program (_${_PYTHON_PREFIX}_CONFIG NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} + PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} PATH_SUFFIXES bin) - unset (_${_PYTHON_PREFIX}_CONFIG_NAMES) - if (NOT _${_PYTHON_PREFIX}_CONFIG) - continue() + # Apple frameworks handling + if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST") + find_program (_${_PYTHON_PREFIX}_CONFIG + NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES} + NAMES_PER_DIR + PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} + PATH_SUFFIXES bin + NO_DEFAULT_PATH) + endif() + + if (_${_PYTHON_PREFIX}_CONFIG) + execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --help + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE __${_PYTHON_PREFIX}_HELP + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (_${_PYTHON_PREFIX}_RESULT) + # assume config tool is not usable + unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + endif() + endif() + + if (_${_PYTHON_PREFIX}_CONFIG) + execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --abiflags + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE __${_PYTHON_PREFIX}_ABIFLAGS + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (_${_PYTHON_PREFIX}_RESULT) + # assume ABI is not supported + set (__${_PYTHON_PREFIX}_ABIFLAGS "") + endif() + if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT __${_PYTHON_PREFIX}_ABIFLAGS IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) + # Wrong ABI + unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + endif() endif() - if (DEFINED CMAKE_LIBRARY_ARCHITECTURE) + + if (_${_PYTHON_PREFIX}_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE) # check that config tool match library architecture execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --configdir RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT @@ -1075,79 +1318,132 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS OUTPUT_STRIP_TRAILING_WHITESPACE) if (_${_PYTHON_PREFIX}_RESULT) unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + else() + string(FIND "${_${_PYTHON_PREFIX}_CONFIGDIR}" "${CMAKE_LIBRARY_ARCHITECTURE}" _${_PYTHON_PREFIX}_RESULT) + if (_${_PYTHON_PREFIX}_RESULT EQUAL -1) + unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + endif() + endif() + endif() + else() + foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) + # try to use pythonX.Y-config tool + _python_get_names (_${_PYTHON_PREFIX}_CONFIG_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} POSIX CONFIG) + + # Framework Paths + _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION}) + + # Apple frameworks handling + if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") + find_program (${_PYTHON_PREFIX}_CONFIG + NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES} + NAMES_PER_DIR + HINTS ${_${_PYTHON_PREFIX}_HINTS} + PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} + ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} + PATH_SUFFIXES bin + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + endif() + + find_program (_${_PYTHON_PREFIX}_CONFIG + NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES} + NAMES_PER_DIR + HINTS ${_${_PYTHON_PREFIX}_HINTS} + PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} + PATH_SUFFIXES bin) + + # Apple frameworks handling + if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST") + find_program (_${_PYTHON_PREFIX}_CONFIG + NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES} + NAMES_PER_DIR + PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} + PATH_SUFFIXES bin + NO_DEFAULT_PATH) + endif() + + unset (_${_PYTHON_PREFIX}_CONFIG_NAMES) + + if (_${_PYTHON_PREFIX}_CONFIG) + execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --help + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE __${_PYTHON_PREFIX}_HELP + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (_${_PYTHON_PREFIX}_RESULT) + # assume config tool is not usable + unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + endif() + endif() + + if (NOT _${_PYTHON_PREFIX}_CONFIG) continue() endif() - string(FIND "${_${_PYTHON_PREFIX}_CONFIGDIR}" "${CMAKE_LIBRARY_ARCHITECTURE}" _${_PYTHON_PREFIX}_RESULT) - if (_${_PYTHON_PREFIX}_RESULT EQUAL -1) + + execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --abiflags + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE __${_PYTHON_PREFIX}_ABIFLAGS + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (_${_PYTHON_PREFIX}_RESULT) + # assume ABI is not supported + set (__${_PYTHON_PREFIX}_ABIFLAGS "") + endif() + if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT __${_PYTHON_PREFIX}_ABIFLAGS IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) + # Wrong ABI unset (_${_PYTHON_PREFIX}_CONFIG CACHE) continue() endif() - endif() - if (_${_PYTHON_PREFIX}_CONFIG) - break() - endif() - endforeach() - endif() + if (_${_PYTHON_PREFIX}_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE) + # check that config tool match library architecture + execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --configdir + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE _${_PYTHON_PREFIX}_CONFIGDIR + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (_${_PYTHON_PREFIX}_RESULT) + unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + continue() + endif() + string(FIND "${_${_PYTHON_PREFIX}_CONFIGDIR}" "${CMAKE_LIBRARY_ARCHITECTURE}" _${_PYTHON_PREFIX}_RESULT) + if (_${_PYTHON_PREFIX}_RESULT EQUAL -1) + unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + continue() + endif() + endif() - if (_${_PYTHON_PREFIX}_CONFIG) - # retrieve root install directory - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --prefix - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE _${_PYTHON_PREFIX}_PREFIX - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (_${_PYTHON_PREFIX}_RESULT) - # python-config is not usable - unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + if (_${_PYTHON_PREFIX}_CONFIG) + break() + endif() + endforeach() endif() endif() - if (_${_PYTHON_PREFIX}_CONFIG) - set (_${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_PREFIX}") + if ((${_PYTHON_PREFIX}_Interpreter_FOUND AND NOT CMAKE_CROSSCOMPILING) OR _${_PYTHON_PREFIX}_CONFIG) + # retrieve root install directory + _python_get_config_var (_${_PYTHON_PREFIX}_PREFIX PREFIX) - unset (_${_PYTHON_PREFIX}_LIB_DIRS) - unset (_${_PYTHON_PREFIX}_PATH_SUFFIXES) - unset (_${_PYTHON_PREFIX}_LIB_NAMES) + # enforce current ABI + _python_get_config_var (_${_PYTHON_PREFIX}_ABIFLAGS ABIFLAGS) - # retrieve library - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --ldflags - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE _${_PYTHON_PREFIX}_FLAGS - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (NOT _${_PYTHON_PREFIX}_RESULT) - # retrieve library directory - string (REGEX MATCHALL "-L[^ ]+" _${_PYTHON_PREFIX}_LIB_DIRS "${_${_PYTHON_PREFIX}_FLAGS}") - string (REPLACE "-L" "" _${_PYTHON_PREFIX}_LIB_DIRS "${_${_PYTHON_PREFIX}_LIB_DIRS}") - if (_${_PYTHON_PREFIX}_CONFIG MATCHES "python([0-9.]+)-config") - _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES ${CMAKE_MATCH_1} LIBRARY) - endif() + set (_${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_PREFIX}") - # retrieve library name - string (REGEX MATCHALL "-lpython[^ ]+" _${_PYTHON_PREFIX}_LIB_NAMES "${_${_PYTHON_PREFIX}_FLAGS}") - string (REPLACE "-l" "" _${_PYTHON_PREFIX}_LIB_NAMES "${_${_PYTHON_PREFIX}_LIB_NAMES}") - list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_LIB_NAMES) + # retrieve library + ## compute some paths and artifact names + if (_${_PYTHON_PREFIX}_CONFIG) + string (REGEX REPLACE "^.+python([0-9.]+)[a-z]*-config" "\\1" _${_PYTHON_PREFIX}_LIB_VERSION "${_${_PYTHON_PREFIX}_CONFIG}") + else() + set (_${_PYTHON_PREFIX}_LIB_VERSION "${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR}") endif() + _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} LIBRARY) + _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} POSIX LIBRARY) - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --configdir - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE _${_PYTHON_PREFIX}_CONFIGDIR - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (NOT _${_PYTHON_PREFIX}_RESULT) - list (APPEND _${_PYTHON_PREFIX}_LIB_DIRS "${_${_PYTHON_PREFIX}_CONFIGDIR}") - endif() - list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_LIB_DIRS) - list (APPEND _${_PYTHON_PREFIX}_HINTS ${_${_PYTHON_PREFIX}_LIB_DIRS}) - - if (NOT _${_PYTHON_PREFIX}_LIB_NAMES) - # config tool do not specify "-l" option (it is the case starting with 3.8) - # extract version from the config tool name and list all possible lib names - if (_${_PYTHON_PREFIX}_CONFIG MATCHES "python([0-9.]+)-config") - _python_get_lib_names (_${_PYTHON_PREFIX}_LIB_NAMES ${CMAKE_MATCH_1}) - endif() - endif() + _python_get_config_var (_${_PYTHON_PREFIX}_CONFIGDIR CONFIGDIR) + list (APPEND _${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_CONFIGDIR}") list (APPEND _${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR) @@ -1173,29 +1469,24 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() # retrieve include directory - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --includes - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE _${_PYTHON_PREFIX}_FLAGS - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (NOT _${_PYTHON_PREFIX}_RESULT) - # retrieve include directory - string (REGEX MATCHALL "-I[^ ]+" _${_PYTHON_PREFIX}_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_FLAGS}") - string (REPLACE "-I" "" _${_PYTHON_PREFIX}_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_INCLUDE_DIRS}") - list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_INCLUDE_DIRS) + _python_get_config_var (_${_PYTHON_PREFIX}_INCLUDE_DIRS INCLUDES) - find_path (${_PYTHON_PREFIX}_INCLUDE_DIR - NAMES Python.h - HINTS ${_${_PYTHON_PREFIX}_INCLUDE_DIRS} - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - endif() + find_path (${_PYTHON_PREFIX}_INCLUDE_DIR + NAMES Python.h + HINTS ${_${_PYTHON_PREFIX}_INCLUDE_DIRS} + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) endif() - # Rely on HINTS and standard paths if config tool failed to locate artifacts + # Rely on HINTS and standard paths if interpreter or config tool failed to locate artifacts if (NOT ${_PYTHON_PREFIX}_LIBRARY_RELEASE OR NOT ${_PYTHON_PREFIX}_INCLUDE_DIR) set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR) + unset (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS) + if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$") + set (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS ENV VIRTUAL_ENV) + endif() + if (_${_PYTHON_PREFIX}_FIND_STRATEGY STREQUAL "LOCATION") unset (_${_PYTHON_PREFIX}_LIB_NAMES) unset (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG) @@ -1205,9 +1496,9 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS foreach (_${_PYTHON_PREFIX}_LIB_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) # library names - _python_get_lib_names (_${_PYTHON_PREFIX}_VERSION_NAMES ${_${_PYTHON_PREFIX}_LIB_VERSION}) + _python_get_names (_${_PYTHON_PREFIX}_VERSION_NAMES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} WIN32 POSIX LIBRARY) list (APPEND _${_PYTHON_PREFIX}_LIB_NAMES ${_${_PYTHON_PREFIX}_VERSION_NAMES}) - _python_get_lib_names (_${_PYTHON_PREFIX}_VERSION_NAMES ${_${_PYTHON_PREFIX}_LIB_VERSION} DEBUG) + _python_get_names (_${_PYTHON_PREFIX}_VERSION_NAMES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} WIN32 DEBUG) list (APPEND _${_PYTHON_PREFIX}_LIB_NAMES_DEBUG ${_${_PYTHON_PREFIX}_VERSION_NAMES}) # Framework Paths @@ -1219,7 +1510,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS list (APPEND _${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_VERSION_PATHS}) # Paths suffixes - _python_get_path_suffixes (_${_PYTHON_PREFIX}_VERSION_PATHS ${_${_PYTHON_PREFIX}_LIB_VERSION} LIBRARY) + _python_get_path_suffixes (_${_PYTHON_PREFIX}_VERSION_PATHS VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} LIBRARY) list (APPEND _${_PYTHON_PREFIX}_PATH_SUFFIXES ${_${_PYTHON_PREFIX}_VERSION_PATHS}) endforeach() @@ -1228,7 +1519,8 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} + PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} + ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH @@ -1241,7 +1533,8 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} + PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} + ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) @@ -1252,6 +1545,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} + PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) @@ -1289,7 +1583,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS # search for debug library if (${_PYTHON_PREFIX}_LIBRARY_RELEASE) # use library location as a hint - _python_get_lib_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG ${_${_PYTHON_PREFIX}_VERSION} DEBUG) + _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG VERSION ${_${_PYTHON_PREFIX}_VERSION} WIN32 DEBUG) get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY) find_library (${_PYTHON_PREFIX}_LIBRARY_DEBUG NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG} @@ -1303,7 +1597,8 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} + PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} + ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES lib libs NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) @@ -1313,7 +1608,8 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${__${_PYTHON_PREFIX}_REGISTRY_PATHS} + PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} + ${__${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES lib libs) # extract version from library name @@ -1326,20 +1622,21 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() else() foreach (_${_PYTHON_PREFIX}_LIB_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) - _python_get_lib_names (_${_PYTHON_PREFIX}_LIB_NAMES ${_${_PYTHON_PREFIX}_LIB_VERSION}) - _python_get_lib_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG ${_${_PYTHON_PREFIX}_LIB_VERSION} DEBUG) + _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} WIN32 POSIX LIBRARY) + _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} WIN32 DEBUG) _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_LIB_VERSION}) _python_get_registries (_${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_LIB_VERSION}) - _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES ${_${_PYTHON_PREFIX}_LIB_VERSION} LIBRARY) + _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} LIBRARY) if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} + PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} + ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH @@ -1352,7 +1649,8 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} + PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} + ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) @@ -1363,6 +1661,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} + PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) @@ -1404,7 +1703,8 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} + PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} + ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES lib libs NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) @@ -1414,7 +1714,8 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${__${_PYTHON_PREFIX}_REGISTRY_PATHS} + PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} + ${__${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES lib libs) endif() endif() @@ -1428,7 +1729,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS # retrieve runtime libraries if (${_PYTHON_PREFIX}_LIBRARY_RELEASE) - _python_get_lib_names (_${_PYTHON_PREFIX}_LIB_NAMES ${_${_PYTHON_PREFIX}_VERSION}) + _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} WIN32 POSIX LIBRARY) get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY) get_filename_component (_${_PYTHON_PREFIX}_PATH2 "${_${_PYTHON_PREFIX}_PATH}" DIRECTORY) _python_find_runtime_library (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE @@ -1438,7 +1739,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS PATH_SUFFIXES bin) endif() if (${_PYTHON_PREFIX}_LIBRARY_DEBUG) - _python_get_lib_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG ${_${_PYTHON_PREFIX}_VERSION} DEBUG) + _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG VERSION ${_${_PYTHON_PREFIX}_VERSION} WIN32 DEBUG) get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}" DIRECTORY) get_filename_component (_${_PYTHON_PREFIX}_PATH2 "${_${_PYTHON_PREFIX}_PATH}" DIRECTORY) _python_find_runtime_library (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG @@ -1452,20 +1753,6 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS if (${_PYTHON_PREFIX}_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG) unset (_${_PYTHON_PREFIX}_INCLUDE_HINTS) - if (${_PYTHON_PREFIX}_EXECUTABLE) - # pick up include directory from configuration - execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys; import sysconfig; sys.stdout.write(sysconfig.get_path('include'))" - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE _${_PYTHON_PREFIX}_PATH - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (NOT _${_PYTHON_PREFIX}_RESULT) - file (TO_CMAKE_PATH "${_${_PYTHON_PREFIX}_PATH}" _${_PYTHON_PREFIX}_PATH) - list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${_${_PYTHON_PREFIX}_PATH}") - endif() - endif() - foreach (_${_PYTHON_PREFIX}_LIB IN ITEMS ${_PYTHON_PREFIX}_LIBRARY_RELEASE ${_PYTHON_PREFIX}_LIBRARY_DEBUG) if (${_${_PYTHON_PREFIX}_LIB}) # Use the library's install prefix as a hint @@ -1487,13 +1774,14 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION}) _python_get_registries (_${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_VERSION}) - _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES ${_${_PYTHON_PREFIX}_VERSION} INCLUDE) + _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES VERSION ${_${_PYTHON_PREFIX}_VERSION} INCLUDE) if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") find_path (${_PYTHON_PREFIX}_INCLUDE_DIR NAMES Python.h HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} + PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} + ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH @@ -1505,7 +1793,8 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS find_path (${_PYTHON_PREFIX}_INCLUDE_DIR NAMES Python.h HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} + PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} + ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) @@ -1526,7 +1815,8 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS find_path (${_PYTHON_PREFIX}_INCLUDE_DIR NAMES Python.h HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS} - PATHS ${__${_PYTHON_PREFIX}_FRAMEWORK_PATHS} + PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} + ${__${_PYTHON_PREFIX}_FRAMEWORK_PATHS} ${__${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} NO_SYSTEM_ENVIRONMENT_PATH @@ -1725,20 +2015,10 @@ if(_${_PYTHON_PREFIX}_CMAKE_ROLE STREQUAL "PROJECT") endif() endif() - if (_${_PYTHON_PREFIX}_CONFIG AND _${_PYTHON_PREFIX}_LIBRARY_TYPE STREQUAL "STATIC") + if (_${_PYTHON_PREFIX}_LIBRARY_TYPE STREQUAL "STATIC") # extend link information with dependent libraries - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --ldflags - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE _${_PYTHON_PREFIX}_FLAGS - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (NOT _${_PYTHON_PREFIX}_RESULT) - string (REGEX MATCHALL "-[Ll][^ ]+" _${_PYTHON_PREFIX}_LINK_LIBRARIES "${_${_PYTHON_PREFIX}_FLAGS}") - # remove elements relative to python library itself - list (FILTER _${_PYTHON_PREFIX}_LINK_LIBRARIES EXCLUDE REGEX "-lpython") - foreach (_${_PYTHON_PREFIX}_DIR IN LISTS ${_PYTHON_PREFIX}_LIBRARY_DIRS) - list (FILTER _${_PYTHON_PREFIX}_LINK_LIBRARIES EXCLUDE REGEX "-L${${_PYTHON_PREFIX}_DIR}") - endforeach() + _python_get_config_var (_${_PYTHON_PREFIX}_LINK_LIBRARIES LIBS) + if (_${_PYTHON_PREFIX}_LINK_LIBRARIES) set_property (TARGET ${__name} PROPERTY INTERFACE_LINK_LIBRARIES ${_${_PYTHON_PREFIX}_LINK_LIBRARIES}) endif() diff --git a/Modules/FindPython2.cmake b/Modules/FindPython2.cmake index 8372ce7..82878ea 100644 --- a/Modules/FindPython2.cmake +++ b/Modules/FindPython2.cmake @@ -193,6 +193,12 @@ Hints ``NEVER`` to select preferably the interpreter from the virtual environment. + .. note:: + + If the component ``Development`` is requested, it is **strongly** + recommended to also include the component ``Interpreter`` to get expected + result. + Commands ^^^^^^^^ diff --git a/Modules/FindPython3.cmake b/Modules/FindPython3.cmake index 2ead5b6..417a789 100644 --- a/Modules/FindPython3.cmake +++ b/Modules/FindPython3.cmake @@ -138,6 +138,47 @@ Hints * If set to TRUE, search **only** for static libraries. * If set to FALSE, search **only** for shared libraries. +``Python3_FIND_ABI`` + This variable defines which ABIs, as defined in + `PEP 3149 <https://www.python.org/dev/peps/pep-3149/>`_, should be searched. + + .. note:: + + If ``Python3_FIND_ABI`` is not defined, any ABI will be searched. + + The ``Python3_FIND_ABI`` variable is a 3-tuple specifying, in that order, + ``pydebug`` (``d``), ``pymalloc`` (``m``) and ``unicode`` (``u``) flags. + Each element can be set to one of the following: + + * ``ON``: Corresponding flag is selected. + * ``OFF``: Corresponding flag is not selected. + * ``ANY``: The two posibilties (``ON`` and ``OFF``) will be searched. + + From this 3-tuple, various ABIs will be searched starting from the most + specialized to the most general. Moreover, ``debug`` versions will be + searched **after** ``non-debug`` ones. + + For example, if we have:: + + set (Python3_FIND_ABI "ON" "ANY" "ANY") + + The following flags combinations will be appended, in that order, to the + artifact names: ``dmu``, ``dm``, ``du``, and ``d``. + + And to search any possible ABIs:: + + set (Python3_FIND_ABI "ANY" "ANY" "ANY") + + The following combinations, in that order, will be used: ``mu``, ``m``, + ``u``, ``<empty>``, ``dmu``, ``dm``, ``du`` and ``d``. + + .. note:: + + This hint is useful only on ``POSIX`` systems. So, on ``Windows`` systems, + when ``Python3_FIND_ABI`` is defined, ``Python`` distributions from + `python.org <https://www.python.org/>`_ will be found only if value for + each flag is ``OFF`` or ``ANY``. + ``Python3_FIND_STRATEGY`` This variable defines how lookup will be done. The ``Python3_FIND_STRATEGY`` variable can be set to empty or one of the @@ -193,6 +234,12 @@ Hints ``NEVER`` to select preferably the interpreter from the virtual environment. + .. note:: + + If the component ``Development`` is requested, it is **strongly** + recommended to also include the component ``Interpreter`` to get expected + result. + Commands ^^^^^^^^ diff --git a/Modules/FindPythonInterp.cmake b/Modules/FindPythonInterp.cmake index da33301..ccc7d5b 100644 --- a/Modules/FindPythonInterp.cmake +++ b/Modules/FindPythonInterp.cmake @@ -39,6 +39,15 @@ If calling both ``find_package(PythonInterp)`` and ``find_package(PythonLibs)``, call ``find_package(PythonInterp)`` first to get the currently active Python version by default with a consistent version of PYTHON_LIBRARIES. + +.. note:: + + A call to ``find_package(PythonInterp ${V})`` for python version ``V`` + may find a ``python`` executable with no version suffix. In this case + no attempt is made to avoid python executables from other versions. + Use :module:`FindPython3`, :module:`FindPython2` or :module:`FindPython` + instead. + #]=======================================================================] unset(_Python_NAMES) diff --git a/Modules/FindQt4.cmake b/Modules/FindQt4.cmake index a145b46..3993968 100644 --- a/Modules/FindQt4.cmake +++ b/Modules/FindQt4.cmake @@ -670,7 +670,7 @@ if (QT_QMAKE_EXECUTABLE AND get_filename_component(qt_headers "${QT_QTCORE_INCLUDE_DIR}/../" ABSOLUTE) set(QT_HEADERS_DIR "${qt_headers}" CACHE INTERNAL "" FORCE) endif() - elseif() + else() message("Warning: QT_QMAKE_EXECUTABLE reported QT_INSTALL_HEADERS as ${qt_headers}") message("Warning: But QtCore couldn't be found. Qt must NOT be installed correctly.") endif() diff --git a/Modules/FindVulkan.cmake b/Modules/FindVulkan.cmake index ae8d72d..55da55f 100644 --- a/Modules/FindVulkan.cmake +++ b/Modules/FindVulkan.cmake @@ -5,7 +5,7 @@ FindVulkan ---------- -Find Vulkan, which isis a low-overhead, cross-platform 3D graphics +Find Vulkan, which is a low-overhead, cross-platform 3D graphics and computing API. IMPORTED Targets diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake index 5be4676..57ae446 100644 --- a/Modules/GetPrerequisites.cmake +++ b/Modules/GetPrerequisites.cmake @@ -5,6 +5,10 @@ GetPrerequisites ---------------- +.. deprecated:: 3.16 + + Use :command:`file(GET_RUNTIME_DEPENDENCIES)` instead. + Functions to analyze and list executable file prerequisites. This module provides functions to list the .dll, .dylib or .so files @@ -706,7 +710,9 @@ function(get_prerequisites target prerequisites_var exclude_system recurse exepa find_program(gp_dumpbin "dumpbin" PATHS ${gp_cmd_paths}) if(gp_dumpbin) set(gp_tool "dumpbin") - else() # Try harder. Maybe we're on MinGW + elseif(CMAKE_OBJDUMP) # Try harder. Maybe we're on MinGW + set(gp_tool "${CMAKE_OBJDUMP}") + else() set(gp_tool "objdump") endif() endif() @@ -723,7 +729,7 @@ function(get_prerequisites target prerequisites_var exclude_system recurse exepa if(gp_tool MATCHES "ldd$") set(gp_cmd_args "") - set(gp_regex "^[\t ]*[^\t ]+ => ([^\t\(]+) .*${eol_char}$") + set(gp_regex "^[\t ]*[^\t ]+ =>[\t ]+([^\t\(]+)( \(.+\))?${eol_char}$") set(gp_regex_error "not found${eol_char}$") set(gp_regex_fallback "^[\t ]*([^\t ]+) => ([^\t ]+).*${eol_char}$") set(gp_regex_cmp_count 1) diff --git a/Modules/CPack.DS_Store.in b/Modules/Internal/CPack/CPack.DS_Store.in Binary files differindex 5be0eeb..5be0eeb 100644 --- a/Modules/CPack.DS_Store.in +++ b/Modules/Internal/CPack/CPack.DS_Store.in diff --git a/Modules/CPack.Description.plist.in b/Modules/Internal/CPack/CPack.Description.plist.in index 3d11476..3d11476 100644 --- a/Modules/CPack.Description.plist.in +++ b/Modules/Internal/CPack/CPack.Description.plist.in diff --git a/Modules/CPack.Info.plist.in b/Modules/Internal/CPack/CPack.Info.plist.in index 6e32500..6e32500 100644 --- a/Modules/CPack.Info.plist.in +++ b/Modules/Internal/CPack/CPack.Info.plist.in diff --git a/Modules/CPack.NuGet.nuspec.in b/Modules/Internal/CPack/CPack.NuGet.nuspec.in index b7beb5d..b7beb5d 100644 --- a/Modules/CPack.NuGet.nuspec.in +++ b/Modules/Internal/CPack/CPack.NuGet.nuspec.in diff --git a/Modules/CPack.OSXScriptLauncher.in b/Modules/Internal/CPack/CPack.OSXScriptLauncher.in Binary files differindex c715860..c715860 100755..100644 --- a/Modules/CPack.OSXScriptLauncher.in +++ b/Modules/Internal/CPack/CPack.OSXScriptLauncher.in diff --git a/Modules/CPack.OSXScriptLauncher.rsrc.in b/Modules/Internal/CPack/CPack.OSXScriptLauncher.rsrc.in Binary files differindex 5f5f17a..5f5f17a 100644 --- a/Modules/CPack.OSXScriptLauncher.rsrc.in +++ b/Modules/Internal/CPack/CPack.OSXScriptLauncher.rsrc.in diff --git a/Modules/CPack.OSXX11.Info.plist.in b/Modules/Internal/CPack/CPack.OSXX11.Info.plist.in index 23a1483..23a1483 100644 --- a/Modules/CPack.OSXX11.Info.plist.in +++ b/Modules/Internal/CPack/CPack.OSXX11.Info.plist.in diff --git a/Modules/CPack.OSXX11.main.scpt.in b/Modules/Internal/CPack/CPack.OSXX11.main.scpt.in Binary files differindex de30ea1..de30ea1 100644 --- a/Modules/CPack.OSXX11.main.scpt.in +++ b/Modules/Internal/CPack/CPack.OSXX11.main.scpt.in diff --git a/Modules/CPack.RuntimeScript.in b/Modules/Internal/CPack/CPack.RuntimeScript.in index f27444f..f27444f 100755 --- a/Modules/CPack.RuntimeScript.in +++ b/Modules/Internal/CPack/CPack.RuntimeScript.in diff --git a/Modules/CPack.STGZ_Header.sh.in b/Modules/Internal/CPack/CPack.STGZ_Header.sh.in index 70f63d2..a857aa5 100755 --- a/Modules/CPack.STGZ_Header.sh.in +++ b/Modules/Internal/CPack/CPack.STGZ_Header.sh.in @@ -43,10 +43,10 @@ for a in "$@CPACK_AT_SIGN@"; do cpack_prefix_dir=`cpack_fix_slashes "${cpack_prefix_dir}"` fi if echo $a | grep "^--help" > /dev/null 2> /dev/null; then - cpack_usage + cpack_usage fi if echo $a | grep "^--version" > /dev/null 2> /dev/null; then - cpack_version + cpack_version exit 2 fi if echo $a | grep "^--include-subdir" > /dev/null 2> /dev/null; then @@ -86,15 +86,19 @@ then @CPACK_RESOURCE_FILE_LICENSE_CONTENT@ ____cpack__here_doc____ echo - echo "Do you accept the license? [yN]: " - read line leftover - case ${line} in - y* | Y*) - cpack_license_accepted=TRUE;; - *) - echo "License not accepted. Exiting ..." - exit 1;; - esac + while true + do + echo "Do you accept the license? [yn]: " + read line leftover + case ${line} in + y* | Y*) + cpack_license_accepted=TRUE + break;; + n* | N* | q* | Q* | e* | E*) + echo "License not accepted. Exiting ..." + exit 1;; + esac + done fi if [ "x${cpack_include_subdir}x" = "xx" ] @@ -143,4 +147,3 @@ exit 0 #----------------------------------------------------------- # Start of TAR.GZ file #-----------------------------------------------------------; - diff --git a/Modules/CPack.VolumeIcon.icns.in b/Modules/Internal/CPack/CPack.VolumeIcon.icns.in Binary files differindex c59217e..c59217e 100644 --- a/Modules/CPack.VolumeIcon.icns.in +++ b/Modules/Internal/CPack/CPack.VolumeIcon.icns.in diff --git a/Modules/CPack.background.png.in b/Modules/Internal/CPack/CPack.background.png.in Binary files differindex a32ab37..a32ab37 100644 --- a/Modules/CPack.background.png.in +++ b/Modules/Internal/CPack/CPack.background.png.in diff --git a/Modules/CPack.distribution.dist.in b/Modules/Internal/CPack/CPack.distribution.dist.in index f20e66c..f20e66c 100644 --- a/Modules/CPack.distribution.dist.in +++ b/Modules/Internal/CPack/CPack.distribution.dist.in diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake index 89dc6f0..7791822 100644 --- a/Modules/Internal/CPack/CPackDeb.cmake +++ b/Modules/Internal/CPack/CPackDeb.cmake @@ -45,7 +45,7 @@ function(extract_so_info shared_object libname version) ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) if(result EQUAL 0) - string(REGEX MATCH "\\(SONAME\\)[^\n]*\\[([^\n]+)\\.so\\.([^\n]*)\\]" soname "${output}") + string(REGEX MATCH "\\(?SONAME\\)?[^\n]*\\[([^\n]+)\\.so\\.([^\n]*)\\]" soname "${output}") set(${libname} "${CMAKE_MATCH_1}" PARENT_SCOPE) set(${version} "${CMAKE_MATCH_2}" PARENT_SCOPE) else() diff --git a/Modules/Internal/CPack/CPackNuGet.cmake b/Modules/Internal/CPack/CPackNuGet.cmake index 4b2ce92..82053b2 100644 --- a/Modules/Internal/CPack/CPackNuGet.cmake +++ b/Modules/Internal/CPack/CPackNuGet.cmake @@ -262,7 +262,7 @@ function(_cpack_nuget_render_spec) # NuGet will name it properly. _cpack_nuget_debug("Rendering `${CPACK_TEMPORARY_DIRECTORY}/CPack.NuGet.nuspec` file...") configure_file( - "${CMAKE_ROOT}/Modules/CPack.NuGet.nuspec.in" + "${CMAKE_ROOT}/Modules/Internal/CPack/CPack.NuGet.nuspec.in" "${CPACK_TEMPORARY_DIRECTORY}/CPack.NuGet.nuspec" @ONLY ) diff --git a/Modules/NSIS.InstallOptions.ini.in b/Modules/Internal/CPack/NSIS.InstallOptions.ini.in index d92d779..d92d779 100644 --- a/Modules/NSIS.InstallOptions.ini.in +++ b/Modules/Internal/CPack/NSIS.InstallOptions.ini.in diff --git a/Modules/NSIS.template.in b/Modules/Internal/CPack/NSIS.template.in index f75ae78..f75ae78 100644 --- a/Modules/NSIS.template.in +++ b/Modules/Internal/CPack/NSIS.template.in diff --git a/Modules/WIX.template.in b/Modules/Internal/CPack/WIX.template.in index c4fc83a..c4fc83a 100644 --- a/Modules/WIX.template.in +++ b/Modules/Internal/CPack/WIX.template.in diff --git a/Modules/Platform/AIX-GNU.cmake b/Modules/Platform/AIX-GNU.cmake index 0abbb61..61d213a 100644 --- a/Modules/Platform/AIX-GNU.cmake +++ b/Modules/Platform/AIX-GNU.cmake @@ -8,23 +8,26 @@ if(__AIX_COMPILER_GNU) endif() set(__AIX_COMPILER_GNU 1) -# -# By default, runtime linking is enabled. All shared objects specified on the command line -# will be listed, even if there are no symbols referenced, in the output file. -string(APPEND CMAKE_SHARED_LINKER_FLAGS_INIT " -Wl,-brtl") -string(APPEND CMAKE_MODULE_LINKER_FLAGS_INIT " -Wl,-brtl") -string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " -Wl,-brtl") - - macro(__aix_compiler_gnu lang) set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG "-Wl,-blibpath:") set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG_SEP ":") - string(APPEND CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS " -Wl,-G,-bnoipath") - set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-Wl,-bexpall") + string(APPEND CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS " -Wl,-bnoipath") + set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-Wl,-bexpall") # CMP0065 old behavior set(CMAKE_${lang}_USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH 1) set(CMAKE_${lang}_LINK_FLAGS "-Wl,-bnoipath") if(CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 7 OR CMAKE_SYSTEM_VERSION VERSION_LESS 7.1) unset(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY) endif() + + # Construct the export list ourselves to pass only the object files so + # that we export only the symbols actually provided by the sources. + set(CMAKE_${lang}_CREATE_SHARED_LIBRARY + "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/objects.exp <OBJECTS>" + "<CMAKE_${lang}_COMPILER> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> -Wl,-bE:<OBJECT_DIR>/objects.exp <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" + ) + + set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS + "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -l . <OBJECTS>" + "<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> -Wl,-bE:<TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>") endmacro() diff --git a/Modules/Platform/AIX-XL.cmake b/Modules/Platform/AIX-XL.cmake index 06a806b..64b0bc1 100644 --- a/Modules/Platform/AIX-XL.cmake +++ b/Modules/Platform/AIX-XL.cmake @@ -8,43 +8,24 @@ if(__AIX_COMPILER_XL) endif() set(__AIX_COMPILER_XL 1) -# -# By default, runtime linking is enabled. All shared objects specified on the command line -# will be listed, even if there are no symbols referenced, in the output file. -string(APPEND CMAKE_SHARED_LINKER_FLAGS_INIT " -Wl,-brtl") -string(APPEND CMAKE_MODULE_LINKER_FLAGS_INIT " -Wl,-brtl") -string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " -Wl,-brtl") - - macro(__aix_compiler_xl lang) set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG "-Wl,-blibpath:") set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG_SEP ":") - set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-G -Wl,-bnoipath") # -shared - set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-Wl,-bexpall") + string(APPEND CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS " -Wl,-bnoipath") + set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-Wl,-bexpall") # CMP0065 old behavior set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS " ") set(CMAKE_SHARED_MODULE_${lang}_FLAGS " ") set(CMAKE_${lang}_LINK_FLAGS "-Wl,-bnoipath") - # Find the CreateExportList program that comes with this toolchain. - find_program(CMAKE_XL_CreateExportList - NAMES CreateExportList - DOC "IBM XL CreateExportList tool" + # Construct the export list ourselves to pass only the object files so + # that we export only the symbols actually provided by the sources. + set(CMAKE_${lang}_CREATE_SHARED_LIBRARY + "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/objects.exp <OBJECTS>" + "<CMAKE_${lang}_COMPILER> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> -Wl,-bE:<OBJECT_DIR>/objects.exp <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" ) - # CMAKE_XL_CreateExportList is part of the AIX XL compilers but not the linux ones. - # If we found the tool, we'll use it to create exports, otherwise stick with the regular - # create shared library compile line. - if (CMAKE_XL_CreateExportList) - # The compiler front-end passes all object files, archive files, and shared - # library files named on the command line to CreateExportList to create a - # list of all symbols to be exported from the shared library. This causes - # all archive members to be copied into the shared library whether they are - # needed or not. Instead we run the tool ourselves to pass only the object - # files so that we export only the symbols actually provided by the sources. - set(CMAKE_${lang}_CREATE_SHARED_LIBRARY - "${CMAKE_XL_CreateExportList} <OBJECT_DIR>/objects.exp <OBJECTS>" - "<CMAKE_${lang}_COMPILER> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> -Wl,-bE:<OBJECT_DIR>/objects.exp <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" - ) - endif() + set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS + "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -l . <OBJECTS>" + "<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> -Wl,-bE:<TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>") endmacro() diff --git a/Modules/Platform/AIX.cmake b/Modules/Platform/AIX.cmake index 551a995..03cef51 100644 --- a/Modules/Platform/AIX.cmake +++ b/Modules/Platform/AIX.cmake @@ -1,5 +1,7 @@ set(CMAKE_SHARED_LIBRARY_PREFIX "lib") # lib set(CMAKE_SHARED_LIBRARY_SUFFIX ".so") # .so +set(CMAKE_AIX_IMPORT_FILE_PREFIX "") +set(CMAKE_AIX_IMPORT_FILE_SUFFIX ".imp") set(CMAKE_DL_LIBS "-lld") # RPATH support on AIX is called libpath. By default the runtime diff --git a/Modules/Platform/AIX/ExportImportList b/Modules/Platform/AIX/ExportImportList new file mode 100755 index 0000000..4f67ef5 --- /dev/null +++ b/Modules/Platform/AIX/ExportImportList @@ -0,0 +1,53 @@ +#!/bin/sh +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# This script is internal to CMake and meant only to be +# invoked by CMake-generated build systems on AIX. + +usage='usage: ExportImportList -o <out-file> [-l <lib>] [--] <objects>...' + +die() { + echo "$@" 1>&2; exit 1 +} + +# Process command-line arguments. +out='' +lib='' +while test "$#" != 0; do + case "$1" in + -l) shift; lib="$1" ;; + -o) shift; out="$1" ;; + --) shift; break ;; + -*) die "$usage" ;; + *) break ;; + esac + shift +done +test -n "$out" || die "$usage" + +# Collect symbols exported from all object files. +out_tmp="$out.tmp$$" +trap 'rm -f "$out_tmp"' EXIT INT TERM +for f in "$@"; do + dump -tov -X 32_64 "$f" | + awk ' + BEGIN { + V["EXPORTED"]=" export" + V["PROTECTED"]=" protected" + } + /^\[[0-9]+\]\tm +[^ ]+ +\.(text|data|bss) +[^ ]+ +(extern|weak) +(EXPORTED|PROTECTED| ) / { + if (!match($NF,/^(\.|__sinit|__sterm|__[0-9]+__)/)) { + print $NF V[$(NF-1)] + } + } + ' +done > "$out_tmp" + +# Generate the export/import file. +{ + if test -n "$lib"; then + echo "#! $lib" + fi + sort -u "$out_tmp" +} > "$out" diff --git a/Modules/Platform/Android-Clang.cmake b/Modules/Platform/Android-Clang.cmake index 9ed1e01..847178f 100644 --- a/Modules/Platform/Android-Clang.cmake +++ b/Modules/Platform/Android-Clang.cmake @@ -40,6 +40,9 @@ macro(__android_compiler_clang lang) endif() if(NOT CMAKE_${lang}_COMPILER_TARGET) set(CMAKE_${lang}_COMPILER_TARGET "${_ANDROID_ABI_CLANG_TARGET}") + if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED) + string(APPEND CMAKE_${lang}_COMPILER_TARGET "${CMAKE_SYSTEM_VERSION}") + endif() list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "--target=${CMAKE_${lang}_COMPILER_TARGET}") endif() endmacro() diff --git a/Modules/Platform/Android-Common.cmake b/Modules/Platform/Android-Common.cmake index f8b9346..1affcd0 100644 --- a/Modules/Platform/Android-Common.cmake +++ b/Modules/Platform/Android-Common.cmake @@ -47,7 +47,41 @@ if(CMAKE_ANDROID_NDK) endif() if(CMAKE_ANDROID_STL_TYPE) - if(CMAKE_ANDROID_NDK) + if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED) + if(CMAKE_ANDROID_STL_TYPE STREQUAL "system") + set(_ANDROID_STL_EXCEPTIONS 0) + set(_ANDROID_STL_RTTI 0) + macro(__android_stl lang) + string(APPEND CMAKE_${lang}_FLAGS_INIT " -stdlib=libstdc++") + endmacro() + elseif(CMAKE_ANDROID_STL_TYPE STREQUAL "c++_static") + set(_ANDROID_STL_EXCEPTIONS 1) + set(_ANDROID_STL_RTTI 1) + macro(__android_stl lang) + string(APPEND CMAKE_${lang}_FLAGS_INIT " -stdlib=libc++") + string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -static-libstdc++") + endmacro() + elseif(CMAKE_ANDROID_STL_TYPE STREQUAL "c++_shared") + set(_ANDROID_STL_EXCEPTIONS 1) + set(_ANDROID_STL_RTTI 1) + macro(__android_stl lang) + string(APPEND CMAKE_${lang}_FLAGS_INIT " -stdlib=libc++") + endmacro() + elseif(CMAKE_ANDROID_STL_TYPE STREQUAL "none") + set(_ANDROID_STL_RTTI 0) + set(_ANDROID_STL_EXCEPTIONS 0) + macro(__android_stl lang) + # FIXME: Add a way to add project-wide language-specific compile-only flags. + set(CMAKE_CXX_COMPILE_OBJECT + "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE> -nostdinc++") + string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -nostdlib++") + endmacro() + else() + message(FATAL_ERROR + "Android: STL '${CMAKE_ANDROID_STL_TYPE}' not supported by this NDK." + ) + endif() + elseif(CMAKE_ANDROID_NDK) macro(__android_stl_inc lang dir req) if(EXISTS "${dir}") @@ -152,6 +186,10 @@ macro(__android_compiler_common lang) __android_stl(CXX) endif() + if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED) + string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -latomic -lm") + endif() + # <ndk>/build/core/definitions.mk appends the sysroot's include directory # explicitly at the end of the command-line include path so that it # precedes the toolchain's builtin include directories. This is @@ -161,7 +199,7 @@ macro(__android_compiler_common lang) # # Do not do this for a standalone toolchain because it is already # tied to a specific API version. - if(CMAKE_ANDROID_NDK) + if(CMAKE_ANDROID_NDK AND NOT CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED) if(CMAKE_SYSROOT_COMPILE) set(_cmake_sysroot_compile "${CMAKE_SYSROOT_COMPILE}") else() @@ -170,7 +208,7 @@ macro(__android_compiler_common lang) if(NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS) list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES "${_cmake_sysroot_compile}/usr/include" - "${_cmake_sysroot_compile}/usr/include/${CMAKE_ANDROID_ARCH_HEADER_TRIPLE}" + "${_cmake_sysroot_compile}/usr/include/${CMAKE_ANDROID_ARCH_TRIPLE}" ) else() list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES "${_cmake_sysroot_compile}/usr/include") diff --git a/Modules/Platform/Android-Determine.cmake b/Modules/Platform/Android-Determine.cmake index bb42eed..e7c1b48 100644 --- a/Modules/Platform/Android-Determine.cmake +++ b/Modules/Platform/Android-Determine.cmake @@ -198,32 +198,66 @@ if(NOT CMAKE_SYSTEM_VERSION MATCHES "^[0-9]+$") message(FATAL_ERROR "Android: The API specified by CMAKE_SYSTEM_VERSION='${CMAKE_SYSTEM_VERSION}' is not an integer.") endif() +if(CMAKE_ANDROID_NDK) + # Identify the host platform. + if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64") + set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "darwin-x86_64") + else() + set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "darwin-x86") + endif() + elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64") + set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "linux-x86_64") + else() + set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "linux-x86") + endif() + elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64") + set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "windows-x86_64") + else() + set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "windows") + endif() + else() + message(FATAL_ERROR "Android: Builds hosted on '${CMAKE_HOST_SYSTEM_NAME}' not supported.") + endif() + + # Look for a unified toolchain/sysroot provided with the NDK. + set(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED "${CMAKE_ANDROID_NDK}/toolchains/llvm/prebuilt/${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}") + if(NOT IS_DIRECTORY "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/sysroot") + set(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED "") + endif() +else() + set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "") + set(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED "") +endif() + # https://developer.android.com/ndk/guides/abis.html set(_ANDROID_ABI_arm64-v8a_PROC "aarch64") set(_ANDROID_ABI_arm64-v8a_ARCH "arm64") -set(_ANDROID_ABI_arm64-v8a_HEADER "aarch64-linux-android") +set(_ANDROID_ABI_arm64-v8a_TRIPLE "aarch64-linux-android") set(_ANDROID_ABI_armeabi-v7a_PROC "armv7-a") set(_ANDROID_ABI_armeabi-v7a_ARCH "arm") -set(_ANDROID_ABI_armeabi-v7a_HEADER "arm-linux-androideabi") +set(_ANDROID_ABI_armeabi-v7a_TRIPLE "arm-linux-androideabi") set(_ANDROID_ABI_armeabi-v6_PROC "armv6") set(_ANDROID_ABI_armeabi-v6_ARCH "arm") -set(_ANDROID_ABI_armeabi-v6_HEADER "arm-linux-androideabi") +set(_ANDROID_ABI_armeabi-v6_TRIPLE "arm-linux-androideabi") set(_ANDROID_ABI_armeabi_PROC "armv5te") set(_ANDROID_ABI_armeabi_ARCH "arm") -set(_ANDROID_ABI_armeabi_HEADER "arm-linux-androideabi") +set(_ANDROID_ABI_armeabi_TRIPLE "arm-linux-androideabi") set(_ANDROID_ABI_mips_PROC "mips") set(_ANDROID_ABI_mips_ARCH "mips") -set(_ANDROID_ABI_mips_HEADER "mipsel-linux-android") +set(_ANDROID_ABI_mips_TRIPLE "mipsel-linux-android") set(_ANDROID_ABI_mips64_PROC "mips64") set(_ANDROID_ABI_mips64_ARCH "mips64") -set(_ANDROID_ABI_mips64_HEADER "mips64el-linux-android") +set(_ANDROID_ABI_mips64_TRIPLE "mips64el-linux-android") set(_ANDROID_ABI_x86_PROC "i686") set(_ANDROID_ABI_x86_ARCH "x86") -set(_ANDROID_ABI_x86_HEADER "i686-linux-android") +set(_ANDROID_ABI_x86_TRIPLE "i686-linux-android") set(_ANDROID_ABI_x86_64_PROC "x86_64") set(_ANDROID_ABI_x86_64_ARCH "x86_64") -set(_ANDROID_ABI_x86_64_HEADER "x86_64-linux-android") +set(_ANDROID_ABI_x86_64_TRIPLE "x86_64-linux-android") set(_ANDROID_PROC_aarch64_ARCH_ABI "arm64-v8a") set(_ANDROID_PROC_armv7-a_ARCH_ABI "armeabi-v7a") @@ -308,7 +342,7 @@ if(_ANDROID_SYSROOT_ARCH AND NOT "x${_ANDROID_SYSROOT_ARCH}" STREQUAL "x${CMAKE_ "does not match architecture '${CMAKE_ANDROID_ARCH}' for the ABI '${CMAKE_ANDROID_ARCH_ABI}'." ) endif() -set(CMAKE_ANDROID_ARCH_HEADER_TRIPLE "${_ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_HEADER}") +set(CMAKE_ANDROID_ARCH_TRIPLE "${_ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_TRIPLE}") # Select a processor. if(NOT CMAKE_SYSTEM_PROCESSOR) @@ -321,7 +355,7 @@ if(NOT _ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_PROC STREQUAL CMAKE_SYSTEM_PROCESS endif() if(CMAKE_ANDROID_NDK AND NOT DEFINED CMAKE_ANDROID_NDK_DEPRECATED_HEADERS) - if(IS_DIRECTORY "${CMAKE_ANDROID_NDK}/sysroot/usr/include/${CMAKE_ANDROID_ARCH_HEADER_TRIPLE}") + if(IS_DIRECTORY "${CMAKE_ANDROID_NDK}/sysroot/usr/include/${CMAKE_ANDROID_ARCH_TRIPLE}") # Unified headers exist so we use them by default. set(CMAKE_ANDROID_NDK_DEPRECATED_HEADERS 0) else() @@ -340,8 +374,10 @@ set(CMAKE_ANDROID_ARCH_ABI \"${CMAKE_ANDROID_ARCH_ABI}\") if(CMAKE_ANDROID_NDK) string(APPEND CMAKE_SYSTEM_CUSTOM_CODE - "set(CMAKE_ANDROID_ARCH_HEADER_TRIPLE \"${CMAKE_ANDROID_ARCH_HEADER_TRIPLE}\")\n" + "set(CMAKE_ANDROID_ARCH_TRIPLE \"${CMAKE_ANDROID_ARCH_TRIPLE}\")\n" "set(CMAKE_ANDROID_NDK_DEPRECATED_HEADERS \"${CMAKE_ANDROID_NDK_DEPRECATED_HEADERS}\")\n" + "set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG \"${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}\")\n" + "set(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED \"${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}\")\n" ) endif() diff --git a/Modules/Platform/Android-Initialize.cmake b/Modules/Platform/Android-Initialize.cmake index a434f90..a5d2820 100644 --- a/Modules/Platform/Android-Initialize.cmake +++ b/Modules/Platform/Android-Initialize.cmake @@ -17,6 +17,13 @@ if(CMAKE_SYSTEM_VERSION EQUAL 1) return() endif() +set(CMAKE_BUILD_TYPE_INIT Debug) + +# Skip sysroot selection if the NDK has a unified toolchain. +if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED) + return() +endif() + if(NOT CMAKE_SYSROOT) if(CMAKE_ANDROID_NDK) set(CMAKE_SYSROOT "${CMAKE_ANDROID_NDK}/platforms/android-${CMAKE_SYSTEM_VERSION}/arch-${CMAKE_ANDROID_ARCH}") @@ -40,5 +47,3 @@ else() "Android: No CMAKE_SYSROOT was selected." ) endif() - -set(CMAKE_BUILD_TYPE_INIT Debug) diff --git a/Modules/Platform/Android/Determine-Compiler-NDK.cmake b/Modules/Platform/Android/Determine-Compiler-NDK.cmake index 5f2cc52..e009c10 100644 --- a/Modules/Platform/Android/Determine-Compiler-NDK.cmake +++ b/Modules/Platform/Android/Determine-Compiler-NDK.cmake @@ -1,6 +1,31 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. +# In Android NDK r19 and above there is a single clang toolchain. +if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED) + if(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION AND NOT CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION STREQUAL "clang") + message(FATAL_ERROR + "Android: The CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION value '${CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION}' " + "is not supported by this NDK. It must be 'clang' or not set at all." + ) + endif() + message(STATUS "Android: Selected unified Clang toolchain") + set(_ANDROID_TOOL_NDK_TOOLCHAIN_VERSION "clang") + set(_ANDROID_TOOL_C_COMPILER "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin/clang${_ANDROID_HOST_EXT}") + set(_ANDROID_TOOL_C_TOOLCHAIN_MACHINE "${CMAKE_ANDROID_ARCH_TRIPLE}") + set(_ANDROID_TOOL_C_TOOLCHAIN_VERSION "") + set(_ANDROID_TOOL_C_COMPILER_EXTERNAL_TOOLCHAIN "") + set(_ANDROID_TOOL_C_TOOLCHAIN_PREFIX "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin/${CMAKE_ANDROID_ARCH_TRIPLE}-") + set(_ANDROID_TOOL_C_TOOLCHAIN_SUFFIX "${_ANDROID_HOST_EXT}") + set(_ANDROID_TOOL_CXX_COMPILER "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin/clang++${_ANDROID_HOST_EXT}") + set(_ANDROID_TOOL_CXX_TOOLCHAIN_MACHINE "${CMAKE_ANDROID_ARCH_TRIPLE}") + set(_ANDROID_TOOL_CXX_TOOLCHAIN_VERSION "") + set(_ANDROID_TOOL_CXX_COMPILER_EXTERNAL_TOOLCHAIN "") + set(_ANDROID_TOOL_CXX_TOOLCHAIN_PREFIX "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin/${CMAKE_ANDROID_ARCH_TRIPLE}-") + set(_ANDROID_TOOL_CXX_TOOLCHAIN_SUFFIX "${_ANDROID_HOST_EXT}") + return() +endif() + # In Android NDK releases there is build system toolchain selection logic in # these files: # @@ -195,40 +220,16 @@ if(NOT _ANDROID_TOOL_PREFIX AND "${_ANDROID_TOOL_NAME}" MATCHES "^(.*-)[0-9.]+$" set(_ANDROID_TOOL_PREFIX "${CMAKE_MATCH_1}") endif() -# Identify the host platform. -if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") - if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64") - set(_ANDROID_HOST_DIR "darwin-x86_64") - else() - set(_ANDROID_HOST_DIR "darwin-x86") - endif() -elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") - if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64") - set(_ANDROID_HOST_DIR "linux-x86_64") - else() - set(_ANDROID_HOST_DIR "linux-x86") - endif() -elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") - if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64") - set(_ANDROID_HOST_DIR "windows-x86_64") - else() - set(_ANDROID_HOST_DIR "windows") - endif() -else() - message(FATAL_ERROR "Android: Builds hosted on '${CMAKE_HOST_SYSTEM_NAME}' not supported.") -endif() - # Help CMakeFindBinUtils locate things. set(_CMAKE_TOOLCHAIN_PREFIX "${_ANDROID_TOOL_PREFIX}") -set(_ANDROID_TOOL_NDK_TOOLCHAIN_HOST_TAG "${_ANDROID_HOST_DIR}") set(_ANDROID_TOOL_NDK_TOOLCHAIN_VERSION "${_ANDROID_TOOL_VERS_NDK}") # _ANDROID_TOOL_PREFIX should now match `gcc -dumpmachine`. string(REGEX REPLACE "-$" "" _ANDROID_TOOL_C_TOOLCHAIN_MACHINE "${_ANDROID_TOOL_PREFIX}") set(_ANDROID_TOOL_C_TOOLCHAIN_VERSION "${_ANDROID_TOOL_VERS}") -set(_ANDROID_TOOL_C_TOOLCHAIN_PREFIX "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_NAME}/prebuilt/${_ANDROID_HOST_DIR}/bin/${_ANDROID_TOOL_PREFIX}") +set(_ANDROID_TOOL_C_TOOLCHAIN_PREFIX "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_NAME}/prebuilt/${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}/bin/${_ANDROID_TOOL_PREFIX}") set(_ANDROID_TOOL_C_TOOLCHAIN_SUFFIX "${_ANDROID_HOST_EXT}") set(_ANDROID_TOOL_CXX_TOOLCHAIN_MACHINE "${_ANDROID_TOOL_C_TOOLCHAIN_MACHINE}") @@ -238,9 +239,9 @@ set(_ANDROID_TOOL_CXX_TOOLCHAIN_SUFFIX "${_ANDROID_TOOL_C_TOOLCHAIN_SUFFIX}") if(_ANDROID_TOOL_CLANG_NAME) message(STATUS "Android: Selected Clang toolchain '${_ANDROID_TOOL_CLANG_NAME}' with GCC toolchain '${_ANDROID_TOOL_NAME}'") - set(_ANDROID_TOOL_C_COMPILER "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_LLVM_NAME}/prebuilt/${_ANDROID_HOST_DIR}/bin/clang${_ANDROID_HOST_EXT}") - set(_ANDROID_TOOL_C_COMPILER_EXTERNAL_TOOLCHAIN ${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_NAME}/prebuilt/${_ANDROID_HOST_DIR}) - set(_ANDROID_TOOL_CXX_COMPILER "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_LLVM_NAME}/prebuilt/${_ANDROID_HOST_DIR}/bin/clang++${_ANDROID_HOST_EXT}") + set(_ANDROID_TOOL_C_COMPILER "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_LLVM_NAME}/prebuilt/${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}/bin/clang${_ANDROID_HOST_EXT}") + set(_ANDROID_TOOL_C_COMPILER_EXTERNAL_TOOLCHAIN ${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_NAME}/prebuilt/${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}) + set(_ANDROID_TOOL_CXX_COMPILER "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_LLVM_NAME}/prebuilt/${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}/bin/clang++${_ANDROID_HOST_EXT}") set(_ANDROID_TOOL_CXX_COMPILER_EXTERNAL_TOOLCHAIN "${_ANDROID_TOOL_C_COMPILER_EXTERNAL_TOOLCHAIN}") else() message(STATUS "Android: Selected GCC toolchain '${_ANDROID_TOOL_NAME}'") @@ -267,4 +268,3 @@ unset(_ANDROID_TOOL_PREFIX) unset(_ANDROID_TOOL_CLANG_NAME) unset(_ANDROID_TOOL_CLANG_VERS) unset(_ANDROID_TOOL_LLVM_NAME) -unset(_ANDROID_HOST_DIR) diff --git a/Modules/Platform/Android/Determine-Compiler-Standalone.cmake b/Modules/Platform/Android/Determine-Compiler-Standalone.cmake index 4c1ac1f..5095aff 100644 --- a/Modules/Platform/Android/Determine-Compiler-Standalone.cmake +++ b/Modules/Platform/Android/Determine-Compiler-Standalone.cmake @@ -62,5 +62,4 @@ else() set(_ANDROID_TOOL_CXX_COMPILER_EXTERNAL_TOOLCHAIN "") endif() -set(_ANDROID_TOOL_NDK_TOOLCHAIN_HOST_TAG "") set(_ANDROID_TOOL_NDK_TOOLCHAIN_VERSION "") diff --git a/Modules/Platform/Android/Determine-Compiler.cmake b/Modules/Platform/Android/Determine-Compiler.cmake index a03ebcc..5c6b97b 100644 --- a/Modules/Platform/Android/Determine-Compiler.cmake +++ b/Modules/Platform/Android/Determine-Compiler.cmake @@ -40,7 +40,6 @@ if(CMAKE_ANDROID_NDK) elseif(CMAKE_ANDROID_STANDALONE_TOOLCHAIN) include(Platform/Android/Determine-Compiler-Standalone) else() - set(_ANDROID_TOOL_NDK_TOOLCHAIN_HOST_TAG "") set(_ANDROID_TOOL_NDK_TOOLCHAIN_VERSION "") set(_ANDROID_TOOL_C_COMPILER "") set(_ANDROID_TOOL_C_TOOLCHAIN_MACHINE "") @@ -65,7 +64,6 @@ macro(__android_determine_compiler lang) # Save the Android-specific information in CMake${lang}Compiler.cmake. set(CMAKE_${lang}_COMPILER_CUSTOM_CODE " -set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG \"${_ANDROID_TOOL_NDK_TOOLCHAIN_HOST_TAG}\") set(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION \"${_ANDROID_TOOL_NDK_TOOLCHAIN_VERSION}\") set(CMAKE_${lang}_ANDROID_TOOLCHAIN_MACHINE \"${_ANDROID_TOOL_${lang}_TOOLCHAIN_MACHINE}\") set(CMAKE_${lang}_ANDROID_TOOLCHAIN_VERSION \"${_ANDROID_TOOL_${lang}_TOOLCHAIN_VERSION}\") diff --git a/Modules/Platform/Android/abi-common.cmake b/Modules/Platform/Android/abi-common.cmake index 6bce3c7..b01ef61 100644 --- a/Modules/Platform/Android/abi-common.cmake +++ b/Modules/Platform/Android/abi-common.cmake @@ -3,7 +3,7 @@ string(APPEND _ANDROID_ABI_INIT_CFLAGS " -no-canonical-prefixes" ) -if(CMAKE_ANDROID_NDK AND NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS) +if(CMAKE_ANDROID_NDK AND NOT CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED AND NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS) string(APPEND _ANDROID_ABI_INIT_CFLAGS " -D__ANDROID_API__=${CMAKE_SYSTEM_VERSION}") endif() diff --git a/Modules/Platform/Apple-XL-C.cmake b/Modules/Platform/Apple-XL-C.cmake index 2aeb132..e4fc3dd 100644 --- a/Modules/Platform/Apple-XL-C.cmake +++ b/Modules/Platform/Apple-XL-C.cmake @@ -1,4 +1,3 @@ -set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-qmkshrobj") set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle") # Enable shared library versioning. diff --git a/Modules/Platform/Apple-XL-CXX.cmake b/Modules/Platform/Apple-XL-CXX.cmake index f8e1906..ea330c8 100644 --- a/Modules/Platform/Apple-XL-CXX.cmake +++ b/Modules/Platform/Apple-XL-CXX.cmake @@ -1,4 +1,3 @@ -set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-qmkshrobj") set(CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS "-bundle") # Enable shared library versioning. diff --git a/Modules/Platform/Linux-XL-C.cmake b/Modules/Platform/Linux-XL-C.cmake index d595e44..ef0c52b 100644 --- a/Modules/Platform/Linux-XL-C.cmake +++ b/Modules/Platform/Linux-XL-C.cmake @@ -1,2 +1 @@ -set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-qmkshrobj") set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-Wl,-export-dynamic") diff --git a/Modules/Platform/Linux-XL-CXX.cmake b/Modules/Platform/Linux-XL-CXX.cmake index 5ceb255..aa57d6e 100644 --- a/Modules/Platform/Linux-XL-CXX.cmake +++ b/Modules/Platform/Linux-XL-CXX.cmake @@ -1,2 +1 @@ -set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-qmkshrobj") set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "-Wl,-export-dynamic") diff --git a/Modules/Platform/Linux-XL-Fortran.cmake b/Modules/Platform/Linux-XL-Fortran.cmake index a878991..d9b4c2d 100644 --- a/Modules/Platform/Linux-XL-Fortran.cmake +++ b/Modules/Platform/Linux-XL-Fortran.cmake @@ -1,2 +1 @@ -set(CMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS "-qmkshrobj") set(CMAKE_SHARED_LIBRARY_LINK_Fortran_FLAGS "-Wl,-export-dynamic") diff --git a/Modules/Platform/SunOS-Clang-C.cmake b/Modules/Platform/SunOS-Clang-C.cmake new file mode 100644 index 0000000..f06eb8f --- /dev/null +++ b/Modules/Platform/SunOS-Clang-C.cmake @@ -0,0 +1 @@ +include(Platform/SunOS-GNU-C) diff --git a/Modules/Platform/SunOS-Clang-CXX.cmake b/Modules/Platform/SunOS-Clang-CXX.cmake new file mode 100644 index 0000000..869182c --- /dev/null +++ b/Modules/Platform/SunOS-Clang-CXX.cmake @@ -0,0 +1 @@ +include(Platform/SunOS-GNU-CXX) diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake index b317da6..728e0b9 100644 --- a/Modules/Platform/Windows-Clang.cmake +++ b/Modules/Platform/Windows-Clang.cmake @@ -99,6 +99,21 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC" "or clang-cl as both C and C++ compilers.") endif() + if(NOT CMAKE_RC_COMPILER_INIT) + # Check if rc is already in the path + # This may happen in cases where the user is already in a visual studio environment when CMake is invoked + find_program(__RC_COMPILER_PATH NAMES rc) + + # Default to rc if it's available, otherwise fall back to llvm-rc + if(__RC_COMPILER_PATH) + set(CMAKE_RC_COMPILER_INIT rc) + else() + set(CMAKE_RC_COMPILER_INIT llvm-rc) + endif() + + unset(__RC_COMPILER_PATH CACHE) + endif() + if ( "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC" OR "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC" ) include(Platform/Windows-MSVC) diff --git a/Modules/Platform/Windows-Flang-Fortran.cmake b/Modules/Platform/Windows-Flang-Fortran.cmake index a4b1cf1..c4420f7 100644 --- a/Modules/Platform/Windows-Flang-Fortran.cmake +++ b/Modules/Platform/Windows-Flang-Fortran.cmake @@ -1,3 +1,8 @@ include(Platform/Windows-MSVC) __windows_compiler_msvc(Fortran) set(CMAKE_Fortran_COMPILE_OBJECT "<CMAKE_Fortran_COMPILER> ${_COMPILE_Fortran} <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>") + +set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded -Xclang --dependent-lib=libcmt) +set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -Xclang --dependent-lib=msvcrt) +set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug -Xclang --dependent-lib=libcmtd) +set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -Xclang --dependent-lib=msvcrtd) diff --git a/Modules/Platform/Windows-OpenWatcom.cmake b/Modules/Platform/Windows-OpenWatcom.cmake index d38d616..76cd28b 100644 --- a/Modules/Platform/Windows-OpenWatcom.cmake +++ b/Modules/Platform/Windows-OpenWatcom.cmake @@ -10,7 +10,7 @@ set(__WINDOWS_OPENWATCOM 1) set(CMAKE_LIBRARY_PATH_FLAG "libpath ") set(CMAKE_LINK_LIBRARY_FLAG "library ") -set(CMAKE_LINK_LIBRARY_FILE_FLAG "library") +set(CMAKE_LINK_LIBRARY_FILE_FLAG "library ") if(CMAKE_VERBOSE_MAKEFILE) set(CMAKE_WCL_QUIET) diff --git a/Modules/ProcessorCount.cmake b/Modules/ProcessorCount.cmake index 8c25256..43ec889 100644 --- a/Modules/ProcessorCount.cmake +++ b/Modules/ProcessorCount.cmake @@ -168,9 +168,13 @@ function(ProcessorCount var) ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE psrinfo_output) - string(REGEX MATCH "([0-9]+) virtual processor" procs "${psrinfo_output}") - set(count "${CMAKE_MATCH_1}") - #message("ProcessorCount: trying psrinfo -p -v '${ProcessorCount_cmd_prvinfo}'") + string(REGEX MATCHALL "has [0-9]+ virtual processor" procs "${psrinfo_output}") + set(count "") + foreach(proc ${procs}) + string(REGEX MATCH "has ([0-9]+) virtual" res ${proc}) + math(EXPR count "${count} + ${CMAKE_MATCH_1}") + endforeach() + #message("ProcessorCount: trying '${ProcessorCount_cmd_psrinfo}' -p -v") else() # Sun (systems where uname -X emits "NumCPU" in its output): find_program(ProcessorCount_cmd_uname uname) diff --git a/Source/.gitattributes b/Source/.gitattributes index 7c160cc..d0aedc2 100644 --- a/Source/.gitattributes +++ b/Source/.gitattributes @@ -1,2 +1,4 @@ +CMakeVersion.cmake export-subst + # Do not format third-party sources. /kwsys/** -format.clang-format-6.0 diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 695e075..7cd07a8 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -95,9 +95,6 @@ include_directories( ${CMake_HAIKU_INCLUDE_DIRS} ) -# let cmake know it is supposed to use it -add_definitions(-DCMAKE_BUILD_WITH_CMAKE) - # Check if we can build the ELF parser. if(CMAKE_USE_ELF_PARSER) set(ELF_SRCS cmELF.h cmELF.cxx) @@ -142,10 +139,33 @@ set(SRCS cmAffinity.cxx cmAffinity.h + cmAlgorithms.h cmArchiveWrite.cxx cmArgumentParser.cxx cmArgumentParser.h cmBase32.cxx + cmBinUtilsLinker.cxx + cmBinUtilsLinker.h + cmBinUtilsLinuxELFGetRuntimeDependenciesTool.cxx + cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h + cmBinUtilsLinuxELFLinker.cxx + cmBinUtilsLinuxELFLinker.h + cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx + cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h + cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.cxx + cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h + cmBinUtilsMacOSMachOLinker.cxx + cmBinUtilsMacOSMachOLinker.h + cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx + cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h + cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx + cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h + cmBinUtilsWindowsPEGetRuntimeDependenciesTool.cxx + cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h + cmBinUtilsWindowsPELinker.cxx + cmBinUtilsWindowsPELinker.h + cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx + cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h cmCacheManager.cxx cmCacheManager.h cmCLocaleEnvironmentScope.h @@ -295,6 +315,10 @@ set(SRCS cmInstallTargetGenerator.cxx cmInstallDirectoryGenerator.h cmInstallDirectoryGenerator.cxx + cmLDConfigLDConfigTool.cxx + cmLDConfigLDConfigTool.h + cmLDConfigTool.cxx + cmLDConfigTool.h cmLinkedTree.h cmLinkItem.cxx cmLinkItem.h @@ -338,7 +362,6 @@ set(SRCS cmProcessOutput.h cmProcessTools.cxx cmProcessTools.h - cmProperty.cxx cmProperty.h cmPropertyDefinition.cxx cmPropertyDefinition.h @@ -360,6 +383,8 @@ set(SRCS cmQtAutoRcc.h cmRST.cxx cmRST.h + cmRuntimeDependencyArchive.cxx + cmRuntimeDependencyArchive.h cmScriptGenerator.h cmScriptGenerator.cxx cmSourceFile.cxx @@ -376,6 +401,8 @@ set(SRCS cmStateSnapshot.cxx cmStateSnapshot.h cmStateTypes.h + cmStringAlgorithms.cxx + cmStringAlgorithms.h cmSystemTools.cxx cmSystemTools.h cmTarget.cxx @@ -502,6 +529,8 @@ set(SRCS cmFindProgramCommand.h cmForEachCommand.cxx cmForEachCommand.h + cmFunctionBlocker.cxx + cmFunctionBlocker.h cmFunctionCommand.cxx cmFunctionCommand.h cmGetCMakePropertyCommand.cxx @@ -607,6 +636,8 @@ set(SRCS cmStringReplaceHelper.cxx cmStringCommand.cxx cmStringCommand.h + cmSubcommandTable.cxx + cmSubcommandTable.h cmSubdirCommand.cxx cmSubdirCommand.h cmSubdirDependsCommand.cxx @@ -635,8 +666,6 @@ set(SRCS cmTryCompileCommand.h cmTryRunCommand.cxx cmTryRunCommand.h - cmUnexpectedCommand.cxx - cmUnexpectedCommand.h cmUnsetCommand.cxx cmUnsetCommand.h cmUseMangledMesaCommand.cxx @@ -1134,6 +1163,21 @@ include (${CMake_BINARY_DIR}/Source/LocalUserOptions.cmake OPTIONAL) include (${CMake_SOURCE_DIR}/Source/LocalUserOptions.cmake OPTIONAL) if(WIN32) + # Compute the binary version that appears in the RC file. Version + # components in the RC file are 16-bit integers so we may have to + # split the patch component. + if(CMake_VERSION_PATCH MATCHES "^([0-9]+)([0-9][0-9][0-9][0-9])$") + set(CMake_RCVERSION_YEAR "${CMAKE_MATCH_1}") + set(CMake_RCVERSION_MONTH_DAY "${CMAKE_MATCH_2}") + string(REGEX REPLACE "^0+" "" CMake_RCVERSION_MONTH_DAY "${CMake_RCVERSION_MONTH_DAY}") + set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_RCVERSION_YEAR},${CMake_RCVERSION_MONTH_DAY}) + unset(CMake_RCVERSION_MONTH_DAY) + unset(CMake_RCVERSION_YEAR) + else() + set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_VERSION_PATCH}) + endif() + set(CMake_RCVERSION_STR ${CMake_VERSION}) + # Add Windows executable version information. configure_file("CMakeVersion.rc.in" "CMakeVersion.rc" @ONLY) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index efbbeb4..f72c20b 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,82 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 15) -set(CMake_VERSION_PATCH 2) +set(CMake_VERSION_PATCH 20190827) #set(CMake_VERSION_RC 0) +set(CMake_VERSION_IS_DIRTY 0) + +# Start with the full version number used in tags. It has no dev info. +set(CMake_VERSION + "${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}") +if(DEFINED CMake_VERSION_RC) + set(CMake_VERSION "${CMake_VERSION}-rc${CMake_VERSION_RC}") +endif() + +# Releases define a small patch level. +if("${CMake_VERSION_PATCH}" VERSION_LESS 20000000) + set(CMake_VERSION_IS_RELEASE 1) +else() + set(CMake_VERSION_IS_RELEASE 0) +endif() + +if(EXISTS ${CMake_SOURCE_DIR}/.git) + find_package(Git QUIET) + if(GIT_FOUND) + macro(_git) + execute_process( + COMMAND ${GIT_EXECUTABLE} ${ARGN} + WORKING_DIRECTORY ${CMake_SOURCE_DIR} + RESULT_VARIABLE _git_res + OUTPUT_VARIABLE _git_out OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE _git_err ERROR_STRIP_TRAILING_WHITESPACE + ) + endmacro() + endif() +endif() + +# Try to identify the current development source version. +if(COMMAND _git) + # Get the commit checked out in this work tree. + _git(log -n 1 HEAD "--pretty=format:%h %s" --) + set(git_info "${_git_out}") +else() + # Get the commit exported by 'git archive'. + set(git_info [==[$Format:%h %s$]==]) +endif() + +# Extract commit information if available. +if(git_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]?[0-9a-f]?)[0-9a-f]* (.*)$") + # Have commit information. + set(git_hash "${CMAKE_MATCH_1}") + set(git_subject "${CMAKE_MATCH_2}") + + # If this is not the exact commit of a release, add dev info. + if(NOT "${git_subject}" MATCHES "^[Cc][Mm]ake ${CMake_VERSION}$") + set(CMake_VERSION "${CMake_VERSION}-g${git_hash}") + endif() + + # If this is a work tree, check whether it is dirty. + if(COMMAND _git) + _git(update-index -q --refresh) + _git(diff-index --name-only HEAD --) + if(_git_out) + set(CMake_VERSION_IS_DIRTY 1) + endif() + endif() +else() + # No commit information. + if(NOT CMake_VERSION_IS_RELEASE) + # Generic development version. + set(CMake_VERSION "${CMake_VERSION}-git") + endif() +endif() + +# Extract the version suffix component. +if(CMake_VERSION MATCHES "-(.*)$") + set(CMake_VERSION_SUFFIX "${CMAKE_MATCH_1}") +else() + set(CMake_VERSION_SUFFIX "") +endif() +if(CMake_VERSION_IS_DIRTY) + set(CMake_VERSION ${CMake_VERSION}-dirty) +endif() diff --git a/Source/CMakeVersionCompute.cmake b/Source/CMakeVersionCompute.cmake deleted file mode 100644 index 72a5800..0000000 --- a/Source/CMakeVersionCompute.cmake +++ /dev/null @@ -1,44 +0,0 @@ -# Load version number components. -include(${CMake_SOURCE_DIR}/Source/CMakeVersion.cmake) - -# Releases define a small patch level. -if("${CMake_VERSION_PATCH}" VERSION_LESS 20000000) - set(CMake_VERSION_IS_DIRTY 0) - set(CMake_VERSION_IS_RELEASE 1) - set(CMake_VERSION_SOURCE "") -else() - set(CMake_VERSION_IS_DIRTY 0) # may be set to 1 by CMakeVersionSource - set(CMake_VERSION_IS_RELEASE 0) - include(${CMake_SOURCE_DIR}/Source/CMakeVersionSource.cmake) -endif() - -# Compute the full version string. -set(CMake_VERSION ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}) -if(CMake_VERSION_SOURCE) - set(CMake_VERSION_SUFFIX "${CMake_VERSION_SOURCE}") -elseif(CMake_VERSION_RC) - set(CMake_VERSION_SUFFIX "rc${CMake_VERSION_RC}") -else() - set(CMake_VERSION_SUFFIX "") -endif() -if(CMake_VERSION_SUFFIX) - set(CMake_VERSION ${CMake_VERSION}-${CMake_VERSION_SUFFIX}) -endif() -if(CMake_VERSION_IS_DIRTY) - set(CMake_VERSION ${CMake_VERSION}-dirty) -endif() - -# Compute the binary version that appears in the RC file. Version -# components in the RC file are 16-bit integers so we may have to -# split the patch component. -if(CMake_VERSION_PATCH MATCHES "^([0-9]+)([0-9][0-9][0-9][0-9])$") - set(CMake_RCVERSION_YEAR "${CMAKE_MATCH_1}") - set(CMake_RCVERSION_MONTH_DAY "${CMAKE_MATCH_2}") - string(REGEX REPLACE "^0+" "" CMake_RCVERSION_MONTH_DAY "${CMake_RCVERSION_MONTH_DAY}") - set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_RCVERSION_YEAR},${CMake_RCVERSION_MONTH_DAY}) - unset(CMake_RCVERSION_MONTH_DAY) - unset(CMake_RCVERSION_YEAR) -else() - set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_VERSION_PATCH}) -endif() -set(CMake_RCVERSION_STR ${CMake_VERSION}) diff --git a/Source/CMakeVersionSource.cmake b/Source/CMakeVersionSource.cmake deleted file mode 100644 index 5ea1de3..0000000 --- a/Source/CMakeVersionSource.cmake +++ /dev/null @@ -1,30 +0,0 @@ -# Try to identify the current development source version. -set(CMake_VERSION_SOURCE "") -if(EXISTS ${CMake_SOURCE_DIR}/.git/HEAD) - find_program(GIT_EXECUTABLE NAMES git git.cmd) - mark_as_advanced(GIT_EXECUTABLE) - if(GIT_EXECUTABLE) - execute_process( - COMMAND ${GIT_EXECUTABLE} rev-parse --verify -q --short=4 HEAD - OUTPUT_VARIABLE head - OUTPUT_STRIP_TRAILING_WHITESPACE - WORKING_DIRECTORY ${CMake_SOURCE_DIR} - ) - if(head) - set(CMake_VERSION_SOURCE "g${head}") - execute_process( - COMMAND ${GIT_EXECUTABLE} update-index -q --refresh - WORKING_DIRECTORY ${CMake_SOURCE_DIR} - ) - execute_process( - COMMAND ${GIT_EXECUTABLE} diff-index --name-only HEAD -- - OUTPUT_VARIABLE dirty - OUTPUT_STRIP_TRAILING_WHITESPACE - WORKING_DIRECTORY ${CMake_SOURCE_DIR} - ) - if(dirty) - set(CMake_VERSION_IS_DIRTY 1) - endif() - endif() - endif() -endif() diff --git a/Source/CPack/IFW/cmCPackIFWCommon.cxx b/Source/CPack/IFW/cmCPackIFWCommon.cxx index 1e72641..f9ce822 100644 --- a/Source/CPack/IFW/cmCPackIFWCommon.cxx +++ b/Source/CPack/IFW/cmCPackIFWCommon.cxx @@ -5,6 +5,7 @@ #include "cmCPackGenerator.h" #include "cmCPackIFWGenerator.h" #include "cmCPackLog.h" // IWYU pragma: keep +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTimestamp.h" #include "cmVersionConfig.h" @@ -77,8 +78,7 @@ bool cmCPackIFWCommon::IsVersionEqual(const char* version) void cmCPackIFWCommon::ExpandListArgument( const std::string& arg, std::map<std::string, std::string>& argsOut) { - std::vector<std::string> args; - cmSystemTools::ExpandListArgument(arg, args, false); + std::vector<std::string> args = cmExpandedList(arg, false); if (args.empty()) { return; } @@ -99,8 +99,7 @@ void cmCPackIFWCommon::ExpandListArgument( void cmCPackIFWCommon::ExpandListArgument( const std::string& arg, std::multimap<std::string, std::string>& argsOut) { - std::vector<std::string> args; - cmSystemTools::ExpandListArgument(arg, args, false); + std::vector<std::string> args = cmExpandedList(arg, false); if (args.empty()) { return; } diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx index c1b6eea..8f13d0e 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -11,6 +11,7 @@ #include "cmCPackLog.h" // IWYU pragma: keep #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include <sstream> @@ -34,8 +35,7 @@ int cmCPackIFWGenerator::PackageFiles() this->Installer.GeneratePackageFiles(); std::string ifwTLD = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - std::string ifwTmpFile = ifwTLD; - ifwTmpFile += "/IFWOutput.log"; + std::string ifwTmpFile = cmStrCat(ifwTLD, "/IFWOutput.log"); // Run repogen if (!this->Installer.RemoteRepositories.empty()) { @@ -116,8 +116,8 @@ int cmCPackIFWGenerator::PackageFiles() // Run binary creator { - std::string ifwCmd = this->BinCreator; - ifwCmd += " -c " + this->toplevel + "/config/config.xml"; + std::string ifwCmd = + cmStrCat(this->BinCreator, " -c ", this->toplevel, "/config/config.xml"); if (!this->Installer.Resources.empty()) { ifwCmd += " -r "; @@ -253,7 +253,7 @@ int cmCPackIFWGenerator::InitializeInternal() // Look 'binarycreator' executable (needs) const char* BinCreatorStr = this->GetOption(BinCreatorOpt); - if (!BinCreatorStr || cmSystemTools::IsNOTFOUND(BinCreatorStr)) { + if (!BinCreatorStr || cmIsNOTFOUND(BinCreatorStr)) { this->BinCreator.clear(); } else { this->BinCreator = BinCreatorStr; @@ -270,7 +270,7 @@ int cmCPackIFWGenerator::InitializeInternal() // Look 'repogen' executable (optional) const char* RepoGenStr = this->GetOption(RepoGenOpt); - if (!RepoGenStr || cmSystemTools::IsNOTFOUND(RepoGenStr)) { + if (!RepoGenStr || cmIsNOTFOUND(RepoGenStr)) { this->RepoGen.clear(); } else { this->RepoGen = RepoGenStr; @@ -292,14 +292,14 @@ int cmCPackIFWGenerator::InitializeInternal() // Additional packages dirs this->PkgsDirsVector.clear(); if (const char* dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) { - cmSystemTools::ExpandListArgument(dirs, this->PkgsDirsVector); + cmExpandList(dirs, this->PkgsDirsVector); } // Additional repositories dirs this->RepoDirsVector.clear(); if (const char* dirs = this->GetOption("CPACK_IFW_REPOSITORIES_DIRECTORIES")) { - cmSystemTools::ExpandListArgument(dirs, this->RepoDirsVector); + cmExpandList(dirs, this->RepoDirsVector); } // Installer @@ -316,18 +316,17 @@ int cmCPackIFWGenerator::InitializeInternal() // Repositories if (const char* RepoAllStr = this->GetOption("CPACK_IFW_REPOSITORIES_ALL")) { - std::vector<std::string> RepoAllVector; - cmSystemTools::ExpandListArgument(RepoAllStr, RepoAllVector); + std::vector<std::string> RepoAllVector = cmExpandedList(RepoAllStr); for (std::string const& r : RepoAllVector) { this->GetRepository(r); } } if (const char* ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) { - this->OnlineOnly = cmSystemTools::IsOn(ifwDownloadAll); + this->OnlineOnly = cmIsOn(ifwDownloadAll); } else if (const char* cpackDownloadAll = this->GetOption("CPACK_DOWNLOAD_ALL")) { - this->OnlineOnly = cmSystemTools::IsOn(cpackDownloadAll); + this->OnlineOnly = cmIsOn(cpackDownloadAll); } else { this->OnlineOnly = false; } diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx index a075a17..b4bfea7 100644 --- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx +++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx @@ -8,6 +8,7 @@ #include "cmCPackIFWRepository.h" #include "cmCPackLog.h" // IWYU pragma: keep #include "cmGeneratedFileStream.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLParser.h" #include "cmXMLWriter.h" @@ -192,8 +193,8 @@ void cmCPackIFWInstaller::ConfigureFromOptions() this->TargetDir = optIFW_TARGET_DIRECTORY; } else if (const char* optPACKAGE_INSTALL_DIRECTORY = this->GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) { - this->TargetDir = "@ApplicationsDir@/"; - this->TargetDir += optPACKAGE_INSTALL_DIRECTORY; + this->TargetDir = + cmStrCat("@ApplicationsDir@/", optPACKAGE_INSTALL_DIRECTORY); } else { this->TargetDir = "@RootDir@/usr/local"; } @@ -244,8 +245,7 @@ void cmCPackIFWInstaller::ConfigureFromOptions() if (const char* optIFW_PACKAGE_RESOURCES = this->GetOption("CPACK_IFW_PACKAGE_RESOURCES")) { this->Resources.clear(); - cmSystemTools::ExpandListArgument(optIFW_PACKAGE_RESOURCES, - this->Resources); + cmExpandList(optIFW_PACKAGE_RESOURCES, this->Resources); } } @@ -292,7 +292,7 @@ protected: { if (this->file) { std::string content(data, data + length); - content = cmSystemTools::TrimWhitespace(content); + content = cmTrimWhitespace(content); std::string source = this->basePath + "/" + content; std::string destination = this->path + "/" + content; if (!cmSystemTools::CopyFileIfDifferent(source, destination)) { diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx index a1a52b1..fb75145 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.cxx +++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx @@ -8,6 +8,7 @@ #include "cmCPackIFWInstaller.h" #include "cmCPackLog.h" // IWYU pragma: keep #include "cmGeneratedFileStream.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTimestamp.h" #include "cmXMLWriter.h" @@ -196,7 +197,7 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component) // User interfaces if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) { this->UserInterfaces.clear(); - cmSystemTools::ExpandListArgument(option, this->UserInterfaces); + cmExpandList(option, this->UserInterfaces); } // CMake dependencies @@ -209,7 +210,7 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component) // Licenses if (const char* option = this->GetOption(prefix + "LICENSES")) { this->Licenses.clear(); - cmSystemTools::ExpandListArgument(option, this->Licenses); + cmExpandList(option, this->Licenses); if (this->Licenses.size() % 2 != 0) { cmCPackIFWLogger( WARNING, @@ -281,13 +282,13 @@ int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group) // User interfaces if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) { this->UserInterfaces.clear(); - cmSystemTools::ExpandListArgument(option, this->UserInterfaces); + cmExpandList(option, this->UserInterfaces); } // Licenses if (const char* option = this->GetOption(prefix + "LICENSES")) { this->Licenses.clear(); - cmSystemTools::ExpandListArgument(option, this->Licenses); + cmExpandList(option, this->Licenses); if (this->Licenses.size() % 2 != 0) { cmCPackIFWLogger( WARNING, @@ -398,18 +399,18 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) this->Translations.clear(); } else if (const char* value = this->GetOption(option)) { this->Translations.clear(); - cmSystemTools::ExpandListArgument(value, this->Translations); + cmExpandList(value, this->Translations); } // QtIFW dependencies std::vector<std::string> deps; option = prefix + "DEPENDS"; if (const char* value = this->GetOption(option)) { - cmSystemTools::ExpandListArgument(value, deps); + cmExpandList(value, deps); } option = prefix + "DEPENDENCIES"; if (const char* value = this->GetOption(option)) { - cmSystemTools::ExpandListArgument(value, deps); + cmExpandList(value, deps); } for (std::string const& d : deps) { DependenceStruct dep(d); @@ -430,8 +431,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) if (this->IsSetToEmpty(option)) { this->AlienAutoDependOn.clear(); } else if (const char* value = this->GetOption(option)) { - std::vector<std::string> depsOn; - cmSystemTools::ExpandListArgument(value, depsOn); + std::vector<std::string> depsOn = cmExpandedList(value); for (std::string const& d : depsOn) { DependenceStruct dep(d); if (this->Generator->Packages.count(dep.Name)) { @@ -488,7 +488,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) this->Replaces.clear(); } else if (const char* value = this->GetOption(option)) { this->Replaces.clear(); - cmSystemTools::ExpandListArgument(value, this->Replaces); + cmExpandList(value, this->Replaces); } // Requires admin rights diff --git a/Source/CPack/WiX/cmCMakeToWixPath.cxx b/Source/CPack/WiX/cmCMakeToWixPath.cxx index b3889cf..630a8f8 100644 --- a/Source/CPack/WiX/cmCMakeToWixPath.cxx +++ b/Source/CPack/WiX/cmCMakeToWixPath.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCMakeToWixPath.h" -#include "cmSystemTools.h" +#include "cmStringAlgorithms.h" #include <string> #include <vector> @@ -29,7 +29,7 @@ std::string CMakeToWixPath(const std::string& cygpath) return cygpath; } - return cmSystemTools::TrimWhitespace(winpath_chars.data()); + return cmTrimWhitespace(winpath_chars.data()); } #else std::string CMakeToWixPath(const std::string& path) diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index 045d93d..b0b2df2 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -2,13 +2,16 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackWIXGenerator.h" +#include "cmAlgorithms.h" #include "cmCPackComponentGroup.h" #include "cmCPackLog.h" #include "cmCryptoHash.h" #include "cmGeneratedFileStream.h" #include "cmInstalledFile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmUuid.h" +#include "cm_string_view.hxx" #include <algorithm> #include "cmWIXDirectoriesSourceWriter.h" @@ -225,8 +228,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() const char* patchFilePath = GetOption("CPACK_WIX_PATCH_FILE"); if (patchFilePath) { - std::vector<std::string> patchFilePaths; - cmSystemTools::ExpandListArgument(patchFilePath, patchFilePaths); + std::vector<std::string> patchFilePaths = cmExpandedList(patchFilePath); for (std::string const& p : patchFilePaths) { if (!this->Patch->LoadFragments(p)) { @@ -237,7 +239,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() // if install folder is supposed to be set absolutely, the default // component guid "*" cannot be used - if (cmSystemTools::IsOn(GetOption("CPACK_WIX_SKIP_PROGRAM_FOLDER"))) { + if (cmIsOn(GetOption("CPACK_WIX_SKIP_PROGRAM_FOLDER"))) { this->ComponentGuidType = cmWIXSourceWriter::CMAKE_GENERATED_GUID; } @@ -300,7 +302,7 @@ void cmCPackWIXGenerator::AppendUserSuppliedExtraSources() if (!cpackWixExtraSources) return; - cmSystemTools::ExpandListArgument(cpackWixExtraSources, this->WixSources); + cmExpandList(cpackWixExtraSources, this->WixSources); } void cmCPackWIXGenerator::AppendUserSuppliedExtraObjects(std::ostream& stream) @@ -309,10 +311,8 @@ void cmCPackWIXGenerator::AppendUserSuppliedExtraObjects(std::ostream& stream) if (!cpackWixExtraObjects) return; - std::vector<std::string> expandedExtraObjects; - - cmSystemTools::ExpandListArgument(cpackWixExtraObjects, - expandedExtraObjects); + std::vector<std::string> expandedExtraObjects = + cmExpandedList(cpackWixExtraObjects); for (std::string const& obj : expandedExtraObjects) { stream << " " << QuotePath(obj); @@ -518,9 +518,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() for (auto const& i : this->Components) { cmCPackComponent const& component = i.second; - std::string componentPath = toplevel; - componentPath += "/"; - componentPath += component.Name; + std::string componentPath = cmStrCat(toplevel, '/', component.Name); std::string const componentFeatureId = "CM_C_" + component.Name; @@ -582,7 +580,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() std::string cmCPackWIXGenerator::GetRootFolderId() const { - if (cmSystemTools::IsOn(GetOption("CPACK_WIX_SKIP_PROGRAM_FOLDER"))) { + if (cmIsOn(GetOption("CPACK_WIX_SKIP_PROGRAM_FOLDER"))) { return ""; } @@ -604,7 +602,7 @@ std::string cmCPackWIXGenerator::GetRootFolderId() const bool cmCPackWIXGenerator::GenerateMainSourceFileFromTemplate() { - std::string wixTemplate = FindTemplate("WIX.template.in"); + std::string wixTemplate = FindTemplate("Internal/CPack/WIX.template.in"); if (GetOption("CPACK_WIX_TEMPLATE") != 0) { wixTemplate = GetOption("CPACK_WIX_TEMPLATE"); } @@ -664,8 +662,7 @@ bool cmCPackWIXGenerator::AddComponentsToFeature( std::vector<std::string> cpackPackageExecutablesList; const char* cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES"); if (cpackPackageExecutables) { - cmSystemTools::ExpandListArgument(cpackPackageExecutables, - cpackPackageExecutablesList); + cmExpandList(cpackPackageExecutables, cpackPackageExecutablesList); if (cpackPackageExecutablesList.size() % 2 != 0) { cmCPackLogger( cmCPackLog::LOG_ERROR, @@ -680,8 +677,7 @@ bool cmCPackWIXGenerator::AddComponentsToFeature( const char* cpackPackageDesktopLinks = GetOption("CPACK_CREATE_DESKTOP_LINKS"); if (cpackPackageDesktopLinks) { - cmSystemTools::ExpandListArgument(cpackPackageDesktopLinks, - cpackPackageDesktopLinksList); + cmExpandList(cpackPackageDesktopLinks, cpackPackageDesktopLinksList); } AddDirectoryAndFileDefinitions( @@ -944,9 +940,7 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitions( shortcut.workingDirectoryId = directoryId; shortcuts.insert(cmWIXShortcuts::START_MENU, id, shortcut); - if (!desktopExecutables.empty() && - std::find(desktopExecutables.begin(), desktopExecutables.end(), - executableName) != desktopExecutables.end()) { + if (cmContains(desktopExecutables, executableName)) { shortcuts.insert(cmWIXShortcuts::DESKTOP, id, shortcut); } } @@ -1090,8 +1084,7 @@ std::string cmCPackWIXGenerator::CreateHashedId( cmCryptoHash sha1(cmCryptoHash::AlgoSHA1); std::string const hash = sha1.HashString(path); - std::string identifier; - identifier += hash.substr(0, 7) + "_"; + std::string identifier = cmStrCat(cm::string_view(hash).substr(0, 7), '_'); const size_t maxFileNameLength = 52; if (normalizedFilename.length() > maxFileNameLength) { @@ -1136,8 +1129,7 @@ void cmCPackWIXGenerator::CollectExtensions(std::string const& variableName, if (!variableContent) return; - std::vector<std::string> list; - cmSystemTools::ExpandListArgument(variableContent, list); + std::vector<std::string> list = cmExpandedList(variableContent); extensions.insert(list.begin(), list.end()); } @@ -1148,8 +1140,7 @@ void cmCPackWIXGenerator::AddCustomFlags(std::string const& variableName, if (!variableContent) return; - std::vector<std::string> list; - cmSystemTools::ExpandListArgument(variableContent, list); + std::vector<std::string> list = cmExpandedList(variableContent); for (std::string const& i : list) { stream << " " << QuotePath(i); diff --git a/Source/CPack/WiX/cmWIXAccessControlList.cxx b/Source/CPack/WiX/cmWIXAccessControlList.cxx index 563de02..b5e287d 100644 --- a/Source/CPack/WiX/cmWIXAccessControlList.cxx +++ b/Source/CPack/WiX/cmWIXAccessControlList.cxx @@ -4,6 +4,7 @@ #include "cmCPackGenerator.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmWIXAccessControlList::cmWIXAccessControlList( @@ -48,8 +49,7 @@ void cmWIXAccessControlList::CreatePermissionElement(std::string const& entry) user = user_and_domain; } - std::vector<std::string> permissions = - cmSystemTools::tokenize(permission_string, ","); + std::vector<std::string> permissions = cmTokenize(permission_string, ","); this->SourceWriter.BeginElement("Permission"); this->SourceWriter.AddAttribute("User", user); @@ -57,8 +57,7 @@ void cmWIXAccessControlList::CreatePermissionElement(std::string const& entry) this->SourceWriter.AddAttribute("Domain", domain); } for (std::string const& permission : permissions) { - this->EmitBooleanAttribute(entry, - cmSystemTools::TrimWhitespace(permission)); + this->EmitBooleanAttribute(entry, cmTrimWhitespace(permission)); } this->SourceWriter.EndElement("Permission"); } diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx index 98fb29d..6c9c6b9 100644 --- a/Source/CPack/cmCPackArchiveGenerator.cxx +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -6,6 +6,7 @@ #include "cmCPackGenerator.h" #include "cmCPackLog.h" #include "cmGeneratedFileStream.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" @@ -71,8 +72,7 @@ int cmCPackArchiveGenerator::addOneComponentToArchive( } std::string filePrefix; if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) { - filePrefix = this->GetOption("CPACK_PACKAGE_FILE_NAME"); - filePrefix += "/"; + filePrefix = cmStrCat(this->GetOption("CPACK_PACKAGE_FILE_NAME"), '/'); } const char* installPrefix = this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"); diff --git a/Source/CPack/cmCPackBundleGenerator.cxx b/Source/CPack/cmCPackBundleGenerator.cxx index 3a476f4..4d5f43f 100644 --- a/Source/CPack/cmCPackBundleGenerator.cxx +++ b/Source/CPack/cmCPackBundleGenerator.cxx @@ -6,6 +6,7 @@ #include <vector> #include "cmCPackLog.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmCPackBundleGenerator::cmCPackBundleGenerator() = default; @@ -40,9 +41,8 @@ int cmCPackBundleGenerator::InitializeInternal() const char* cmCPackBundleGenerator::GetPackagingInstallPrefix() { - this->InstallPrefix = "/"; - this->InstallPrefix += this->GetOption("CPACK_BUNDLE_NAME"); - this->InstallPrefix += ".app/Contents/Resources"; + this->InstallPrefix = cmStrCat('/', this->GetOption("CPACK_BUNDLE_NAME"), + ".app/Contents/Resources"); return this->InstallPrefix.c_str(); } @@ -89,11 +89,10 @@ int cmCPackBundleGenerator::ConstructBundle() // The staging directory contains everything that will end-up inside the // final disk image ... - std::ostringstream staging; - staging << toplevel; + std::string const staging = toplevel; std::ostringstream contents; - contents << staging.str() << "/" << cpack_bundle_name << ".app/" + contents << staging << "/" << cpack_bundle_name << ".app/" << "Contents"; std::ostringstream application; @@ -190,9 +189,8 @@ int cmCPackBundleGenerator::SignBundle(const std::string& src_dir) if (!cpack_apple_cert_app.empty()) { std::string output; std::string bundle_path; - bundle_path = src_dir + "/"; - bundle_path += this->GetOption("CPACK_BUNDLE_NAME"); - bundle_path += ".app"; + bundle_path = + cmStrCat(src_dir, '/', this->GetOption("CPACK_BUNDLE_NAME"), ".app"); // A list of additional files to sign, ie. frameworks and plugins. const std::string sign_parameter = @@ -205,8 +203,7 @@ int cmCPackBundleGenerator::SignBundle(const std::string& src_dir) ? this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES") : ""; - std::vector<std::string> relFiles; - cmSystemTools::ExpandListArgument(sign_files, relFiles); + std::vector<std::string> relFiles = cmExpandedList(sign_files); // sign the files supplied by the user, ie. frameworks. for (auto const& file : relFiles) { diff --git a/Source/CPack/cmCPackComponentGroup.cxx b/Source/CPack/cmCPackComponentGroup.cxx index f888a5f..9e05d86 100644 --- a/Source/CPack/cmCPackComponentGroup.cxx +++ b/Source/CPack/cmCPackComponentGroup.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackComponentGroup.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include <string> @@ -14,9 +15,7 @@ unsigned long cmCPackComponent::GetInstalledSize( } for (std::string const& file : this->Files) { - std::string path = installDir; - path += '/'; - path += file; + std::string path = cmStrCat(installDir, '/', file); this->TotalSize += cmSystemTools::FileLength(path); } diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx index 49a9f15..553a677 100644 --- a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx +++ b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx @@ -28,13 +28,11 @@ int cmCPackCygwinBinaryGenerator::InitializeInternal() int cmCPackCygwinBinaryGenerator::PackageFiles() { - std::string packageName = this->GetOption("CPACK_PACKAGE_NAME"); - packageName += "-"; - packageName += this->GetOption("CPACK_PACKAGE_VERSION"); + std::string packageName = + cmStrCat(this->GetOption("CPACK_PACKAGE_NAME"), '-', + this->GetOption("CPACK_PACKAGE_VERSION")); packageName = cmsys::SystemTools::LowerCase(packageName); - std::string manifest = "/usr/share/doc/"; - manifest += packageName; - manifest += "/MANIFEST"; + std::string manifest = cmStrCat("/usr/share/doc/", packageName, "/MANIFEST"); std::string manifestFile = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); // Create a MANIFEST file that contains all of the files in // the tar file diff --git a/Source/CPack/cmCPackCygwinSourceGenerator.cxx b/Source/CPack/cmCPackCygwinSourceGenerator.cxx index 889f29a..8cae9b4 100644 --- a/Source/CPack/cmCPackCygwinSourceGenerator.cxx +++ b/Source/CPack/cmCPackCygwinSourceGenerator.cxx @@ -37,8 +37,7 @@ int cmCPackCygwinSourceGenerator::PackageFiles() { // Create a tar file of the sources std::string packageDirFileName = - this->GetOption("CPACK_TEMPORARY_DIRECTORY"); - packageDirFileName += ".tar.bz2"; + cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), ".tar.bz2"); packageFileNames[0] = packageDirFileName; std::string output; // skip one parent up to the cmCPackTarBZip2Generator @@ -94,8 +93,8 @@ int cmCPackCygwinSourceGenerator::PackageFiles() << this->GetOption("CPACK_TOPLEVEL_DIRECTORY") << "]\n"); return 0; } - std::string outerTarFile = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); - outerTarFile += "-"; + std::string outerTarFile = + cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), '-'); const char* patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); if (!patch) { cmCPackLogger(cmCPackLog::LOG_WARNING, @@ -106,19 +105,18 @@ int cmCPackCygwinSourceGenerator::PackageFiles() outerTarFile += patch; outerTarFile += "-src.tar.bz2"; std::string tmpDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - std::string buildScript = tmpDir; - buildScript += "/"; - buildScript += cmSystemTools::GetFilenameName( - this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT")); - std::string patchFile = tmpDir; - patchFile += "/"; - patchFile += - cmSystemTools::GetFilenameName(this->GetOption("CPACK_CYGWIN_PATCH_FILE")); + std::string buildScript = + cmStrCat(tmpDir, '/', + cmSystemTools::GetFilenameName( + this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT"))); + std::string patchFile = + cmStrCat(tmpDir, '/', + cmSystemTools::GetFilenameName( + this->GetOption("CPACK_CYGWIN_PATCH_FILE"))); std::string file = cmSystemTools::GetFilenameName(compressOutFile); - std::string sourceTar = cmSystemTools::GetFilenamePath(compressOutFile); - sourceTar += "/"; - sourceTar += file; + std::string sourceTar = + cmStrCat(cmSystemTools::GetFilenamePath(compressOutFile), '/', file); /* reset list of file to be packaged */ files.clear(); // a source release in cygwin should have the build script used @@ -140,8 +138,8 @@ int cmCPackCygwinSourceGenerator::PackageFiles() const char* cmCPackCygwinSourceGenerator::GetPackagingInstallPrefix() { - this->InstallPrefix = "/"; - this->InstallPrefix += this->GetOption("CPACK_PACKAGE_FILE_NAME"); + this->InstallPrefix = + cmStrCat('/', this->GetOption("CPACK_PACKAGE_FILE_NAME")); return this->InstallPrefix.c_str(); } diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index cfb5efd..cefbc90 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -8,6 +8,7 @@ #include "cmCPackLog.h" #include "cmCryptoHash.h" #include "cmGeneratedFileStream.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cm_sys_stat.h" @@ -148,8 +149,7 @@ void DebGenerator::generateControlFile() const unsigned long totalSize = 0; { - std::string dirName = TemporaryDir; - dirName += '/'; + std::string dirName = cmStrCat(TemporaryDir, '/'); for (std::string const& file : PackageFiles) { totalSize += cmSystemTools::FileLength(file); } @@ -247,8 +247,7 @@ std::string DebGenerator::generateMD5File() const cmGeneratedFileStream out(md5filename); - std::string topLevelWithTrailingSlash = TemporaryDir; - topLevelWithTrailingSlash += '/'; + std::string topLevelWithTrailingSlash = cmStrCat(TemporaryDir, '/'); for (std::string const& file : PackageFiles) { // hash only regular files if (cmSystemTools::FileIsDirectory(file) || @@ -377,8 +376,7 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const // default control_tar.ClearPermissions(); - std::vector<std::string> controlExtraList; - cmSystemTools::ExpandListArgument(ControlExtra, controlExtraList); + std::vector<std::string> controlExtraList = cmExpandedList(ControlExtra); for (std::string const& i : controlExtraList) { std::string filenamename = cmsys::SystemTools::GetFilenameName(i); std::string localcopy = WorkDir + "/" + filenamename; @@ -439,7 +437,7 @@ cmCPackDebGenerator::~cmCPackDebGenerator() = default; int cmCPackDebGenerator::InitializeInternal() { this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/usr"); - if (cmSystemTools::IsOff(this->GetOption("CPACK_SET_DESTDIR"))) { + if (cmIsOff(this->GetOption("CPACK_SET_DESTDIR"))) { this->SetOption("CPACK_SET_DESTDIR", "I_ON"); } return this->Superclass::InitializeInternal(); @@ -468,8 +466,7 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, // Tell CPackDeb.cmake the name of the component GROUP. this->SetOption("CPACK_DEB_PACKAGE_COMPONENT", packageName.c_str()); // Tell CPackDeb.cmake the path where the component is. - std::string component_path = "/"; - component_path += packageName; + std::string component_path = cmStrCat('/', packageName); this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH", component_path.c_str()); if (!this->ReadListFile("Internal/CPack/CPackDeb.cmake")) { @@ -499,9 +496,8 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, retval = 0; } // add the generated package to package file names list - packageFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - packageFileName += "/"; - packageFileName += this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"); + packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', + this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME")); packageFileNames.push_back(std::move(packageFileName)); if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE")) { @@ -523,9 +519,9 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, retval = 0; } // add the generated package to package file names list - packageFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - packageFileName += "/"; - packageFileName += this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"); + packageFileName = + cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', + this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME")); packageFileNames.push_back(std::move(packageFileName)); } @@ -613,8 +609,7 @@ int cmCPackDebGenerator::PackageComponentsAllInOne( if (!compInstDirName.empty()) { // Tell CPackDeb.cmake the path where the component is. - std::string component_path = "/"; - component_path += compInstDirName; + std::string component_path = cmStrCat('/', compInstDirName); this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH", component_path.c_str()); } @@ -643,9 +638,8 @@ int cmCPackDebGenerator::PackageComponentsAllInOne( retval = 0; } // add the generated package to package file names list - packageFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - packageFileName += "/"; - packageFileName += this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"); + packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', + this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME")); packageFileNames.push_back(std::move(packageFileName)); return retval; } diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index 7a3742b..ca06b81 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -6,6 +6,7 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmsys/FStream.hxx" @@ -127,9 +128,8 @@ int cmCPackDragNDropGenerator::InitializeInternal() return 0; } - std::vector<std::string> languages; - cmSystemTools::ExpandListArgument( - this->GetOption("CPACK_DMG_SLA_LANGUAGES"), languages); + std::vector<std::string> languages = + cmExpandedList(this->GetOption("CPACK_DMG_SLA_LANGUAGES")); if (languages.empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_DMG_SLA_LANGUAGES set but empty" << std::endl); @@ -196,9 +196,7 @@ int cmCPackDragNDropGenerator::PackageFiles() full_package_name += std::string(GetOutputExtension()); packageFileNames.push_back(full_package_name); - std::string src_dir = toplevel; - src_dir += "/"; - src_dir += package_file; + std::string src_dir = cmStrCat(toplevel, '/', package_file); if (0 == this->CreateDMG(src_dir, full_package_name)) { return 0; @@ -409,8 +407,8 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, } // Create a temporary read-write disk image ... - std::string temp_image = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - temp_image += "/temp.dmg"; + std::string temp_image = + cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/temp.dmg"); std::string create_error; std::ostringstream temp_image_command; @@ -522,12 +520,12 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, if (!cpack_license_file.empty() || !slaDirectory.empty()) { // Use old hardcoded style if sla_dir is not set bool oldStyle = slaDirectory.empty(); - std::string sla_r = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - sla_r += "/sla.r"; + std::string sla_r = + cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/sla.r"); std::vector<std::string> languages; if (!oldStyle) { - cmSystemTools::ExpandListArgument(cpack_dmg_languages, languages); + cmExpandList(cpack_dmg_languages, languages); } cmGeneratedFileStream ofs(sla_r); @@ -649,8 +647,8 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, if (temp_image_format != "UDZO") { temp_image_format = "UDZO"; // convert to UDZO to enable unflatten/flatten - std::string temp_udzo = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - temp_udzo += "/temp-udzo.dmg"; + std::string temp_udzo = cmStrCat( + this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/temp-udzo.dmg"); std::ostringstream udco_image_command; udco_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); diff --git a/Source/CPack/cmCPackExternalGenerator.cxx b/Source/CPack/cmCPackExternalGenerator.cxx index 9dc9853..5dc6ace 100644 --- a/Source/CPack/cmCPackExternalGenerator.cxx +++ b/Source/CPack/cmCPackExternalGenerator.cxx @@ -2,10 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackExternalGenerator.h" -#include "cmAlgorithms.h" #include "cmCPackComponentGroup.h" #include "cmCPackLog.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cm_jsoncpp_value.h" @@ -17,6 +17,8 @@ #include <utility> #include <vector> +#include "cm_memory.hxx" + int cmCPackExternalGenerator::InitializeInternal() { this->SetOption("CPACK_EXTERNAL_KNOWN_VERSIONS", "1.0"); @@ -148,8 +150,7 @@ int cmCPackExternalGenerator::InstallCMakeProject( bool cmCPackExternalGenerator::StagingEnabled() const { - return !cmSystemTools::IsOff( - this->GetOption("CPACK_EXTERNAL_ENABLE_STAGING")); + return !cmIsOff(this->GetOption("CPACK_EXTERNAL_ENABLE_STAGING")); } cmCPackExternalGenerator::cmCPackExternalVersionGenerator:: @@ -207,8 +208,7 @@ int cmCPackExternalGenerator::cmCPackExternalVersionGenerator::WriteToJSON( if (defaultDirectoryPermissions && *defaultDirectoryPermissions) { root["defaultDirectoryPermissions"] = defaultDirectoryPermissions; } - if (cmSystemTools::IsInternallyOn( - this->Parent->GetOption("CPACK_SET_DESTDIR"))) { + if (cmIsInternallyOn(this->Parent->GetOption("CPACK_SET_DESTDIR"))) { root["setDestdir"] = true; root["packagingInstallPrefix"] = this->Parent->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"); @@ -216,8 +216,7 @@ int cmCPackExternalGenerator::cmCPackExternalVersionGenerator::WriteToJSON( root["setDestdir"] = false; } - root["stripFiles"] = - !cmSystemTools::IsOff(this->Parent->GetOption("CPACK_STRIP_FILES")); + root["stripFiles"] = !cmIsOff(this->Parent->GetOption("CPACK_STRIP_FILES")); root["warnOnAbsoluteInstallDestination"] = this->Parent->IsOn("CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION"); root["errorOnAbsoluteInstallDestination"] = diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx index 9fdafa4..a35977c 100644 --- a/Source/CPack/cmCPackFreeBSDGenerator.cxx +++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx @@ -6,6 +6,7 @@ #include "cmCPackArchiveGenerator.h" #include "cmCPackLog.h" #include "cmGeneratedFileStream.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" // Needed for ::open() and ::stat() @@ -227,9 +228,8 @@ void cmCPackFreeBSDGenerator::write_manifest_fields( manifest << ManifestKeyValue( "desc", var_lookup("CPACK_FREEBSD_PACKAGE_DESCRIPTION")); manifest << ManifestKeyValue("www", var_lookup("CPACK_FREEBSD_PACKAGE_WWW")); - std::vector<std::string> licenses; - cmSystemTools::ExpandListArgument( - var_lookup("CPACK_FREEBSD_PACKAGE_LICENSE"), licenses); + std::vector<std::string> licenses = + cmExpandedList(var_lookup("CPACK_FREEBSD_PACKAGE_LICENSE")); std::string licenselogic("single"); if (licenses.empty()) { cmSystemTools::SetFatalErrorOccured(); @@ -238,14 +238,12 @@ void cmCPackFreeBSDGenerator::write_manifest_fields( } manifest << ManifestKeyValue("licenselogic", licenselogic); manifest << (ManifestKeyListValue("licenses") << licenses); - std::vector<std::string> categories; - cmSystemTools::ExpandListArgument( - var_lookup("CPACK_FREEBSD_PACKAGE_CATEGORIES"), categories); + std::vector<std::string> categories = + cmExpandedList(var_lookup("CPACK_FREEBSD_PACKAGE_CATEGORIES")); manifest << (ManifestKeyListValue("categories") << categories); manifest << ManifestKeyValue("prefix", var_lookup("CMAKE_INSTALL_PREFIX")); - std::vector<std::string> deps; - cmSystemTools::ExpandListArgument(var_lookup("CPACK_FREEBSD_PACKAGE_DEPS"), - deps); + std::vector<std::string> deps = + cmExpandedList(var_lookup("CPACK_FREEBSD_PACKAGE_DEPS")); if (!deps.empty()) { manifest << (ManifestKeyDepsValue("deps") << deps); } diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 7e07ff4..288d5d8 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -7,7 +7,7 @@ #include "cmsys/RegularExpression.hxx" #include <algorithm> #include <cstring> -#include <memory> // IWYU pragma: keep +#include <memory> #include <utility> #include "cmCPackComponentGroup.h" @@ -21,6 +21,7 @@ #include "cmMakefile.h" #include "cmState.h" #include "cmStateSnapshot.h" +#include "cmStringAlgorithms.h" #include "cmVersion.h" #include "cmWorkingDirectory.h" #include "cmXMLSafe.h" @@ -72,8 +73,8 @@ int cmCPackGenerator::PrepareNames() } } - std::string tempDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY"); - tempDirectory += "/_CPack_Packages/"; + std::string tempDirectory = + cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/_CPack_Packages/"); const char* toplevelTag = this->GetOption("CPACK_TOPLEVEL_TAG"); if (toplevelTag) { tempDirectory += toplevelTag; @@ -179,8 +180,8 @@ int cmCPackGenerator::InstallProject() std::string bareTempInstallDirectory = this->GetOption("CPACK_TEMPORARY_INSTALL_DIRECTORY"); std::string tempInstallDirectoryStr = bareTempInstallDirectory; - bool setDestDir = cmSystemTools::IsOn(this->GetOption("CPACK_SET_DESTDIR")) | - cmSystemTools::IsInternallyOn(this->GetOption("CPACK_SET_DESTDIR")); + bool setDestDir = cmIsOn(this->GetOption("CPACK_SET_DESTDIR")) | + cmIsInternallyOn(this->GetOption("CPACK_SET_DESTDIR")); if (!setDestDir) { tempInstallDirectoryStr += this->GetPackagingInstallPrefix(); } @@ -196,8 +197,7 @@ int cmCPackGenerator::InstallProject() } if (setDestDir) { - std::string destDir = "DESTDIR="; - destDir += tempInstallDirectory; + std::string destDir = cmStrCat("DESTDIR=", tempInstallDirectory); cmSystemTools::PutEnv(destDir); } else { // Make sure there is no destdir @@ -210,8 +210,8 @@ int cmCPackGenerator::InstallProject() const char* default_dir_install_permissions = this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); if (default_dir_install_permissions && *default_dir_install_permissions) { - std::vector<std::string> items; - cmSystemTools::ExpandListArgument(default_dir_install_permissions, items); + std::vector<std::string> items = + cmExpandedList(default_dir_install_permissions); for (const auto& arg : items) { if (!cmFSPermissions::stringToModeT(arg, default_dir_mode_v)) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -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)) { @@ -270,11 +270,11 @@ int cmCPackGenerator::InstallProjectViaInstallCommands( (void)setDestDir; const char* installCommands = this->GetOption("CPACK_INSTALL_COMMANDS"); if (installCommands && *installCommands) { - std::string tempInstallDirectoryEnv = "CMAKE_INSTALL_PREFIX="; - tempInstallDirectoryEnv += tempInstallDirectory; + std::string tempInstallDirectoryEnv = + cmStrCat("CMAKE_INSTALL_PREFIX=", tempInstallDirectory); cmSystemTools::PutEnv(tempInstallDirectoryEnv); - std::vector<std::string> installCommandsVector; - cmSystemTools::ExpandListArgument(installCommands, installCommandsVector); + std::vector<std::string> installCommandsVector = + cmExpandedList(installCommands); for (std::string const& ic : installCommandsVector) { cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ic << std::endl); std::string output; @@ -283,8 +283,8 @@ int cmCPackGenerator::InstallProjectViaInstallCommands( ic, &output, &output, &retVal, nullptr, this->GeneratorVerbose, cmDuration::zero()); if (!resB || retVal) { - std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - tmpFile += "/InstallOutput.log"; + std::string tmpFile = cmStrCat( + this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/InstallOutput.log"); cmGeneratedFileStream ofs(tmpFile); ofs << "# Run command: " << ic << std::endl << "# Output:" << std::endl @@ -310,9 +310,8 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( std::vector<cmsys::RegularExpression> ignoreFilesRegex; const char* cpackIgnoreFiles = this->GetOption("CPACK_IGNORE_FILES"); if (cpackIgnoreFiles) { - std::vector<std::string> ignoreFilesRegexString; - cmSystemTools::ExpandListArgument(cpackIgnoreFiles, - ignoreFilesRegexString); + std::vector<std::string> ignoreFilesRegexString = + cmExpandedList(cpackIgnoreFiles); for (std::string const& ifr : ignoreFilesRegexString) { cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Create ignore files regex for: " << ifr << std::endl); @@ -322,9 +321,8 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( const char* installDirectories = this->GetOption("CPACK_INSTALLED_DIRECTORIES"); if (installDirectories && *installDirectories) { - std::vector<std::string> installDirectoriesVector; - cmSystemTools::ExpandListArgument(installDirectories, - installDirectoriesVector); + std::vector<std::string> installDirectoriesVector = + cmExpandedList(installDirectories); if (installDirectoriesVector.size() % 2 != 0) { cmCPackLogger( cmCPackLog::LOG_ERROR, @@ -344,8 +342,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( std::string top = *it; it++; std::string subdir = *it; - std::string findExpr = top; - findExpr += "/*"; + std::string findExpr = cmStrCat(top, "/*"); cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Install directory: " << top << std::endl); gl.RecurseOn(); @@ -373,8 +370,8 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( if (skip) { continue; } - std::string filePath = tempDir; - filePath += "/" + subdir + "/" + cmSystemTools::RelativePath(top, gf); + std::string filePath = cmStrCat(tempDir, '/', subdir, '/', + cmSystemTools::RelativePath(top, gf)); cmCPackLogger(cmCPackLog::LOG_DEBUG, "Copy file: " << inFile << " -> " << filePath << std::endl); @@ -399,8 +396,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( /* rebuild symlinks in the installed tree */ if (!symlinkedFiles.empty()) { std::string curDir = cmSystemTools::GetCurrentWorkingDirectory(); - std::string goToDir = tempDir; - goToDir += "/" + subdir; + std::string goToDir = cmStrCat(tempDir, '/', subdir); cmCPackLogger(cmCPackLog::LOG_DEBUG, "Change dir to: " << goToDir << std::endl); cmWorkingDirectory workdir(goToDir); @@ -448,12 +444,23 @@ 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); - std::vector<std::string> cmakeScriptsVector; - cmSystemTools::ExpandListArgument(cmakeScripts, cmakeScriptsVector); + std::vector<std::string> cmakeScriptsVector = cmExpandedList(cmakeScripts); for (std::string const& installScript : cmakeScriptsVector) { cmCPackLogger(cmCPackLog::LOG_OUTPUT, @@ -517,8 +524,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( << std::endl); return 0; } - std::vector<std::string> cmakeProjectsVector; - cmSystemTools::ExpandListArgument(cmakeProjects, cmakeProjectsVector); + std::vector<std::string> cmakeProjectsVector = + cmExpandedList(cmakeProjects); std::vector<std::string>::iterator it; for (it = cmakeProjectsVector.begin(); it != cmakeProjectsVector.end(); ++it) { @@ -562,8 +569,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( cmSystemTools::UpperCase(project.Component) + "_INSTALL_TYPES"; const char* installTypes = this->GetOption(installTypesVar); if (installTypes && *installTypes) { - std::vector<std::string> installTypesVector; - cmSystemTools::ExpandListArgument(installTypes, installTypesVector); + std::vector<std::string> installTypesVector = + cmExpandedList(installTypes); for (std::string const& installType : installTypesVector) { project.InstallationTypes.push_back( this->GetInstallationType(project.ProjectName, installType)); @@ -575,7 +582,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( "CPACK_COMPONENTS_" + cmSystemTools::UpperCase(project.Component); const char* components = this->GetOption(componentsVar); if (components && *components) { - cmSystemTools::ExpandListArgument(components, componentsVector); + cmExpandList(components, componentsVector); for (std::string const& comp : componentsVector) { project.Components.push_back( this->GetComponent(project.ProjectName, comp)); @@ -651,8 +658,8 @@ int cmCPackGenerator::RunPreinstallTarget( buildCommand, &output, &output, &retVal, installDirectory.c_str(), this->GeneratorVerbose, cmDuration::zero()); if (!resB || retVal) { - std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - tmpFile += "/PreinstallOutput.log"; + std::string tmpFile = cmStrCat( + this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/PreinstallOutput.log"); cmGeneratedFileStream ofs(tmpFile); ofs << "# Run command: " << buildCommand << std::endl << "# Directory: " << installDirectory << std::endl @@ -739,7 +746,7 @@ int cmCPackGenerator::InstallCMakeProject( // CPACK_PACKAGING_INSTALL_PREFIX // I know this is tricky and awkward but it's the price for // CPACK_SET_DESTDIR backward compatibility. - if (cmSystemTools::IsInternallyOn(this->GetOption("CPACK_SET_DESTDIR"))) { + if (cmIsInternallyOn(this->GetOption("CPACK_SET_DESTDIR"))) { this->SetOption("CPACK_INSTALL_PREFIX", this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX")); } @@ -747,7 +754,7 @@ int cmCPackGenerator::InstallCMakeProject( if (this->GetOption("CPACK_INSTALL_PREFIX")) { dir += this->GetOption("CPACK_INSTALL_PREFIX"); } - mf.AddDefinition("CMAKE_INSTALL_PREFIX", dir.c_str()); + mf.AddDefinition("CMAKE_INSTALL_PREFIX", dir); cmCPackLogger( cmCPackLog::LOG_DEBUG, @@ -760,7 +767,7 @@ int cmCPackGenerator::InstallCMakeProject( // Make sure that DESTDIR + CPACK_INSTALL_PREFIX directory // exists: // - if (cmSystemTools::StringStartsWith(dir.c_str(), "/")) { + if (cmHasLiteralPrefix(dir, "/")) { dir = tempInstallDirectory + dir; } else { dir = tempInstallDirectory + "/" + dir; @@ -787,7 +794,7 @@ int cmCPackGenerator::InstallCMakeProject( return 0; } } else { - mf.AddDefinition("CMAKE_INSTALL_PREFIX", tempInstallDirectory.c_str()); + mf.AddDefinition("CMAKE_INSTALL_PREFIX", tempInstallDirectory); if (!cmsys::SystemTools::MakeDirectory(tempInstallDirectory, default_dir_mode)) { @@ -806,16 +813,16 @@ int cmCPackGenerator::InstallCMakeProject( } if (!buildConfig.empty()) { - mf.AddDefinition("BUILD_TYPE", buildConfig.c_str()); + mf.AddDefinition("BUILD_TYPE", buildConfig); } std::string installComponentLowerCase = cmSystemTools::LowerCase(component); if (installComponentLowerCase != "all") { - mf.AddDefinition("CMAKE_INSTALL_COMPONENT", component.c_str()); + mf.AddDefinition("CMAKE_INSTALL_COMPONENT", component); } // strip on TRUE, ON, 1, one or several file names, but not on // FALSE, OFF, 0 and an empty string - if (!cmSystemTools::IsOff(this->GetOption("CPACK_STRIP_FILES"))) { + if (!cmIsOff(this->GetOption("CPACK_STRIP_FILES"))) { mf.AddDefinition("CMAKE_INSTALL_DO_STRIP", "1"); } // Remember the list of files before installation @@ -851,9 +858,8 @@ int cmCPackGenerator::InstallCMakeProject( // forward definition of CMAKE_ABSOLUTE_DESTINATION_FILES // to CPack (may be used by generators like CPack RPM or DEB) // in order to transparently handle ABSOLUTE PATH - if (mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) { - mf.AddDefinition("CPACK_ABSOLUTE_DESTINATION_FILES", - mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")); + if (const char* def = mf.GetDefinition("CMAKE_ABSOLUTE_DESTINATION_FILES")) { + mf.AddDefinition("CPACK_ABSOLUTE_DESTINATION_FILES", def); } // Now rebuild the list of files after installation @@ -901,10 +907,8 @@ int cmCPackGenerator::InstallCMakeProject( GetComponentInstallDirNameSuffix(component); if (nullptr != this->GetOption(absoluteDestFileComponent)) { std::string absoluteDestFilesListComponent = - this->GetOption(absoluteDestFileComponent); - absoluteDestFilesListComponent += ";"; - absoluteDestFilesListComponent += - mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"); + cmStrCat(this->GetOption(absoluteDestFileComponent), ';', + mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES")); this->SetOption(absoluteDestFileComponent, absoluteDestFilesListComponent.c_str()); } else { @@ -967,8 +971,7 @@ int cmCPackGenerator::DoPackage() return 0; } - if (cmSystemTools::IsOn( - this->GetOption("CPACK_REMOVE_TOPLEVEL_DIRECTORY"))) { + if (cmIsOn(this->GetOption("CPACK_REMOVE_TOPLEVEL_DIRECTORY"))) { const char* toplevelDirectory = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); if (cmSystemTools::FileExists(toplevelDirectory)) { @@ -997,8 +1000,7 @@ int cmCPackGenerator::DoPackage() cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl); cmsys::Glob gl; - std::string findExpr = tempDirectory; - findExpr += "/*"; + std::string findExpr = cmStrCat(tempDirectory, "/*"); gl.RecurseOn(); gl.SetRecurseListDirs(true); gl.SetRecurseThroughSymlinks(false); @@ -1018,8 +1020,7 @@ int cmCPackGenerator::DoPackage() "Remove old package file" << std::endl); cmSystemTools::RemoveFile(tempPackageFileName); } - if (cmSystemTools::IsOn( - this->GetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY"))) { + if (cmIsOn(this->GetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY"))) { tempDirectory = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); } @@ -1143,14 +1144,14 @@ bool cmCPackGenerator::IsSet(const std::string& name) const bool cmCPackGenerator::IsOn(const std::string& name) const { - return cmSystemTools::IsOn(GetOption(name)); + return cmIsOn(GetOption(name)); } bool cmCPackGenerator::IsSetToOff(const std::string& op) const { const char* ret = this->MakefileMap->GetDefinition(op); if (ret && *ret) { - return cmSystemTools::IsOff(ret); + return cmIsOff(ret); } return false; } @@ -1195,8 +1196,7 @@ const char* cmCPackGenerator::GetInstallPath() if (cmsys::SystemTools::GetEnv("ProgramFiles", prgfiles)) { this->InstallPath = prgfiles; } else if (cmsys::SystemTools::GetEnv("SystemDrive", sysDrive)) { - this->InstallPath = sysDrive; - this->InstallPath += "/Program Files"; + this->InstallPath = cmStrCat(sysDrive, "/Program Files"); } else { this->InstallPath = "c:/Program Files"; } @@ -1464,7 +1464,7 @@ cmCPackComponent* cmCPackGenerator::GetComponent( component->IsRequired = this->IsOn(macroPrefix + "_REQUIRED"); component->IsDisabledByDefault = this->IsOn(macroPrefix + "_DISABLED"); component->IsDownloaded = this->IsOn(macroPrefix + "_DOWNLOADED") || - cmSystemTools::IsOn(this->GetOption("CPACK_DOWNLOAD_ALL")); + cmIsOn(this->GetOption("CPACK_DOWNLOAD_ALL")); const char* archiveFile = this->GetOption(macroPrefix + "_ARCHIVE_FILE"); if (archiveFile && *archiveFile) { @@ -1492,8 +1492,8 @@ cmCPackComponent* cmCPackGenerator::GetComponent( // Determine the installation types. const char* installTypes = this->GetOption(macroPrefix + "_INSTALL_TYPES"); if (installTypes && *installTypes) { - std::vector<std::string> installTypesVector; - cmSystemTools::ExpandListArgument(installTypes, installTypesVector); + std::vector<std::string> installTypesVector = + cmExpandedList(installTypes); for (std::string const& installType : installTypesVector) { component->InstallationTypes.push_back( this->GetInstallationType(projectName, installType)); @@ -1503,8 +1503,7 @@ cmCPackComponent* cmCPackGenerator::GetComponent( // Determine the component dependencies. const char* depends = this->GetOption(macroPrefix + "_DEPENDS"); if (depends && *depends) { - std::vector<std::string> dependsVector; - cmSystemTools::ExpandListArgument(depends, dependsVector); + std::vector<std::string> dependsVector = cmExpandedList(depends); for (std::string const& depend : dependsVector) { cmCPackComponent* child = GetComponent(projectName, depend); component->Dependencies.push_back(child); diff --git a/Source/CPack/cmCPackLog.cxx b/Source/CPack/cmCPackLog.cxx index a3ca4b5..ca675fd 100644 --- a/Source/CPack/cmCPackLog.cxx +++ b/Source/CPack/cmCPackLog.cxx @@ -83,7 +83,7 @@ void cmCPackLog::Log(int tag, const char* file, int line, const char* msg, if (!tagString.empty()) { tagString += ","; } - tagString = "VERBOSE"; + tagString += "VERBOSE"; } } if (tag & LOG_WARNING) { @@ -93,7 +93,7 @@ void cmCPackLog::Log(int tag, const char* file, int line, const char* msg, if (!tagString.empty()) { tagString += ","; } - tagString = "WARNING"; + tagString += "WARNING"; } } if (tag & LOG_ERROR) { @@ -103,7 +103,7 @@ void cmCPackLog::Log(int tag, const char* file, int line, const char* msg, if (!tagString.empty()) { tagString += ","; } - tagString = "ERROR"; + tagString += "ERROR"; } } if (tag & LOG_DEBUG && this->Debug) { @@ -113,7 +113,7 @@ void cmCPackLog::Log(int tag, const char* file, int line, const char* msg, if (!tagString.empty()) { tagString += ","; } - tagString = "DEBUG"; + tagString += "DEBUG"; } useFileAndLine = true; } @@ -124,7 +124,7 @@ void cmCPackLog::Log(int tag, const char* file, int line, const char* msg, if (!tagString.empty()) { tagString += ","; } - tagString = "VERBOSE"; + tagString += "VERBOSE"; } } if (this->Quiet) { diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index e2020c5..8098edf 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -2,11 +2,13 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackNSISGenerator.h" +#include "cmAlgorithms.h" #include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmsys/Directory.hxx" @@ -36,7 +38,8 @@ int cmCPackNSISGenerator::PackageFiles() { // TODO: Fix nsis to force out file name - std::string nsisInFileName = this->FindTemplate("NSIS.template.in"); + std::string nsisInFileName = + this->FindTemplate("Internal/CPack/NSIS.template.in"); if (nsisInFileName.empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPack error: Could not find NSIS installer template file." @@ -44,7 +47,7 @@ int cmCPackNSISGenerator::PackageFiles() return false; } std::string nsisInInstallOptions = - this->FindTemplate("NSIS.InstallOptions.ini.in"); + this->FindTemplate("Internal/CPack/NSIS.InstallOptions.ini.in"); if (nsisInInstallOptions.empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPack error: Could not find NSIS installer options file." @@ -53,8 +56,7 @@ int cmCPackNSISGenerator::PackageFiles() } std::string nsisFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - std::string tmpFile = nsisFileName; - tmpFile += "/NSISOutput.log"; + std::string tmpFile = cmStrCat(nsisFileName, "/NSISOutput.log"); std::string nsisInstallOptions = nsisFileName + "/NSIS.InstallOptions.ini"; nsisFileName += "/project.nsi"; std::ostringstream str; @@ -139,39 +141,34 @@ int cmCPackNSISGenerator::PackageFiles() installerIconCode.c_str()); } if (this->IsSet("CPACK_PACKAGE_ICON")) { - std::string installerIconCode = "!define MUI_HEADERIMAGE_BITMAP \""; - installerIconCode += this->GetOption("CPACK_PACKAGE_ICON"); - installerIconCode += "\"\n"; + std::string installerIconCode = + cmStrCat("!define MUI_HEADERIMAGE_BITMAP \"", + this->GetOption("CPACK_PACKAGE_ICON"), "\"\n"); this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_ICON_CODE", installerIconCode.c_str()); } if (this->IsSet("CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP")) { - std::string installerBitmapCode = - "!define MUI_WELCOMEFINISHPAGE_BITMAP \""; - installerBitmapCode += - this->GetOption("CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP"); - installerBitmapCode += "\"\n"; + std::string installerBitmapCode = cmStrCat( + "!define MUI_WELCOMEFINISHPAGE_BITMAP \"", + this->GetOption("CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP"), "\"\n"); this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_WELCOMEFINISH_CODE", installerBitmapCode.c_str()); } if (this->IsSet("CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP")) { - std::string installerBitmapCode = - "!define MUI_UNWELCOMEFINISHPAGE_BITMAP \""; - installerBitmapCode += - this->GetOption("CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP"); - installerBitmapCode += "\"\n"; + std::string installerBitmapCode = cmStrCat( + "!define MUI_UNWELCOMEFINISHPAGE_BITMAP \"", + this->GetOption("CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP"), "\"\n"); this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_UNWELCOMEFINISH_CODE", installerBitmapCode.c_str()); } if (this->IsSet("CPACK_NSIS_MUI_FINISHPAGE_RUN")) { - std::string installerRunCode = "!define MUI_FINISHPAGE_RUN \"$INSTDIR\\"; - installerRunCode += this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY"); - installerRunCode += "\\"; - installerRunCode += this->GetOption("CPACK_NSIS_MUI_FINISHPAGE_RUN"); - installerRunCode += "\"\n"; + std::string installerRunCode = + cmStrCat("!define MUI_FINISHPAGE_RUN \"$INSTDIR\\", + this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY"), '\\', + this->GetOption("CPACK_NSIS_MUI_FINISHPAGE_RUN"), "\"\n"); this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_FINISHPAGE_RUN_CODE", installerRunCode.c_str()); } @@ -273,7 +270,7 @@ int cmCPackNSISGenerator::PackageFiles() if (anyDownloadedComponents) { defines += "!define CPACK_USES_DOWNLOAD\n"; - if (cmSystemTools::IsOn(this->GetOption("CPACK_ADD_REMOVE"))) { + if (cmIsOn(this->GetOption("CPACK_ADD_REMOVE"))) { defines += "!define CPACK_NSIS_ADD_REMOVE\n"; } } @@ -294,9 +291,9 @@ int cmCPackNSISGenerator::PackageFiles() this->ConfigureFile(nsisInInstallOptions, nsisInstallOptions); this->ConfigureFile(nsisInFileName, nsisFileName); - std::string nsisCmd = "\""; - nsisCmd += this->GetOption("CPACK_INSTALLER_PROGRAM"); - nsisCmd += "\" \"" + nsisFileName + "\""; + std::string nsisCmd = + cmStrCat('"', this->GetOption("CPACK_INSTALLER_PROGRAM"), "\" \"", + nsisFileName, '"'); cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << nsisCmd << std::endl); std::string output; int retVal = 1; @@ -320,8 +317,7 @@ int cmCPackNSISGenerator::PackageFiles() int cmCPackNSISGenerator::InitializeInternal() { - if (cmSystemTools::IsOn( - this->GetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY"))) { + if (cmIsOn(this->GetOption("CPACK_INCLUDE_TOPLEVEL_DIRECTORY"))) { cmCPackLogger( cmCPackLog::LOG_WARNING, "NSIS Generator cannot work with CPACK_INCLUDE_TOPLEVEL_DIRECTORY set. " @@ -413,8 +409,7 @@ int cmCPackNSISGenerator::InitializeInternal() if (!resS || retVal || (!versionRex.find(output) && !versionRexCVS.find(output))) { const char* topDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - std::string tmpFile = topDir ? topDir : "."; - tmpFile += "/NSISOutput.log"; + std::string tmpFile = cmStrCat(topDir ? topDir : ".", "/NSISOutput.log"); cmGeneratedFileStream ofs(tmpFile); ofs << "# Run command: " << nsisCmd << std::endl << "# Output:" << std::endl @@ -458,8 +453,7 @@ int cmCPackNSISGenerator::InitializeInternal() "CPACK_CREATE_DESKTOP_LINKS: " << cpackPackageDeskTopLinks << std::endl); - cmSystemTools::ExpandListArgument(cpackPackageDeskTopLinks, - cpackPackageDesktopLinksVector); + cmExpandList(cpackPackageDeskTopLinks, cpackPackageDesktopLinksVector); for (std::string const& cpdl : cpackPackageDesktopLinksVector) { cmCPackLogger(cmCPackLog::LOG_DEBUG, "CPACK_CREATE_DESKTOP_LINKS: " << cpdl << std::endl); @@ -477,9 +471,8 @@ int cmCPackNSISGenerator::InitializeInternal() cmCPackLogger(cmCPackLog::LOG_DEBUG, "The cpackPackageExecutables: " << cpackPackageExecutables << "." << std::endl); - std::vector<std::string> cpackPackageExecutablesVector; - cmSystemTools::ExpandListArgument(cpackPackageExecutables, - cpackPackageExecutablesVector); + std::vector<std::string> cpackPackageExecutablesVector = + cmExpandedList(cpackPackageExecutables); if (cpackPackageExecutablesVector.size() % 2 != 0) { cmCPackLogger( cmCPackLog::LOG_ERROR, @@ -501,10 +494,7 @@ int cmCPackNSISGenerator::InitializeInternal() << ".lnk\"" << std::endl; // see if CPACK_CREATE_DESKTOP_LINK_ExeName is on // if so add a desktop link - if (!cpackPackageDesktopLinksVector.empty() && - std::find(cpackPackageDesktopLinksVector.begin(), - cpackPackageDesktopLinksVector.end(), - execName) != cpackPackageDesktopLinksVector.end()) { + if (cmContains(cpackPackageDesktopLinksVector, execName)) { str << " StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2\n"; str << " CreateShortCut \"$DESKTOP\\" << linkName << R"(.lnk" "$INSTDIR\)" << cpackNsisExecutablesDirectory << "\\" @@ -534,8 +524,8 @@ void cmCPackNSISGenerator::CreateMenuLinks(std::ostream& str, } cmCPackLogger(cmCPackLog::LOG_DEBUG, "The cpackMenuLinks: " << cpackMenuLinks << "." << std::endl); - std::vector<std::string> cpackMenuLinksVector; - cmSystemTools::ExpandListArgument(cpackMenuLinks, cpackMenuLinksVector); + std::vector<std::string> cpackMenuLinksVector = + cmExpandedList(cpackMenuLinks); if (cpackMenuLinksVector.size() % 2 != 0) { cmCPackLogger( cmCPackLog::LOG_ERROR, @@ -576,8 +566,7 @@ void cmCPackNSISGenerator::CreateMenuLinks(std::ostream& str, } // see if CPACK_CREATE_DESKTOP_LINK_ExeName is on // if so add a desktop link - std::string desktop = "CPACK_CREATE_DESKTOP_LINK_"; - desktop += linkName; + std::string desktop = cmStrCat("CPACK_CREATE_DESKTOP_LINK_", linkName); if (this->IsSet(desktop)) { str << " StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2\n"; str << " CreateShortCut \"$DESKTOP\\" << linkName @@ -659,8 +648,8 @@ std::string cmCPackNSISGenerator::CreateComponentDescription( if (component->IsDownloaded) { if (component->ArchiveFile.empty()) { // Compute the name of the archive. - std::string packagesDir = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); - packagesDir += ".dummy"; + std::string packagesDir = + cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), ".dummy"); std::ostringstream out; out << cmSystemTools::GetFilenameWithoutLastExtension(packagesDir) << "-" << component->Name << ".zip"; @@ -674,8 +663,8 @@ std::string cmCPackNSISGenerator::CreateComponentDescription( if (userUploadDirectory && *userUploadDirectory) { uploadDirectory = userUploadDirectory; } else { - uploadDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY"); - uploadDirectory += "/CPackUploads"; + uploadDirectory = + cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/CPackUploads"); } if (!cmSystemTools::FileExists(uploadDirectory)) { if (!cmSystemTools::MakeDirectory(uploadDirectory)) { @@ -712,17 +701,14 @@ std::string cmCPackNSISGenerator::CreateComponentDescription( } // The directory where this component's files reside - std::string dirName = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); - dirName += '/'; - dirName += component->Name; - dirName += '/'; + std::string dirName = cmStrCat( + this->GetOption("CPACK_TEMPORARY_DIRECTORY"), '/', component->Name, '/'); // Build the list of files to go into this archive, and determine the // size of the installed component. - std::string zipListFileName = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); - zipListFileName += "/winZip.filelist"; - bool needQuotesInFile = - cmSystemTools::IsOn(this->GetOption("CPACK_ZIP_NEED_QUOTES")); + std::string zipListFileName = cmStrCat( + this->GetOption("CPACK_TEMPORARY_DIRECTORY"), "/winZip.filelist"); + bool needQuotesInFile = cmIsOn(this->GetOption("CPACK_ZIP_NEED_QUOTES")); unsigned long totalSize = 0; { // the scope is needed for cmGeneratedFileStream cmGeneratedFileStream out(zipListFileName); @@ -751,8 +737,8 @@ std::string cmCPackNSISGenerator::CreateComponentDescription( cmd, &output, &output, &retVal, dirName.c_str(), cmSystemTools::OUTPUT_NONE, cmDuration::zero()); if (!res || retVal) { - std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - tmpFile += "/CompressZip.log"; + std::string tmpFile = cmStrCat( + this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/CompressZip.log"); cmGeneratedFileStream ofs(tmpFile); ofs << "# Run command: " << cmd << std::endl << "# Output:" << std::endl diff --git a/Source/CPack/cmCPackNuGetGenerator.cxx b/Source/CPack/cmCPackNuGetGenerator.cxx index 76f0699..19a3a0a 100644 --- a/Source/CPack/cmCPackNuGetGenerator.cxx +++ b/Source/CPack/cmCPackNuGetGenerator.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackNuGetGenerator.h" -#include "cmAlgorithms.h" #include "cmCPackComponentGroup.h" #include "cmCPackLog.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include <algorithm> diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx index 90e0afe..992299a 100644 --- a/Source/CPack/cmCPackOSXX11Generator.cxx +++ b/Source/CPack/cmCPackOSXX11Generator.cxx @@ -8,6 +8,7 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cm_sys_stat.h" @@ -28,9 +29,8 @@ int cmCPackOSXX11Generator::PackageFiles() << "." << std::endl); std::ostringstream str; std::ostringstream deleteStr; - std::vector<std::string> cpackPackageExecutablesVector; - cmSystemTools::ExpandListArgument(cpackPackageExecutables, - cpackPackageExecutablesVector); + std::vector<std::string> cpackPackageExecutablesVector = + cmExpandedList(cpackPackageExecutables); if (cpackPackageExecutablesVector.size() % 2 != 0) { cmCPackLogger( cmCPackLog::LOG_ERROR, @@ -55,16 +55,14 @@ int cmCPackOSXX11Generator::PackageFiles() diskImageDirectory + "/.background"; // App bundle directories - std::string packageDirFileName = toplevel; - packageDirFileName += "/"; - packageDirFileName += this->GetOption("CPACK_PACKAGE_FILE_NAME"); - packageDirFileName += ".app"; + std::string packageDirFileName = cmStrCat( + toplevel, '/', this->GetOption("CPACK_PACKAGE_FILE_NAME"), ".app"); std::string contentsDirectory = packageDirFileName + "/Contents"; std::string resourcesDirectory = contentsDirectory + "/Resources"; std::string appDirectory = contentsDirectory + "/MacOS"; std::string scriptDirectory = resourcesDirectory + "/Scripts"; - std::string resourceFileName = this->GetOption("CPACK_PACKAGE_FILE_NAME"); - resourceFileName += ".rsrc"; + std::string resourceFileName = + cmStrCat(this->GetOption("CPACK_PACKAGE_FILE_NAME"), ".rsrc"); const char* dir = resourcesDirectory.c_str(); const char* appdir = appDirectory.c_str(); @@ -113,13 +111,10 @@ int cmCPackOSXX11Generator::PackageFiles() } // Two of the files need to have execute permission, so ensure they do: - std::string runTimeScript = dir; - runTimeScript += "/"; - runTimeScript += "RuntimeScript"; + std::string runTimeScript = cmStrCat(dir, "/RuntimeScript"); - std::string appScriptName = appdir; - appScriptName += "/"; - appScriptName += this->GetOption("CPACK_PACKAGE_FILE_NAME"); + std::string appScriptName = + cmStrCat(appdir, '/', this->GetOption("CPACK_PACKAGE_FILE_NAME")); mode_t mode; if (cmsys::SystemTools::GetPermissions(runTimeScript.c_str(), mode)) { @@ -139,8 +134,8 @@ int cmCPackOSXX11Generator::PackageFiles() } std::string output; - std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - tmpFile += "/hdiutilOutput.log"; + std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), + "/hdiutilOutput.log"); std::ostringstream dmgCmd; dmgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM_DISK_IMAGE") << "\" create -ov -fs HFS+ -format UDZO -srcfolder \"" @@ -228,9 +223,8 @@ bool cmCPackOSXX11Generator::CopyCreateResourceFile(const std::string& name) return false; } - std::string destFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - destFileName += "/Resources/"; - destFileName += name + ext; + std::string destFileName = cmStrCat( +this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/Resources/", name, ext ); cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: " @@ -245,9 +239,7 @@ bool cmCPackOSXX11Generator::CopyResourcePlistFile( const std::string& name, const std::string& dir, const char* outputFileName /* = 0 */, bool copyOnly /* = false */) { - std::string inFName = "CPack."; - inFName += name; - inFName += ".in"; + std::string inFName = cmStrCat("Internal/CPack/CPack.", name, ".in"); std::string inFileName = this->FindTemplate(inFName.c_str()); if (inFileName.empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -259,9 +251,7 @@ bool cmCPackOSXX11Generator::CopyResourcePlistFile( outputFileName = name.c_str(); } - std::string destFileName = dir; - destFileName += "/"; - destFileName += outputFileName; + std::string destFileName = cmStrCat(dir, '/', outputFileName); cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: " << inFileName << " to " << destFileName @@ -272,8 +262,8 @@ bool cmCPackOSXX11Generator::CopyResourcePlistFile( const char* cmCPackOSXX11Generator::GetPackagingInstallPrefix() { - this->InstallPrefix = "/"; - this->InstallPrefix += this->GetOption("CPACK_PACKAGE_FILE_NAME"); - this->InstallPrefix += ".app/Contents/Resources"; + this->InstallPrefix = + cmStrCat('/', this->GetOption("CPACK_PACKAGE_FILE_NAME"), + ".app/Contents/Resources"); return this->InstallPrefix.c_str(); } diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx index 8c22c65..3e1a51b 100644 --- a/Source/CPack/cmCPackPKGGenerator.cxx +++ b/Source/CPack/cmCPackPKGGenerator.cxx @@ -7,6 +7,7 @@ #include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" @@ -34,8 +35,8 @@ std::string cmCPackPKGGenerator::GetPackageName( const cmCPackComponent& component) { if (component.ArchiveFile.empty()) { - std::string packagesDir = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); - packagesDir += ".dummy"; + std::string packagesDir = + cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), ".dummy"); std::ostringstream out; out << cmSystemTools::GetFilenameWithoutLastExtension(packagesDir) << "-" << component.Name << ".pkg"; @@ -48,7 +49,7 @@ std::string cmCPackPKGGenerator::GetPackageName( void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile) { std::string distributionTemplate = - this->FindTemplate("CPack.distribution.dist.in"); + this->FindTemplate("Internal/CPack/CPack.distribution.dist.in"); if (distributionTemplate.empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find input file: " << distributionTemplate @@ -56,8 +57,8 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile) return; } - std::string distributionFile = metapackageFile; - distributionFile += "/Contents/distribution.dist"; + std::string distributionFile = + cmStrCat(metapackageFile, "/Contents/distribution.dist"); // Create the choice outline, which provides a tree-based view of // the components in their groups. @@ -144,12 +145,9 @@ void cmCPackPKGGenerator::CreateChoice(const cmCPackComponentGroup& group, void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component, cmXMLWriter& xout) { - std::string packageId = "com."; - packageId += this->GetOption("CPACK_PACKAGE_VENDOR"); - packageId += '.'; - packageId += this->GetOption("CPACK_PACKAGE_NAME"); - packageId += '.'; - packageId += component.Name; + std::string packageId = + cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"), '.', + this->GetOption("CPACK_PACKAGE_NAME"), '.', component.Name); xout.StartElement("choice"); xout.Attribute("id", component.Name + "Choice"); @@ -192,14 +190,13 @@ void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component, // Create a description of the package associated with this // component. - std::string relativePackageLocation = "Contents/Packages/"; - relativePackageLocation += this->GetPackageName(component); + std::string relativePackageLocation = + cmStrCat("Contents/Packages/", this->GetPackageName(component)); // Determine the installed size of the package. - std::string dirName = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); - dirName += '/'; - dirName += component.Name; - dirName += this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"); + std::string dirName = + cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), '/', component.Name, + this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX")); unsigned long installedSize = component.GetInstalledSizeInKbytes(dirName); xout.StartElement("pkg-ref"); @@ -282,9 +279,7 @@ bool cmCPackPKGGenerator::CopyCreateResourceFile(const std::string& name, return false; } - std::string destFileName = dirName; - destFileName += '/'; - destFileName += name + ext; + std::string destFileName = cmStrCat(dirName, '/', name, ext); // Set this so that distribution.dist gets the right name (without // the path). @@ -305,9 +300,7 @@ bool cmCPackPKGGenerator::CopyResourcePlistFile(const std::string& name, outName = name.c_str(); } - std::string inFName = "CPack."; - inFName += name; - inFName += ".in"; + std::string inFName = cmStrCat("Internal/CPack/CPack.", name, ".in"); std::string inFileName = this->FindTemplate(inFName.c_str()); if (inFileName.empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -315,9 +308,8 @@ bool cmCPackPKGGenerator::CopyResourcePlistFile(const std::string& name, return false; } - std::string destFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - destFileName += "/"; - destFileName += outName; + std::string destFileName = + cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', outName); cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: " << inFileName << " to " << destFileName @@ -330,9 +322,7 @@ int cmCPackPKGGenerator::CopyInstallScript(const std::string& resdir, const std::string& script, const std::string& name) { - std::string dst = resdir; - dst += "/"; - dst += name; + std::string dst = cmStrCat(resdir, '/', name); cmSystemTools::CopyFileAlways(script, dst); cmSystemTools::SetPermissions(dst.c_str(), 0777); cmCPackLogger(cmCPackLog::LOG_VERBOSE, diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx index 3d93c48..5dc36ab 100644 --- a/Source/CPack/cmCPackPackageMakerGenerator.cxx +++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx @@ -15,6 +15,7 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" @@ -47,8 +48,8 @@ int cmCPackPackageMakerGenerator::PackageFiles() this->GetOption("CPACK_TEMPORARY_DIRECTORY"); if (this->Components.empty()) { packageDirFileName += ".pkg"; - resDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - resDir += "/Resources"; + resDir = + cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/Resources"); } else { packageDirFileName += ".mpkg"; if (!cmsys::SystemTools::MakeDirectory(packageDirFileName.c_str())) { @@ -58,8 +59,7 @@ int cmCPackPackageMakerGenerator::PackageFiles() return 0; } - resDir = packageDirFileName; - resDir += "/Contents"; + resDir = cmStrCat(packageDirFileName, "/Contents"); if (!cmsys::SystemTools::MakeDirectory(resDir.c_str())) { cmCPackLogger(cmCPackLog::LOG_ERROR, "unable to create package subdirectory " << resDir @@ -155,8 +155,8 @@ int cmCPackPackageMakerGenerator::PackageFiles() if (!this->Components.empty()) { // Create the directory where component packages will be built. - std::string basePackageDir = packageDirFileName; - basePackageDir += "/Contents/Packages"; + std::string basePackageDir = + cmStrCat(packageDirFileName, "/Contents/Packages"); if (!cmsys::SystemTools::MakeDirectory(basePackageDir.c_str())) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem creating component packages directory: " @@ -172,8 +172,8 @@ int cmCPackPackageMakerGenerator::PackageFiles() if (userUploadDirectory && *userUploadDirectory) { uploadDirectory = userUploadDirectory; } else { - uploadDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY"); - uploadDirectory += "/CPackUploads"; + uploadDirectory = + cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/CPackUploads"); } // Create packages for each component @@ -232,9 +232,7 @@ int cmCPackPackageMakerGenerator::PackageFiles() packageFile += '/'; packageFile += GetPackageName(compIt->second); - std::string packageDir = toplevel; - packageDir += '/'; - packageDir += compIt->first; + std::string packageDir = cmStrCat(toplevel, '/', compIt->first); if (!this->GenerateComponentPackage( packageFile.c_str(), packageDir.c_str(), compIt->second)) { return 0; @@ -283,8 +281,8 @@ int cmCPackPackageMakerGenerator::PackageFiles() WriteDistributionFile(packageDirFileName.c_str()); } - std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - tmpFile += "/hdiutilOutput.log"; + std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), + "/hdiutilOutput.log"); std::ostringstream dmgCmd; dmgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM_DISK_IMAGE") << "\" create -ov -fs HFS+ -format UDZO -srcfolder \"" @@ -461,8 +459,8 @@ int cmCPackPackageMakerGenerator::InitializeInternal() bool cmCPackPackageMakerGenerator::RunPackageMaker(const char* command, const char* packageFile) { - std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - tmpFile += "/PackageMakerOutput.log"; + std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), + "/PackageMakerOutput.log"); cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << command << std::endl); std::string output; @@ -517,8 +515,9 @@ bool cmCPackPackageMakerGenerator::GenerateComponentPackage( this->PackageMakerVersion < 3.0) { // Create Description.plist and Info.plist files for normal Mac OS // X packages, which work on Mac OS X 10.3 and newer. - std::string descriptionFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - descriptionFile += '/' + component.Name + "-Description.plist"; + std::string descriptionFile = + cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', + component.Name, "-Description.plist"); cmsys::ofstream out(descriptionFile.c_str()); cmXMLWriter xout(out); xout.StartDocument(); @@ -539,12 +538,10 @@ bool cmCPackPackageMakerGenerator::GenerateComponentPackage( out.close(); // Create the Info.plist file for this component - std::string moduleVersionSuffix = "."; - moduleVersionSuffix += component.Name; + std::string moduleVersionSuffix = cmStrCat('.', component.Name); this->SetOption("CPACK_MODULE_VERSION_SUFFIX", moduleVersionSuffix.c_str()); - std::string infoFileName = component.Name; - infoFileName += "-Info.plist"; + std::string infoFileName = cmStrCat(component.Name, "-Info.plist"); if (!this->CopyResourcePlistFile("Info.plist", infoFileName.c_str())) { return false; } @@ -561,12 +558,9 @@ bool cmCPackPackageMakerGenerator::GenerateComponentPackage( // like normal packages, and can be downloaded by the installer // on-the-fly in Mac OS X 10.5 or newer. Thus, we need to create // flat packages when the packages will be downloaded on the fly. - std::string pkgId = "com."; - pkgId += this->GetOption("CPACK_PACKAGE_VENDOR"); - pkgId += '.'; - pkgId += this->GetOption("CPACK_PACKAGE_NAME"); - pkgId += '.'; - pkgId += component.Name; + std::string pkgId = + cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"), '.', + this->GetOption("CPACK_PACKAGE_NAME"), '.', component.Name); pkgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM") << "\" --root \"" << packageDir << "\"" diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index 94b5b5f..800af28 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.cxx +++ b/Source/CPack/cmCPackProductBuildGenerator.cxx @@ -10,6 +10,7 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmCPackProductBuildGenerator::cmCPackProductBuildGenerator() @@ -28,8 +29,8 @@ int cmCPackProductBuildGenerator::PackageFiles() this->GetOption("CPACK_TEMPORARY_DIRECTORY"); // Create the directory where component packages will be built. - std::string basePackageDir = packageDirFileName; - basePackageDir += "/Contents/Packages"; + std::string basePackageDir = + cmStrCat(packageDirFileName, "/Contents/Packages"); if (!cmsys::SystemTools::MakeDirectory(basePackageDir.c_str())) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem creating component packages directory: " @@ -41,9 +42,7 @@ int cmCPackProductBuildGenerator::PackageFiles() std::map<std::string, cmCPackComponent>::iterator compIt; for (compIt = this->Components.begin(); compIt != this->Components.end(); ++compIt) { - std::string packageDir = toplevel; - packageDir += '/'; - packageDir += compIt->first; + std::string packageDir = cmStrCat(toplevel, '/', compIt->first); if (!this->GenerateComponentPackage(basePackageDir, GetPackageName(compIt->second), packageDir, &compIt->second)) { @@ -138,8 +137,8 @@ int cmCPackProductBuildGenerator::InitializeInternal() bool cmCPackProductBuildGenerator::RunProductBuild(const std::string& command) { - std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - tmpFile += "/ProductBuildOutput.log"; + std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), + "/ProductBuildOutput.log"); cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << command << std::endl); std::string output; @@ -166,9 +165,7 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( const std::string& packageFileDir, const std::string& packageFileName, const std::string& packageDir, const cmCPackComponent* component) { - std::string packageFile = packageFileDir; - packageFile += '/'; - packageFile += packageFileName; + std::string packageFile = cmStrCat(packageFileDir, '/', packageFileName); cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Building component package: " << packageFile @@ -206,10 +203,8 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( // The command that will be used to run ProductBuild std::ostringstream pkgCmd; - std::string pkgId = "com."; - pkgId += this->GetOption("CPACK_PACKAGE_VENDOR"); - pkgId += '.'; - pkgId += this->GetOption("CPACK_PACKAGE_NAME"); + std::string pkgId = cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"), + '.', this->GetOption("CPACK_PACKAGE_NAME")); if (component) { pkgId += '.'; pkgId += component->Name; diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx index 33ab62b..0f621cc 100644 --- a/Source/CPack/cmCPackRPMGenerator.cxx +++ b/Source/CPack/cmCPackRPMGenerator.cxx @@ -12,6 +12,7 @@ #include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmCPackRPMGenerator::cmCPackRPMGenerator() = default; @@ -21,7 +22,7 @@ cmCPackRPMGenerator::~cmCPackRPMGenerator() = default; int cmCPackRPMGenerator::InitializeInternal() { this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/usr"); - if (cmSystemTools::IsOff(this->GetOption("CPACK_SET_DESTDIR"))) { + if (cmIsOff(this->GetOption("CPACK_SET_DESTDIR"))) { this->SetOption("CPACK_SET_DESTDIR", "I_ON"); } /* Replace space in CPACK_PACKAGE_NAME in order to avoid @@ -81,8 +82,7 @@ int cmCPackRPMGenerator::PackageOnePack(std::string const& initialToplevel, // Tell CPackRPM.cmake the name of the component NAME. this->SetOption("CPACK_RPM_PACKAGE_COMPONENT", packageName.c_str()); // Tell CPackRPM.cmake the path where the component is. - std::string component_path = "/"; - component_path += packageName; + std::string component_path = cmStrCat('/', packageName); this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH", component_path.c_str()); if (!this->ReadListFile("Internal/CPack/CPackRPM.cmake")) { @@ -375,8 +375,7 @@ int cmCPackRPMGenerator::PackageComponentsAllInOne( if (!compInstDirName.empty()) { // Tell CPackRPM.cmake the path where the component is. - std::string component_path = "/"; - component_path += compInstDirName; + std::string component_path = cmStrCat('/', compInstDirName); this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH", component_path.c_str()); } diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx index aba15d2..4666dc2 100644 --- a/Source/CPack/cmCPackSTGZGenerator.cxx +++ b/Source/CPack/cmCPackSTGZGenerator.cxx @@ -21,7 +21,8 @@ int cmCPackSTGZGenerator::InitializeInternal() { this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "0"); - std::string inFile = this->FindTemplate("CPack.STGZ_Header.sh.in"); + std::string inFile = + this->FindTemplate("Internal/CPack/CPack.STGZ_Header.sh.in"); if (inFile.empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find template file: " << inFile << std::endl); diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 58b9e70..69dac88 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -1,21 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmsys/CommandLineArguments.hxx" -#include "cmsys/Encoding.hxx" -#include <iostream> -#include <map> -#include <memory> // IWYU pragma: keep -#include <sstream> -#include <stddef.h> -#include <string> -#include <utility> -#include <vector> - -#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) -# include "cmsys/ConsoleBuf.hxx" -#endif - #include "cmCPackGenerator.h" #include "cmCPackGeneratorFactory.h" #include "cmCPackLog.h" @@ -26,22 +11,39 @@ #include "cmMakefile.h" #include "cmState.h" #include "cmStateSnapshot.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" -static const char* cmDocumentationName[][2] = { +#include "cmsys/CommandLineArguments.hxx" +#include "cmsys/Encoding.hxx" + +#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP) +# include "cmsys/ConsoleBuf.hxx" +#endif + +#include <iostream> +#include <map> +#include <sstream> +#include <stddef.h> +#include <string> +#include <utility> +#include <vector> + +namespace { +const char* cmDocumentationName[][2] = { { nullptr, " cpack - Packaging driver provided by CMake." }, { nullptr, nullptr } }; -static const char* cmDocumentationUsage[][2] = { +const char* cmDocumentationUsage[][2] = { // clang-format off { nullptr, " cpack [options]" }, { nullptr, nullptr } // clang-format on }; -static const char* cmDocumentationOptions[][2] = { +const char* cmDocumentationOptions[][2] = { { "-G <generators>", "Override/define CPACK_GENERATOR" }, { "-C <Configuration>", "Specify the project configuration" }, { "-D <var>=<value>", "Set a CPack variable." }, @@ -90,16 +92,17 @@ int cpackDefinitionArgument(const char* argument, const char* cValue, return 1; } -static void cpackProgressCallback(const std::string& message, float /*unused*/) +void cpackProgressCallback(const std::string& message, float /*unused*/) { std::cout << "-- " << message << std::endl; } +} // namespace // this is CPack. int main(int argc, char const* const* argv) { cmSystemTools::EnsureStdPipes(); -#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) +#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP) // Replace streambuf so we can output Unicode to console cmsys::ConsoleBuf::Manager consoleOut(std::cout); consoleOut.SetUTF8Pipes(); @@ -227,8 +230,8 @@ int main(int argc, char const* const* argv) bool cpackConfigFileSpecified = true; if (cpackConfigFile.empty()) { - cpackConfigFile = cmSystemTools::GetCurrentWorkingDirectory(); - cpackConfigFile += "/CPackConfig.cmake"; + cpackConfigFile = cmStrCat(cmSystemTools::GetCurrentWorkingDirectory(), + "/CPackConfig.cmake"); cpackConfigFileSpecified = false; } @@ -269,7 +272,7 @@ int main(int argc, char const* const* argv) } if (!cpackBuildConfig.empty()) { - globalMF.AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig.c_str()); + globalMF.AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig); } if (cmSystemTools::FileExists(cpackConfigFile)) { @@ -291,24 +294,21 @@ int main(int argc, char const* const* argv) } if (!generator.empty()) { - globalMF.AddDefinition("CPACK_GENERATOR", generator.c_str()); + globalMF.AddDefinition("CPACK_GENERATOR", generator); } if (!cpackProjectName.empty()) { - globalMF.AddDefinition("CPACK_PACKAGE_NAME", cpackProjectName.c_str()); + globalMF.AddDefinition("CPACK_PACKAGE_NAME", cpackProjectName); } if (!cpackProjectVersion.empty()) { - globalMF.AddDefinition("CPACK_PACKAGE_VERSION", - cpackProjectVersion.c_str()); + globalMF.AddDefinition("CPACK_PACKAGE_VERSION", cpackProjectVersion); } if (!cpackProjectVendor.empty()) { - globalMF.AddDefinition("CPACK_PACKAGE_VENDOR", - cpackProjectVendor.c_str()); + globalMF.AddDefinition("CPACK_PACKAGE_VENDOR", cpackProjectVendor); } // if this is not empty it has been set on the command line // go for it. Command line override values set in config file. if (!cpackProjectDirectory.empty()) { - globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", - cpackProjectDirectory.c_str()); + globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", cpackProjectDirectory); } // The value has not been set on the command line else { @@ -317,11 +317,11 @@ int main(int argc, char const* const* argv) // use default value iff no value has been provided by the config file if (!globalMF.IsSet("CPACK_PACKAGE_DIRECTORY")) { globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", - cpackProjectDirectory.c_str()); + cpackProjectDirectory); } } for (auto const& cd : definitions.Map) { - globalMF.AddDefinition(cd.first, cd.second.c_str()); + globalMF.AddDefinition(cd.first, cd.second); } const char* cpackModulesPath = globalMF.GetDefinition("CPACK_MODULE_PATH"); @@ -333,8 +333,7 @@ int main(int argc, char const* const* argv) cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "CPack generator not specified" << std::endl); } else { - std::vector<std::string> generatorsVector; - cmSystemTools::ExpandListArgument(genList, generatorsVector); + std::vector<std::string> generatorsVector = cmExpandedList(genList); for (std::string const& gen : generatorsVector) { cmMakefile::ScopePushPop raii(&globalMF); cmMakefile* mf = &globalMF; @@ -425,7 +424,7 @@ int main(int argc, char const* const* argv) std::ostringstream ostr; ostr << projVersionMajor << "." << projVersionMinor << "." << projVersionPatch; - mf->AddDefinition("CPACK_PACKAGE_VERSION", ostr.str().c_str()); + mf->AddDefinition("CPACK_PACKAGE_VERSION", ostr.str()); } int res = cpackGenerator->DoPackage(); diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index 9ad9669..e7fb4c7 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -7,6 +7,7 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" #include "cmake.h" @@ -76,6 +77,11 @@ int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring, if (config) { args.push_back("-DCMAKE_BUILD_TYPE:STRING=" + std::string(config)); } + if (!this->BuildMakeProgram.empty() && + (this->BuildGenerator.find("Make") != std::string::npos || + this->BuildGenerator.find("Ninja") != std::string::npos)) { + args.push_back("-DCMAKE_MAKE_PROGRAM:FILEPATH=" + this->BuildMakeProgram); + } for (std::string const& opt : this->BuildOptions) { args.push_back(opt); @@ -284,9 +290,8 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) std::vector<std::string> extraPaths; // if this->ExecutableDirectory is set try that as well if (!this->ExecutableDirectory.empty()) { - std::string tempPath = this->ExecutableDirectory; - tempPath += "/"; - tempPath += this->TestCommand; + std::string tempPath = + cmStrCat(this->ExecutableDirectory, '/', this->TestCommand); extraPaths.push_back(tempPath); } std::vector<std::string> failed; diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx index 2eacaf1..cb22fa6 100644 --- a/Source/CTest/cmCTestBuildCommand.cxx +++ b/Source/CTest/cmCTestBuildCommand.cxx @@ -7,6 +7,7 @@ #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" @@ -90,9 +91,8 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() this->Makefile->GetCMakeInstance()->CreateGlobalGenerator( cmakeGeneratorName); if (!this->GlobalGenerator) { - std::string e = "could not create generator named \""; - e += cmakeGeneratorName; - e += "\""; + std::string e = cmStrCat("could not create generator named \"", + cmakeGeneratorName, '"'); this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e); cmSystemTools::SetFatalErrorOccured(); return nullptr; @@ -154,17 +154,15 @@ bool cmCTestBuildCommand::InitialPass(std::vector<std::string> const& args, { bool ret = cmCTestHandlerCommand::InitialPass(args, status); if (this->Values[ctb_NUMBER_ERRORS] && *this->Values[ctb_NUMBER_ERRORS]) { - std::ostringstream str; - str << this->Handler->GetTotalErrors(); - this->Makefile->AddDefinition(this->Values[ctb_NUMBER_ERRORS], - str.str().c_str()); + this->Makefile->AddDefinition( + this->Values[ctb_NUMBER_ERRORS], + std::to_string(this->Handler->GetTotalErrors())); } if (this->Values[ctb_NUMBER_WARNINGS] && *this->Values[ctb_NUMBER_WARNINGS]) { - std::ostringstream str; - str << this->Handler->GetTotalWarnings(); - this->Makefile->AddDefinition(this->Values[ctb_NUMBER_WARNINGS], - str.str().c_str()); + this->Makefile->AddDefinition( + this->Values[ctb_NUMBER_WARNINGS], + std::to_string(this->Handler->GetTotalWarnings())); } return ret; } diff --git a/Source/CTest/cmCTestBuildCommand.h b/Source/CTest/cmCTestBuildCommand.h index 77b0549..a62c301 100644 --- a/Source/CTest/cmCTestBuildCommand.h +++ b/Source/CTest/cmCTestBuildCommand.h @@ -6,13 +6,16 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmCTestHandlerCommand.h" +#include "cmCommand.h" #include <string> +#include <utility> #include <vector> +#include "cm_memory.hxx" + class cmCTestBuildHandler; class cmCTestGenericHandler; -class cmCommand; class cmExecutionStatus; class cmGlobalGenerator; @@ -30,12 +33,12 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmCTestBuildCommand* ni = new cmCTestBuildCommand; + auto ni = cm::make_unique<cmCTestBuildCommand>(); ni->CTest = this->CTest; ni->CTestScriptHandler = this->CTestScriptHandler; - return ni; + return std::unique_ptr<cmCommand>(std::move(ni)); } /** diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index c8e4fa1..147286e 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -9,6 +9,8 @@ #include "cmGeneratedFileStream.h" #include "cmMakefile.h" #include "cmProcessOutput.h" +#include "cmStringAlgorithms.h" +#include "cmStringReplaceHelper.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" @@ -246,13 +248,11 @@ void cmCTestBuildHandler::PopulateCustomVectors(cmMakefile* mf) // Record the user-specified custom warning rules. if (const char* customWarningMatchers = mf->GetDefinition("CTEST_CUSTOM_WARNING_MATCH")) { - cmSystemTools::ExpandListArgument(customWarningMatchers, - this->ReallyCustomWarningMatches); + cmExpandList(customWarningMatchers, this->ReallyCustomWarningMatches); } if (const char* customWarningExceptions = mf->GetDefinition("CTEST_CUSTOM_WARNING_EXCEPTION")) { - cmSystemTools::ExpandListArgument(customWarningExceptions, - this->ReallyCustomWarningExceptions); + cmExpandList(customWarningExceptions, this->ReallyCustomWarningExceptions); } } @@ -327,7 +327,7 @@ int cmCTestBuildHandler::ProcessHandler() std::string const& useLaunchers = this->CTest->GetCTestConfiguration("UseLaunchers"); - this->UseCTestLaunch = cmSystemTools::IsOn(useLaunchers); + this->UseCTestLaunch = cmIsOn(useLaunchers); // Create a last build log cmGeneratedFileStream ofs; @@ -384,11 +384,8 @@ int cmCTestBuildHandler::ProcessHandler() if (this->CTest->GetCTestConfiguration("SourceDirectory").size() > 20) { std::string srcdir = this->CTest->GetCTestConfiguration("SourceDirectory") + "/"; - std::string srcdirrep; for (cc = srcdir.size() - 2; cc > 0; cc--) { if (srcdir[cc] == '/') { - srcdirrep = srcdir.substr(cc); - srcdirrep = "/..." + srcdirrep; srcdir = srcdir.substr(0, cc + 1); break; } @@ -398,11 +395,8 @@ int cmCTestBuildHandler::ProcessHandler() if (this->CTest->GetCTestConfiguration("BuildDirectory").size() > 20) { std::string bindir = this->CTest->GetCTestConfiguration("BuildDirectory") + "/"; - std::string bindirrep; for (cc = bindir.size() - 2; cc > 0; cc--) { if (bindir[cc] == '/') { - bindirrep = bindir.substr(cc); - bindirrep = "/..." + bindirrep; bindir = bindir.substr(0, cc + 1); break; } @@ -415,6 +409,9 @@ int cmCTestBuildHandler::ProcessHandler() // Remember start build time this->StartBuild = this->CTest->CurrentTime(); this->StartBuildTime = std::chrono::system_clock::now(); + + cmStringReplaceHelper colorRemover("\x1b\\[[0-9;]*m", "", nullptr); + this->ColorRemover = &colorRemover; int retVal = 0; int res = cmsysProcess_State_Exited; if (!this->CTest->GetShowOnly()) { @@ -572,8 +569,7 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(cmXMLWriter& xml) std::string srcdir = this->CTest->GetCTestConfiguration("SourceDirectory"); // make sure the source dir is in the correct case on windows // via a call to collapse full path. - srcdir = cmSystemTools::CollapseFullPath(srcdir); - srcdir += "/"; + srcdir = cmStrCat(cmSystemTools::CollapseFullPath(srcdir), '/'); for (it = ew.begin(); it != ew.end() && (numErrorsAllowed || numWarningsAllowed); it++) { cmCTestBuildErrorWarning* cm = &(*it); @@ -704,10 +700,8 @@ cmCTestBuildHandler::LaunchHelper::LaunchHelper(cmCTestBuildHandler* handler) } else { // Compute a directory in which to store launcher fragments. std::string& launchDir = this->Handler->CTestLaunchDir; - launchDir = this->CTest->GetBinaryDir(); - launchDir += "/Testing/"; - launchDir += tag; - launchDir += "/Build"; + launchDir = + cmStrCat(this->CTest->GetBinaryDir(), "/Testing/", tag, "/Build"); // Clean out any existing launcher fragments. cmSystemTools::RemoveADirectory(launchDir); @@ -716,8 +710,7 @@ cmCTestBuildHandler::LaunchHelper::LaunchHelper(cmCTestBuildHandler* handler) // Enable launcher fragments. cmSystemTools::MakeDirectory(launchDir); this->WriteLauncherConfig(); - std::string launchEnv = "CTEST_LAUNCH_LOGS="; - launchEnv += launchDir; + std::string launchEnv = cmStrCat("CTEST_LAUNCH_LOGS=", launchDir); cmSystemTools::PutEnv(launchEnv); } } @@ -743,8 +736,8 @@ void cmCTestBuildHandler::LaunchHelper::WriteLauncherConfig() this->Handler->ReallyCustomWarningExceptions); // Give some testing configuration information to the launcher. - std::string fname = this->Handler->CTestLaunchDir; - fname += "/CTestLaunchConfig.cmake"; + std::string fname = + cmStrCat(this->Handler->CTestLaunchDir, "/CTestLaunchConfig.cmake"); cmGeneratedFileStream fout(fname); std::string srcdir = this->CTest->GetCTestConfiguration("SourceDirectory"); fout << "set(CTEST_SOURCE_DIRECTORY \"" << srcdir << "\")\n"; @@ -756,10 +749,8 @@ void cmCTestBuildHandler::LaunchHelper::WriteScrapeMatchers( if (matchers.empty()) { return; } - std::string fname = this->Handler->CTestLaunchDir; - fname += "/Custom"; - fname += purpose; - fname += ".txt"; + std::string fname = + cmStrCat(this->Handler->CTestLaunchDir, "/Custom", purpose, ".txt"); cmGeneratedFileStream fout(fname); for (std::string const& m : matchers) { fout << m << "\n"; @@ -898,9 +889,8 @@ int cmCTestBuildHandler::RunMakeCommand(const std::string& command, // dashboard. cmCTestBuildErrorWarning errorwarning; errorwarning.LogLine = 1; - errorwarning.Text = - "*** WARNING non-zero return value in ctest from: "; - errorwarning.Text += argv[0]; + errorwarning.Text = cmStrCat( + "*** WARNING non-zero return value in ctest from: ", argv[0]); errorwarning.PreContext.clear(); errorwarning.PostContext.clear(); errorwarning.Error = false; @@ -922,8 +912,8 @@ int cmCTestBuildHandler::RunMakeCommand(const std::string& command, // If there was an error running command, report that on the dashboard. cmCTestBuildErrorWarning errorwarning; errorwarning.LogLine = 1; - errorwarning.Text = "*** ERROR executing: "; - errorwarning.Text += cmsysProcess_GetErrorString(cp); + errorwarning.Text = + cmStrCat("*** ERROR executing: ", cmsysProcess_GetErrorString(cp)); errorwarning.PreContext.clear(); errorwarning.PostContext.clear(); errorwarning.Error = true; @@ -1084,7 +1074,12 @@ int cmCTestBuildHandler::ProcessSingleLine(const char* data) return b_REGULAR_LINE; } - cmCTestOptionalLog(this->CTest, DEBUG, "Line: [" << data << "]" << std::endl, + // Ignore ANSI color codes when checking for errors and warnings. + std::string input(data); + std::string line; + this->ColorRemover->Replace(input, line); + + cmCTestOptionalLog(this->CTest, DEBUG, "Line: [" << line << "]" << std::endl, this->Quiet); int warningLine = 0; @@ -1096,10 +1091,10 @@ int cmCTestBuildHandler::ProcessSingleLine(const char* data) // Errors int wrxCnt = 0; for (cmsys::RegularExpression& rx : this->ErrorMatchRegex) { - if (rx.find(data)) { + if (rx.find(line.c_str())) { errorLine = 1; cmCTestOptionalLog(this->CTest, DEBUG, - " Error Line: " << data << " (matches: " + " Error Line: " << line << " (matches: " << this->CustomErrorMatches[wrxCnt] << ")" << std::endl, this->Quiet); @@ -1110,11 +1105,11 @@ int cmCTestBuildHandler::ProcessSingleLine(const char* data) // Error exceptions wrxCnt = 0; for (cmsys::RegularExpression& rx : this->ErrorExceptionRegex) { - if (rx.find(data)) { + if (rx.find(line.c_str())) { errorLine = 0; cmCTestOptionalLog(this->CTest, DEBUG, " Not an error Line: " - << data << " (matches: " + << line << " (matches: " << this->CustomErrorExceptions[wrxCnt] << ")" << std::endl, this->Quiet); @@ -1127,11 +1122,11 @@ int cmCTestBuildHandler::ProcessSingleLine(const char* data) // Warnings int wrxCnt = 0; for (cmsys::RegularExpression& rx : this->WarningMatchRegex) { - if (rx.find(data)) { + if (rx.find(line.c_str())) { warningLine = 1; cmCTestOptionalLog(this->CTest, DEBUG, " Warning Line: " - << data << " (matches: " + << line << " (matches: " << this->CustomWarningMatches[wrxCnt] << ")" << std::endl, this->Quiet); @@ -1143,11 +1138,11 @@ int cmCTestBuildHandler::ProcessSingleLine(const char* data) wrxCnt = 0; // Warning exceptions for (cmsys::RegularExpression& rx : this->WarningExceptionRegex) { - if (rx.find(data)) { + if (rx.find(line.c_str())) { warningLine = 0; cmCTestOptionalLog(this->CTest, DEBUG, " Not a warning Line: " - << data << " (matches: " + << line << " (matches: " << this->CustomWarningExceptions[wrxCnt] << ")" << std::endl, this->Quiet); diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h index 722c590..87f1534 100644 --- a/Source/CTest/cmCTestBuildHandler.h +++ b/Source/CTest/cmCTestBuildHandler.h @@ -18,6 +18,7 @@ #include <vector> class cmMakefile; +class cmStringReplaceHelper; class cmXMLWriter; /** \class cmCTestBuildHandler @@ -143,6 +144,9 @@ private: int MaxErrors; int MaxWarnings; + // Used to remove ANSI color codes before checking for errors and warnings. + cmStringReplaceHelper* ColorRemover; + bool UseCTestLaunch; std::string CTestLaunchDir; class LaunchHelper; diff --git a/Source/CTest/cmCTestCVS.cxx b/Source/CTest/cmCTestCVS.cxx index 9c03839..560c169 100644 --- a/Source/CTest/cmCTestCVS.cxx +++ b/Source/CTest/cmCTestCVS.cxx @@ -4,8 +4,10 @@ #include "cmCTest.h" #include "cmProcessTools.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" +#include "cm_string_view.hxx" #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" @@ -204,8 +206,7 @@ std::string cmCTestCVS::ComputeBranchFlag(std::string const& dir) if (tagStream && cmSystemTools::GetLineFromStream(tagStream, tagLine) && tagLine.size() > 1 && tagLine[0] == 'T') { // Use the branch specified in the tag file. - std::string flag = "-r"; - flag += tagLine.substr(1); + std::string flag = cmStrCat("-r", cm::string_view(tagLine).substr(1)); return flag; } // Use the default branch. diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx index 74a932a..320c184 100644 --- a/Source/CTest/cmCTestConfigureCommand.cxx +++ b/Source/CTest/cmCTestConfigureCommand.cxx @@ -6,6 +6,7 @@ #include "cmCTestConfigureHandler.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" @@ -25,7 +26,7 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() std::vector<std::string> options; if (this->Values[ctc_OPTIONS]) { - cmSystemTools::ExpandListArgument(this->Values[ctc_OPTIONS], options); + cmExpandList(this->Values[ctc_OPTIONS], options); } if (this->CTest->GetCTestConfiguration("BuildDirectory").empty()) { @@ -75,9 +76,8 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() delete gg; } - std::string cmakeConfigureCommand = "\""; - cmakeConfigureCommand += cmSystemTools::GetCMakeCommand(); - cmakeConfigureCommand += "\""; + std::string cmakeConfigureCommand = + cmStrCat('"', cmSystemTools::GetCMakeCommand(), '"'); for (std::string const& option : options) { cmakeConfigureCommand += " \""; diff --git a/Source/CTest/cmCTestConfigureCommand.h b/Source/CTest/cmCTestConfigureCommand.h index 0cbcbfa..4677c83 100644 --- a/Source/CTest/cmCTestConfigureCommand.h +++ b/Source/CTest/cmCTestConfigureCommand.h @@ -6,11 +6,14 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmCTestHandlerCommand.h" +#include "cmCommand.h" #include <string> +#include <utility> + +#include "cm_memory.hxx" class cmCTestGenericHandler; -class cmCommand; /** \class cmCTestConfigure * \brief Run a ctest script @@ -25,12 +28,12 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmCTestConfigureCommand* ni = new cmCTestConfigureCommand; + auto ni = cm::make_unique<cmCTestConfigureCommand>(); ni->CTest = this->CTest; ni->CTestScriptHandler = this->CTestScriptHandler; - return ni; + return std::unique_ptr<cmCommand>(std::move(ni)); } /** diff --git a/Source/CTest/cmCTestCoverageCommand.h b/Source/CTest/cmCTestCoverageCommand.h index 1ae2d86..08f31f7 100644 --- a/Source/CTest/cmCTestCoverageCommand.h +++ b/Source/CTest/cmCTestCoverageCommand.h @@ -6,12 +6,15 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmCTestHandlerCommand.h" +#include "cmCommand.h" #include <set> #include <string> +#include <utility> + +#include "cm_memory.hxx" class cmCTestGenericHandler; -class cmCommand; /** \class cmCTestCoverage * \brief Run a ctest script @@ -26,12 +29,12 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmCTestCoverageCommand* ni = new cmCTestCoverageCommand; + auto ni = cm::make_unique<cmCTestCoverageCommand>(); ni->CTest = this->CTest; ni->CTestScriptHandler = this->CTestScriptHandler; - return ni; + return std::unique_ptr<cmCommand>(std::move(ni)); } /** diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index f6028c4..772fa47 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -13,6 +13,7 @@ #include "cmParseGTMCoverage.h" #include "cmParseJacocoCoverage.h" #include "cmParsePHPCoverage.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" #include "cmXMLWriter.h" @@ -129,10 +130,9 @@ void cmCTestCoverageHandler::Initialize() void cmCTestCoverageHandler::CleanCoverageLogFiles(std::ostream& log) { - std::string logGlob = this->CTest->GetCTestConfiguration("BuildDirectory"); - logGlob += "/Testing/"; - logGlob += this->CTest->GetCurrentTag(); - logGlob += "/CoverageLog*"; + std::string logGlob = + cmStrCat(this->CTest->GetCTestConfiguration("BuildDirectory"), "/Testing/", + this->CTest->GetCurrentTag(), "/CoverageLog*"); cmsys::Glob gl; gl.FindFiles(logGlob); std::vector<std::string> const& files = gl.GetFiles(); @@ -1181,7 +1181,7 @@ int cmCTestCoverageHandler::HandleGCovCoverage( // gcov 4.7 can have output lines saying "No executable lines" and // "Removing 'filename.gcov'"... Don't log those as "errors." if (line != "No executable lines" && - !cmSystemTools::StringStartsWith(line.c_str(), "Removing ")) { + !cmHasLiteralPrefix(line, "Removing ")) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output line: [" << line << "]" << std::endl); @@ -1455,8 +1455,7 @@ int cmCTestCoverageHandler::HandleLCovCoverage( std::vector<std::string> lcovFiles; dir = this->CTest->GetBinaryDir(); std::string daGlob; - daGlob = dir; - daGlob += "/*.LCOV"; + daGlob = cmStrCat(dir, "/*.LCOV"); cmCTestOptionalLog( this->CTest, HANDLER_VERBOSE_OUTPUT, " looking for LCOV files in: " << daGlob << std::endl, this->Quiet); @@ -1597,12 +1596,10 @@ void cmCTestCoverageHandler::FindGCovFiles(std::vector<std::string>& files) cmCTestOptionalLog( this->CTest, HANDLER_VERBOSE_OUTPUT, " globbing for coverage in: " << lm.first << std::endl, this->Quiet); - std::string daGlob = lm.first; - daGlob += "/*.da"; + std::string daGlob = cmStrCat(lm.first, "/*.da"); gl.FindFiles(daGlob); cmAppend(files, gl.GetFiles()); - daGlob = lm.first; - daGlob += "/*.gcda"; + daGlob = cmStrCat(lm.first, "/*.gcda"); gl.FindFiles(daGlob); cmAppend(files, gl.GetFiles()); } @@ -1631,8 +1628,7 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files) // DPI file should appear in build directory std::string daGlob; - daGlob = buildDir; - daGlob += "/*.dpi"; + daGlob = cmStrCat(buildDir, "/*.dpi"); cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " looking for dpi files in: " << daGlob << std::endl, this->Quiet); @@ -1945,10 +1941,9 @@ int cmCTestCoverageHandler::RunBullseyeCommand( cmCTestRunProcess runCoverageSrc; runCoverageSrc.SetCommand(program.c_str()); runCoverageSrc.AddArgument(arg); - std::string stdoutFile = cont->BinaryDir + "/Testing/Temporary/"; - stdoutFile += this->GetCTestInstance()->GetCurrentTag(); - stdoutFile += "-"; - stdoutFile += cmd; + std::string stdoutFile = + cmStrCat(cont->BinaryDir, "/Testing/Temporary/", + this->GetCTestInstance()->GetCurrentTag(), '-', cmd); std::string stderrFile = stdoutFile; stdoutFile += ".stdout"; stderrFile += ".stderr"; @@ -2037,9 +2032,7 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary( coveredFileNames.insert(file); if (!cmSystemTools::FileIsFullPath(sourceFile)) { // file will be relative to the binary dir - file = cont->BinaryDir; - file += "/"; - file += sourceFile; + file = cmStrCat(cont->BinaryDir, '/', sourceFile); } file = cmSystemTools::CollapseFullPath(file); bool shouldIDoCoverage = @@ -2221,9 +2214,8 @@ int cmCTestCoverageHandler::GetLabelId(std::string const& label) void cmCTestCoverageHandler::LoadLabels() { - std::string fileList = this->CTest->GetBinaryDir(); - fileList += "/CMakeFiles"; - fileList += "/TargetDirectories.txt"; + std::string fileList = + cmStrCat(this->CTest->GetBinaryDir(), "/CMakeFiles/TargetDirectories.txt"); cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, " target directory list [" << fileList << "]\n", this->Quiet); @@ -2237,8 +2229,7 @@ void cmCTestCoverageHandler::LoadLabels() void cmCTestCoverageHandler::LoadLabels(const char* dir) { LabelSet& dirLabels = this->TargetDirs[dir]; - std::string fname = dir; - fname += "/Labels.txt"; + std::string fname = cmStrCat(dir, "/Labels.txt"); cmsys::ifstream fin(fname.c_str()); if (!fin) { return; diff --git a/Source/CTest/cmCTestCurl.cxx b/Source/CTest/cmCTestCurl.cxx index cc63e45..40f5918 100644 --- a/Source/CTest/cmCTestCurl.cxx +++ b/Source/CTest/cmCTestCurl.cxx @@ -5,6 +5,7 @@ #include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCurl.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include <ostream> @@ -127,9 +128,7 @@ bool cmCTestCurl::UploadFile(std::string const& local_file, return false; } // set the url - std::string upload_url = url; - upload_url += "?"; - upload_url += fields; + std::string upload_url = cmStrCat(url, '?', fields); ::curl_easy_setopt(this->Curl, CURLOPT_URL, upload_url.c_str()); // now specify which file to upload ::curl_easy_setopt(this->Curl, CURLOPT_INFILE, ftpfile); diff --git a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h index 9425ece..84250cb 100644 --- a/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h +++ b/Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h @@ -6,11 +6,14 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmCTestCommand.h" +#include "cmCommand.h" #include <string> +#include <utility> #include <vector> -class cmCommand; +#include "cm_memory.hxx" + class cmExecutionStatus; /** \class cmCTestEmptyBinaryDirectory @@ -27,13 +30,12 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmCTestEmptyBinaryDirectoryCommand* ni = - new cmCTestEmptyBinaryDirectoryCommand; + auto ni = cm::make_unique<cmCTestEmptyBinaryDirectoryCommand>(); ni->CTest = this->CTest; ni->CTestScriptHandler = this->CTestScriptHandler; - return ni; + return std::unique_ptr<cmCommand>(std::move(ni)); } /** diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index 9d9761c..f7319ef 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -10,11 +10,11 @@ #include <time.h> #include <vector> -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestVC.h" #include "cmProcessOutput.h" #include "cmProcessTools.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" static unsigned int cmCTestGITVersion(unsigned int epic, unsigned int major, @@ -111,8 +111,8 @@ std::string cmCTestGIT::FindGitDir() else if (git_dir[0] == '/') { // Cygwin Git reports a full path that Cygwin understands, but we // are a Windows application. Run "cygpath" to get Windows path. - std::string cygpath_exe = cmSystemTools::GetFilenamePath(git); - cygpath_exe += "/cygpath.exe"; + std::string cygpath_exe = + cmStrCat(cmSystemTools::GetFilenamePath(git), "/cygpath.exe"); if (cmSystemTools::FileExists(cygpath_exe)) { char const* cygpath[] = { cygpath_exe.c_str(), "-w", git_dir.c_str(), 0 }; @@ -211,8 +211,7 @@ bool cmCTestGIT::UpdateByFetchAndReset() bool cmCTestGIT::UpdateByCustom(std::string const& custom) { - std::vector<std::string> git_custom_command; - cmSystemTools::ExpandListArgument(custom, git_custom_command, true); + std::vector<std::string> git_custom_command = cmExpandedList(custom, true); std::vector<char const*> git_custom; git_custom.reserve(git_custom_command.size() + 1); for (std::string const& i : git_custom_command) { @@ -270,7 +269,7 @@ bool cmCTestGIT::UpdateImpl() std::string init_submodules = this->CTest->GetCTestConfiguration("GITInitSubmodules"); - if (cmSystemTools::IsOn(init_submodules)) { + if (cmIsOn(init_submodules)) { char const* git_submodule_init[] = { git, "submodule", "init", nullptr }; ret = this->RunChild(git_submodule_init, &submodule_out, &submodule_err, top_dir.c_str()); diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index adf9553..6add717 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -4,6 +4,7 @@ #include "cmCTest.h" #include "cmCTestGenericHandler.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmSystemTools.h" @@ -13,8 +14,6 @@ #include <sstream> #include <stdlib.h> -class cmExecutionStatus; - cmCTestHandlerCommand::cmCTestHandlerCommand() { const size_t INIT_SIZE = 100; @@ -86,7 +85,7 @@ private: } bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& /*unused*/) + cmExecutionStatus& status) { // save error state and restore it if needed SaveRestoreErrorState errorState; @@ -113,20 +112,20 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, foundBadArgument = true; } } - bool capureCMakeError = (this->Values[ct_CAPTURE_CMAKE_ERROR] && - *this->Values[ct_CAPTURE_CMAKE_ERROR]); + bool captureCMakeError = (this->Values[ct_CAPTURE_CMAKE_ERROR] && + *this->Values[ct_CAPTURE_CMAKE_ERROR]); // now that arguments are parsed check to see if there is a // CAPTURE_CMAKE_ERROR specified let the errorState object know. - if (capureCMakeError) { + if (captureCMakeError) { errorState.CaptureCMakeError(); } // if we found a bad argument then exit before running command if (foundBadArgument) { // store the cmake error - if (capureCMakeError) { + if (captureCMakeError) { this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], "-1"); - std::string const err = this->GetName() + " " + this->GetError(); + std::string const err = this->GetName() + " " + status.GetError(); if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) { cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n"); } @@ -192,11 +191,11 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot instantiate test handler " << this->GetName() << std::endl); - if (capureCMakeError) { + if (captureCMakeError) { this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], "-1"); - const char* err = this->GetError(); - if (err && !cmSystemTools::FindLastString(err, "unknown error.")) { + std::string const& err = status.GetError(); + if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) { cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n"); } return true; @@ -216,11 +215,11 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, this->SetError("failed to change directory to " + this->CTest->GetCTestConfiguration("BuildDirectory") + " : " + std::strerror(workdir.GetLastResult())); - if (capureCMakeError) { + if (captureCMakeError) { this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], "-1"); cmCTestLog(this->CTest, ERROR_MESSAGE, - this->GetName() << " " << this->GetError() << "\n"); + this->GetName() << " " << status.GetError() << "\n"); // return success because failure is recorded in CAPTURE_CMAKE_ERROR return true; } @@ -229,21 +228,19 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, int res = handler->ProcessHandler(); if (this->Values[ct_RETURN_VALUE] && *this->Values[ct_RETURN_VALUE]) { - std::ostringstream str; - str << res; this->Makefile->AddDefinition(this->Values[ct_RETURN_VALUE], - str.str().c_str()); + std::to_string(res)); } this->ProcessAdditionalValues(handler); // log the error message if there was an error - if (capureCMakeError) { + if (captureCMakeError) { const char* returnString = "0"; if (cmSystemTools::GetErrorOccuredFlag()) { returnString = "-1"; - const char* err = this->GetError(); + std::string const& err = status.GetError(); // print out the error if it is not "unknown error" which means // there was no message - if (err && !cmSystemTools::FindLastString(err, "unknown error.")) { + if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) { cmCTestLog(this->CTest, ERROR_MESSAGE, err); } } diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx index a96513e..ac52581 100644 --- a/Source/CTest/cmCTestLaunch.cxx +++ b/Source/CTest/cmCTestLaunch.cxx @@ -6,7 +6,6 @@ #include "cmsys/Process.h" #include "cmsys/RegularExpression.hxx" #include <iostream> -#include <memory> // IWYU pragma: keep #include <stdlib.h> #include <string.h> @@ -17,6 +16,7 @@ #include "cmProcessOutput.h" #include "cmState.h" #include "cmStateSnapshot.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" #include "cmake.h" @@ -176,14 +176,8 @@ void cmCTestLaunch::ComputeFileNames() this->LogHash = md5.FinalizeHex(); // We store stdout and stderr in temporary log files. - this->LogOut = this->LogDir; - this->LogOut += "launch-"; - this->LogOut += this->LogHash; - this->LogOut += "-out.txt"; - this->LogErr = this->LogDir; - this->LogErr += "launch-"; - this->LogErr += this->LogHash; - this->LogErr += "-err.txt"; + this->LogOut = cmStrCat(this->LogDir, "launch-", this->LogHash, "-out.txt"); + this->LogErr = cmStrCat(this->LogDir, "launch-", this->LogHash, "-err.txt"); } void cmCTestLaunch::RunChild() @@ -282,11 +276,8 @@ void cmCTestLaunch::LoadLabels() } // Labels are listed in per-target files. - std::string fname = this->OptionBuildDir; - fname += "/CMakeFiles"; - fname += "/"; - fname += this->OptionTargetName; - fname += ".dir/Labels.txt"; + std::string fname = cmStrCat(this->OptionBuildDir, "/CMakeFiles/", + this->OptionTargetName, ".dir/Labels.txt"); // We are interested in per-target labels for this source file. std::string source = this->OptionSource; @@ -340,10 +331,9 @@ bool cmCTestLaunch::IsError() const void cmCTestLaunch::WriteXML() { // Name the xml file. - std::string logXML = this->LogDir; - logXML += this->IsError() ? "error-" : "warning-"; - logXML += this->LogHash; - logXML += ".xml"; + std::string logXML = + cmStrCat(this->LogDir, this->IsError() ? "error-" : "warning-", + this->LogHash, ".xml"); // Use cmGeneratedFileStream to atomically create the report file. cmGeneratedFileStream fxml(logXML); @@ -494,9 +484,9 @@ void cmCTestLaunch::DumpFileToXML(cmXMLElement& e3, const char* tag, continue; } if (this->Match(line, this->RegexWarningSuppress)) { - line = "[CTest: warning suppressed] " + line; + line = cmStrCat("[CTest: warning suppressed] ", line); } else if (this->Match(line, this->RegexWarning)) { - line = "[CTest: warning matched] " + line; + line = cmStrCat("[CTest: warning matched] ", line); } e4.Content(sep); e4.Content(line); @@ -546,10 +536,7 @@ void cmCTestLaunch::LoadScrapeRules() void cmCTestLaunch::LoadScrapeRules( const char* purpose, std::vector<cmsys::RegularExpression>& regexps) { - std::string fname = this->LogDir; - fname += "Custom"; - fname += purpose; - fname += ".txt"; + std::string fname = cmStrCat(this->LogDir, "Custom", purpose, ".txt"); cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary); std::string line; cmsys::RegularExpression rex; @@ -595,7 +582,7 @@ bool cmCTestLaunch::Match(std::string const& line, bool cmCTestLaunch::MatchesFilterPrefix(std::string const& line) const { return !this->OptionFilterPrefix.empty() && - cmSystemTools::StringStartsWith(line, this->OptionFilterPrefix.c_str()); + cmHasPrefix(line, this->OptionFilterPrefix); } int cmCTestLaunch::Main(int argc, const char* const argv[]) @@ -617,8 +604,7 @@ void cmCTestLaunch::LoadConfig() cm.GetCurrentSnapshot().SetDefaultDefinitions(); cmGlobalGenerator gg(&cm); cmMakefile mf(&gg, cm.GetCurrentSnapshot()); - std::string fname = this->LogDir; - fname += "CTestLaunchConfig.cmake"; + std::string fname = cmStrCat(this->LogDir, "CTestLaunchConfig.cmake"); if (cmSystemTools::FileExists(fname) && mf.ReadListFile(fname)) { this->SourceDir = mf.GetSafeDefinition("CTEST_SOURCE_DIRECTORY"); cmSystemTools::ConvertToUnixSlashes(this->SourceDir); diff --git a/Source/CTest/cmCTestMemCheckCommand.cxx b/Source/CTest/cmCTestMemCheckCommand.cxx index 7dad1ce..804efa5 100644 --- a/Source/CTest/cmCTestMemCheckCommand.cxx +++ b/Source/CTest/cmCTestMemCheckCommand.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestMemCheckCommand.h" -#include <sstream> #include <string> #include <vector> @@ -45,9 +44,9 @@ void cmCTestMemCheckCommand::ProcessAdditionalValues( cmCTestGenericHandler* handler) { if (this->Values[ctm_DEFECT_COUNT] && *this->Values[ctm_DEFECT_COUNT]) { - std::ostringstream str; - str << static_cast<cmCTestMemCheckHandler*>(handler)->GetDefectCount(); - this->Makefile->AddDefinition(this->Values[ctm_DEFECT_COUNT], - str.str().c_str()); + this->Makefile->AddDefinition( + this->Values[ctm_DEFECT_COUNT], + std::to_string( + static_cast<cmCTestMemCheckHandler*>(handler)->GetDefectCount())); } } diff --git a/Source/CTest/cmCTestMemCheckCommand.h b/Source/CTest/cmCTestMemCheckCommand.h index b6b3c40..837a687 100644 --- a/Source/CTest/cmCTestMemCheckCommand.h +++ b/Source/CTest/cmCTestMemCheckCommand.h @@ -5,10 +5,14 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <utility> + +#include "cm_memory.hxx" + #include "cmCTestTestCommand.h" +#include "cmCommand.h" class cmCTestGenericHandler; -class cmCommand; /** \class cmCTestMemCheck * \brief Run a ctest script @@ -23,12 +27,12 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmCTestMemCheckCommand* ni = new cmCTestMemCheckCommand; + auto ni = cm::make_unique<cmCTestMemCheckCommand>(); ni->CTest = this->CTest; ni->CTestScriptHandler = this->CTestScriptHandler; - return ni; + return std::unique_ptr<cmCommand>(std::move(ni)); } protected: diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index b09e7bb..259240f 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -1074,10 +1074,7 @@ void cmCTestMemCheckHandler::AppendMemTesterOutput(cmCTestTestResult& res, void cmCTestMemCheckHandler::TestOutputFileNames( int test, std::vector<std::string>& files) { - std::string index; - std::ostringstream stream; - stream << test; - index = stream.str(); + std::string index = std::to_string(test); std::string ofile = this->MemoryTesterOutputFile; std::string::size_type pos = ofile.find("??"); ofile.replace(pos, 2, index); diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index ef63073..af1980a 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -10,6 +10,7 @@ #include "cmDuration.h" #include "cmListFileCache.h" #include "cmRange.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" @@ -29,11 +30,13 @@ #include <iostream> #include <list> #include <math.h> +#include <memory> #include <sstream> #include <stack> #include <stdlib.h> #include <unordered_map> #include <utility> +#include <vector> namespace cmsys { class RegularExpression; @@ -108,8 +111,7 @@ void cmCTestMultiProcessHandler::SetTestLoad(unsigned long load) std::string fake_load_value; if (cmSystemTools::GetEnv("__CTEST_FAKE_LOAD_AVERAGE_FOR_TESTING", fake_load_value)) { - if (!cmSystemTools::StringToULong(fake_load_value.c_str(), - &this->FakeLoadForTesting)) { + if (!cmStrToULong(fake_load_value, &this->FakeLoadForTesting)) { cmSystemTools::Error("Failed to parse fake load value: " + fake_load_value); } @@ -171,8 +173,7 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) // Find any failed dependencies for this test. We assume the more common // scenario has no failed tests, so make it the outer loop. for (std::string const& f : *this->Failed) { - if (this->Properties[test]->RequireSuccessDepends.find(f) != - this->Properties[test]->RequireSuccessDepends.end()) { + if (cmContains(this->Properties[test]->RequireSuccessDepends, f)) { testRun->AddFailedDependency(f); } } @@ -188,10 +189,13 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) std::strerror(workdir.GetLastResult())); } else { if (testRun->StartTest(this->Completed, this->Total)) { + // Ownership of 'testRun' has moved to another structure. + // When the test finishes, FinishTestProcess will be called. return true; } } + // Pass ownership of 'testRun'. this->FinishTestProcess(testRun, false); return false; } @@ -273,7 +277,7 @@ bool cmCTestMultiProcessHandler::StartTest(int test) { // Check for locked resources for (std::string const& i : this->Properties[test]->LockedResources) { - if (this->LockedResources.find(i) != this->LockedResources.end()) { + if (cmContains(this->LockedResources, i)) { return false; } } @@ -619,9 +623,7 @@ void cmCTestMultiProcessHandler::CreateParallelTestCostList() // In parallel test runs add previously failed tests to the front // of the cost list and queue other tests for further sorting for (auto const& t : this->Tests) { - if (std::find(this->LastTestsFailed.begin(), this->LastTestsFailed.end(), - this->Properties[t.first]->Name) != - this->LastTestsFailed.end()) { + if (cmContains(this->LastTestsFailed, this->Properties[t.first]->Name)) { // If the test failed last time, it should be run first. this->SortedTests.push_back(t.first); alreadySortedTests.insert(t.first); @@ -660,7 +662,7 @@ void cmCTestMultiProcessHandler::CreateParallelTestCostList() TestComparator(this)); for (auto const& j : sortedCopy) { - if (alreadySortedTests.find(j) == alreadySortedTests.end()) { + if (!cmContains(alreadySortedTests, j)) { this->SortedTests.push_back(j); alreadySortedTests.insert(j); } @@ -692,7 +694,7 @@ void cmCTestMultiProcessHandler::CreateSerialTestCostList() TestSet alreadySortedTests; for (int test : presortedList) { - if (alreadySortedTests.find(test) != alreadySortedTests.end()) { + if (cmContains(alreadySortedTests, test)) { continue; } @@ -700,8 +702,7 @@ void cmCTestMultiProcessHandler::CreateSerialTestCostList() GetAllTestDependencies(test, dependencies); for (int testDependency : dependencies) { - if (alreadySortedTests.find(testDependency) == - alreadySortedTests.end()) { + if (!cmContains(alreadySortedTests, testDependency)) { alreadySortedTests.insert(testDependency); this->SortedTests.push_back(testDependency); } @@ -821,6 +822,11 @@ static Json::Value DumpCTestProperties( "FAIL_REGULAR_EXPRESSION", DumpRegExToJsonArray(testProperties.ErrorRegularExpressions))); } + if (!testProperties.SkipRegularExpressions.empty()) { + properties.append(DumpCTestProperty( + "SKIP_REGULAR_EXPRESSION", + DumpRegExToJsonArray(testProperties.SkipRegularExpressions))); + } if (!testProperties.FixturesCleanup.empty()) { properties.append(DumpCTestProperty( "FIXTURES_CLEANUP", DumpToJsonArray(testProperties.FixturesCleanup))); @@ -855,8 +861,8 @@ static Json::Value DumpCTestProperties( DumpCTestProperty("PROCESSORS", testProperties.Processors)); } if (!testProperties.RequiredFiles.empty()) { - properties["REQUIRED_FILES"] = - DumpToJsonArray(testProperties.RequiredFiles); + properties.append(DumpCTestProperty( + "REQUIRED_FILES", DumpToJsonArray(testProperties.RequiredFiles))); } if (!testProperties.LockedResources.empty()) { properties.append(DumpCTestProperty( diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx index 2eb8dba..64354e8 100644 --- a/Source/CTest/cmCTestP4.cxx +++ b/Source/CTest/cmCTestP4.cxx @@ -7,6 +7,7 @@ #include "cmCTestVC.h" #include "cmProcessTools.h" #include "cmRange.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmsys/RegularExpression.hxx" @@ -459,8 +460,7 @@ bool cmCTestP4::LoadModifications() bool cmCTestP4::UpdateCustom(const std::string& custom) { - std::vector<std::string> p4_custom_command; - cmSystemTools::ExpandListArgument(custom, p4_custom_command, true); + std::vector<std::string> p4_custom_command = cmExpandedList(custom, true); std::vector<char const*> p4_custom; p4_custom.reserve(p4_custom_command.size() + 1); diff --git a/Source/CTest/cmCTestReadCustomFilesCommand.h b/Source/CTest/cmCTestReadCustomFilesCommand.h index ba25c51..db2ac5e 100644 --- a/Source/CTest/cmCTestReadCustomFilesCommand.h +++ b/Source/CTest/cmCTestReadCustomFilesCommand.h @@ -6,11 +6,14 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmCTestCommand.h" +#include "cmCommand.h" #include <string> +#include <utility> #include <vector> -class cmCommand; +#include "cm_memory.hxx" + class cmExecutionStatus; /** \class cmCTestReadCustomFiles @@ -27,11 +30,11 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmCTestReadCustomFilesCommand* ni = new cmCTestReadCustomFilesCommand; + auto ni = cm::make_unique<cmCTestReadCustomFilesCommand>(); ni->CTest = this->CTest; - return ni; + return std::unique_ptr<cmCommand>(std::move(ni)); } /** diff --git a/Source/CTest/cmCTestRunScriptCommand.cxx b/Source/CTest/cmCTestRunScriptCommand.cxx index a7e47d3..f59ca57 100644 --- a/Source/CTest/cmCTestRunScriptCommand.cxx +++ b/Source/CTest/cmCTestRunScriptCommand.cxx @@ -5,8 +5,6 @@ #include "cmCTestScriptHandler.h" #include "cmMakefile.h" -#include <sstream> - class cmExecutionStatus; bool cmCTestRunScriptCommand::InitialPass(std::vector<std::string> const& args, @@ -41,9 +39,7 @@ bool cmCTestRunScriptCommand::InitialPass(std::vector<std::string> const& args, int ret; cmCTestScriptHandler::RunScript(this->CTest, this->Makefile, args[i].c_str(), !np, &ret); - std::ostringstream str; - str << ret; - this->Makefile->AddDefinition(returnVariable, str.str().c_str()); + this->Makefile->AddDefinition(returnVariable, std::to_string(ret)); } } return true; diff --git a/Source/CTest/cmCTestRunScriptCommand.h b/Source/CTest/cmCTestRunScriptCommand.h index 9d8b4b5..6961f6e 100644 --- a/Source/CTest/cmCTestRunScriptCommand.h +++ b/Source/CTest/cmCTestRunScriptCommand.h @@ -6,11 +6,14 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmCTestCommand.h" +#include "cmCommand.h" #include <string> +#include <utility> #include <vector> -class cmCommand; +#include "cm_memory.hxx" + class cmExecutionStatus; /** \class cmCTestRunScript @@ -27,12 +30,12 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmCTestRunScriptCommand* ni = new cmCTestRunScriptCommand; + auto ni = cm::make_unique<cmCTestRunScriptCommand>(); ni->CTest = this->CTest; ni->CTestScriptHandler = this->CTestScriptHandler; - return ni; + return std::unique_ptr<cmCommand>(std::move(ni)); } /** diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 31976b9..23c6b0d 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -6,12 +6,12 @@ #include "cmCTestMemCheckHandler.h" #include "cmCTestMultiProcessHandler.h" #include "cmProcess.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" #include "cmsys/RegularExpression.hxx" #include <chrono> -#include <cmAlgorithms.h> #include <cstdint> #include <cstring> #include <iomanip> @@ -20,6 +20,8 @@ #include <stdio.h> #include <utility> +#include "cm_memory.hxx" + cmCTestRunTest::cmCTestRunTest(cmCTestMultiProcessHandler& multiHandler) : MultiTestHandler(multiHandler) { @@ -76,6 +78,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) } std::int64_t retVal = this->TestProcess->GetExitValue(); bool forceFail = false; + bool forceSkip = false; bool skipped = false; bool outputTestErrorsToConsole = false; if (!this->TestProperties->RequiredRegularExpressions.empty() && @@ -84,49 +87,62 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) for (auto& pass : this->TestProperties->RequiredRegularExpressions) { if (pass.first.find(this->ProcessOutput)) { found = true; - reason = "Required regular expression found."; + reason = cmStrCat("Required regular expression found. Regex=[", + pass.second, ']'); break; } } if (!found) { - reason = "Required regular expression not found."; + reason = "Required regular expression not found. Regex=["; + for (auto& pass : this->TestProperties->RequiredRegularExpressions) { + reason += pass.second; + reason += "\n"; + } + reason += "]"; forceFail = true; } - reason += "Regex=["; - for (auto& pass : this->TestProperties->RequiredRegularExpressions) { - reason += pass.second; - reason += "\n"; - } - reason += "]"; } if (!this->TestProperties->ErrorRegularExpressions.empty() && this->FailedDependencies.empty()) { - for (auto& pass : this->TestProperties->ErrorRegularExpressions) { - if (pass.first.find(this->ProcessOutput)) { - reason = "Error regular expression found in output."; - reason += " Regex=["; - reason += pass.second; - reason += "]"; + for (auto& fail : this->TestProperties->ErrorRegularExpressions) { + if (fail.first.find(this->ProcessOutput)) { + reason = cmStrCat("Error regular expression found in output. Regex=[", + fail.second, ']'); forceFail = true; break; } } } + if (!this->TestProperties->SkipRegularExpressions.empty() && + this->FailedDependencies.empty()) { + for (auto& skip : this->TestProperties->SkipRegularExpressions) { + if (skip.first.find(this->ProcessOutput)) { + reason = cmStrCat("Skip regular expression found in output. Regex=[", + skip.second, ']'); + forceSkip = true; + break; + } + } + } std::ostringstream outputStream; if (res == cmProcess::State::Exited) { bool success = !forceFail && (retVal == 0 || !this->TestProperties->RequiredRegularExpressions.empty()); - if (this->TestProperties->SkipReturnCode >= 0 && - this->TestProperties->SkipReturnCode == retVal) { + if ((this->TestProperties->SkipReturnCode >= 0 && + this->TestProperties->SkipReturnCode == retVal) || + forceSkip) { this->TestResult.Status = cmCTestTestHandler::NOT_RUN; std::ostringstream s; - s << "SKIP_RETURN_CODE=" << this->TestProperties->SkipReturnCode; + if (forceSkip) { + s << "SKIP_REGULAR_EXPRESSION_MATCHED"; + } else { + s << "SKIP_RETURN_CODE=" << this->TestProperties->SkipReturnCode; + } this->TestResult.CompletionStatus = s.str(); cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Skipped "); skipped = true; - } else if ((success && !this->TestProperties->WillFail) || - (!success && this->TestProperties->WillFail)) { + } else if (success != this->TestProperties->WillFail) { this->TestResult.Status = cmCTestTestHandler::COMPLETED; outputStream << " Passed "; } else { @@ -481,12 +497,11 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) this->TestProcess = cm::make_unique<cmProcess>(*this); std::string msg; if (this->CTest->GetConfigType().empty()) { - msg = "Test not available without configuration."; - msg += " (Missing \"-C <config>\"?)"; + msg = "Test not available without configuration. (Missing \"-C " + "<config>\"?)"; } else { - msg = "Test not available in configuration \""; - msg += this->CTest->GetConfigType(); - msg += "\"."; + msg = cmStrCat("Test not available in configuration \"", + this->CTest->GetConfigType(), "\"."); } *this->TestHandler->LogFile << msg << std::endl; cmCTestLog(this->CTest, ERROR_MESSAGE, msg << std::endl); @@ -666,7 +681,7 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout, this->TestProcess->SetTimeout(timeout); -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP cmSystemTools::SaveRestoreEnvironment sre; #endif diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index 38cc417..43dfe8e 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <memory> #include <set> #include <stddef.h> #include <string> @@ -12,7 +13,7 @@ #include "cmCTestTestHandler.h" #include "cmDuration.h" -#include "cmProcess.h" // IWYU pragma: keep (for unique_ptr) +#include "cmProcess.h" class cmCTest; class cmCTestMultiProcessHandler; diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx index c834686..dc1472b 100644 --- a/Source/CTest/cmCTestSVN.cxx +++ b/Source/CTest/cmCTestSVN.cxx @@ -6,6 +6,7 @@ #include "cmCTest.h" #include "cmCTestVC.h" #include "cmProcessTools.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLParser.h" #include "cmXMLWriter.h" @@ -143,9 +144,8 @@ bool cmCTestSVN::NoteNewRevision() // the repository root. if (!svninfo.Root.empty() && cmCTestSVNPathStarts(svninfo.URL, svninfo.Root)) { - svninfo.Base = - cmCTest::DecodeURL(svninfo.URL.substr(svninfo.Root.size())); - svninfo.Base += "/"; + svninfo.Base = cmStrCat( + cmCTest::DecodeURL(svninfo.URL.substr(svninfo.Root.size())), '/'); } this->Log << "Repository '" << svninfo.LocalPath << "' Base = " << svninfo.Base << "\n"; diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index a739f44..81966dd 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -4,13 +4,8 @@ #include "cmsys/Directory.hxx" #include "cmsys/Process.h" -#include <map> -#include <ratio> -#include <sstream> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <utility> + +#include "cm_memory.hxx" #include "cmCTest.h" #include "cmCTestBuildCommand.h" @@ -27,49 +22,35 @@ #include "cmCTestTestCommand.h" #include "cmCTestUpdateCommand.h" #include "cmCTestUploadCommand.h" +#include "cmCommand.h" #include "cmDuration.h" -#include "cmFunctionBlocker.h" #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" +#include <map> +#include <memory> +#include <ratio> +#include <sstream> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <utility> + #ifdef _WIN32 # include <windows.h> #else # include <unistd.h> #endif -class cmExecutionStatus; -struct cmListFileFunction; - #define CTEST_INITIAL_CMAKE_OUTPUT_FILE_NAME "CTestInitialCMakeOutput.log" -// used to keep elapsed time up to date -class cmCTestScriptFunctionBlocker : public cmFunctionBlocker -{ -public: - bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf, - cmExecutionStatus& /*status*/) override; - // virtual bool ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf); - // virtual void ScopeEnded(cmMakefile &mf); - - cmCTestScriptHandler* CTestScriptHandler; -}; - -// simply update the time and don't block anything -bool cmCTestScriptFunctionBlocker::IsFunctionBlocked( - const cmListFileFunction& /*lff*/, cmMakefile& /*mf*/, - cmExecutionStatus& /*status*/) -{ - this->CTestScriptHandler->UpdateElapsedTime(); - return false; -} - cmCTestScriptHandler::cmCTestScriptHandler() { this->Backup = false; @@ -163,16 +144,16 @@ void cmCTestScriptHandler::UpdateElapsedTime() auto itime = cmDurationTo<unsigned int>(std::chrono::steady_clock::now() - this->ScriptStartTime); auto timeString = std::to_string(itime); - this->Makefile->AddDefinition("CTEST_ELAPSED_TIME", timeString.c_str()); + this->Makefile->AddDefinition("CTEST_ELAPSED_TIME", timeString); } } -void cmCTestScriptHandler::AddCTestCommand(std::string const& name, - cmCTestCommand* command) +void cmCTestScriptHandler::AddCTestCommand( + std::string const& name, std::unique_ptr<cmCTestCommand> command) { command->CTest = this->CTest; command->CTestScriptHandler = this; - this->CMake->GetState()->AddBuiltinCommand(name, command); + this->CMake->GetState()->AddBuiltinCommand(name, std::move(command)); } int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg) @@ -295,21 +276,28 @@ void cmCTestScriptHandler::CreateCMake() } }); - this->AddCTestCommand("ctest_build", new cmCTestBuildCommand); - this->AddCTestCommand("ctest_configure", new cmCTestConfigureCommand); - this->AddCTestCommand("ctest_coverage", new cmCTestCoverageCommand); + this->AddCTestCommand("ctest_build", cm::make_unique<cmCTestBuildCommand>()); + this->AddCTestCommand("ctest_configure", + cm::make_unique<cmCTestConfigureCommand>()); + this->AddCTestCommand("ctest_coverage", + cm::make_unique<cmCTestCoverageCommand>()); this->AddCTestCommand("ctest_empty_binary_directory", - new cmCTestEmptyBinaryDirectoryCommand); - this->AddCTestCommand("ctest_memcheck", new cmCTestMemCheckCommand); + cm::make_unique<cmCTestEmptyBinaryDirectoryCommand>()); + this->AddCTestCommand("ctest_memcheck", + cm::make_unique<cmCTestMemCheckCommand>()); this->AddCTestCommand("ctest_read_custom_files", - new cmCTestReadCustomFilesCommand); - this->AddCTestCommand("ctest_run_script", new cmCTestRunScriptCommand); - this->AddCTestCommand("ctest_sleep", new cmCTestSleepCommand); - this->AddCTestCommand("ctest_start", new cmCTestStartCommand); - this->AddCTestCommand("ctest_submit", new cmCTestSubmitCommand); - this->AddCTestCommand("ctest_test", new cmCTestTestCommand); - this->AddCTestCommand("ctest_update", new cmCTestUpdateCommand); - this->AddCTestCommand("ctest_upload", new cmCTestUploadCommand); + cm::make_unique<cmCTestReadCustomFilesCommand>()); + this->AddCTestCommand("ctest_run_script", + cm::make_unique<cmCTestRunScriptCommand>()); + this->AddCTestCommand("ctest_sleep", cm::make_unique<cmCTestSleepCommand>()); + this->AddCTestCommand("ctest_start", cm::make_unique<cmCTestStartCommand>()); + this->AddCTestCommand("ctest_submit", + cm::make_unique<cmCTestSubmitCommand>()); + this->AddCTestCommand("ctest_test", cm::make_unique<cmCTestTestCommand>()); + this->AddCTestCommand("ctest_update", + cm::make_unique<cmCTestUpdateCommand>()); + this->AddCTestCommand("ctest_upload", + cm::make_unique<cmCTestUploadCommand>()); } // this sets up some variables for the script to use, creates the required @@ -340,31 +328,29 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg) this->CreateCMake(); // set a variable with the path to the current script - this->Makefile->AddDefinition( - "CTEST_SCRIPT_DIRECTORY", cmSystemTools::GetFilenamePath(script).c_str()); - this->Makefile->AddDefinition( - "CTEST_SCRIPT_NAME", cmSystemTools::GetFilenameName(script).c_str()); + this->Makefile->AddDefinition("CTEST_SCRIPT_DIRECTORY", + cmSystemTools::GetFilenamePath(script)); + this->Makefile->AddDefinition("CTEST_SCRIPT_NAME", + cmSystemTools::GetFilenameName(script)); this->Makefile->AddDefinition("CTEST_EXECUTABLE_NAME", - cmSystemTools::GetCTestCommand().c_str()); + cmSystemTools::GetCTestCommand()); this->Makefile->AddDefinition("CMAKE_EXECUTABLE_NAME", - cmSystemTools::GetCMakeCommand().c_str()); - this->Makefile->AddDefinition("CTEST_RUN_CURRENT_SCRIPT", true); + cmSystemTools::GetCMakeCommand()); + this->Makefile->AddDefinitionBool("CTEST_RUN_CURRENT_SCRIPT", true); this->SetRunCurrentScript(true); this->UpdateElapsedTime(); // add the script arg if defined if (!script_arg.empty()) { - this->Makefile->AddDefinition("CTEST_SCRIPT_ARG", script_arg.c_str()); + this->Makefile->AddDefinition("CTEST_SCRIPT_ARG", script_arg); } #if defined(__CYGWIN__) this->Makefile->AddDefinition("CMAKE_LEGACY_CYGWIN_WIN32", "0"); #endif - // always add a function blocker to update the elapsed time - cmCTestScriptFunctionBlocker* f = new cmCTestScriptFunctionBlocker(); - f->CTestScriptHandler = this; - this->Makefile->AddFunctionBlocker(f); + // set a callback function to update the elapsed time + this->Makefile->OnExecuteCommand([this] { this->UpdateElapsedTime(); }); /* Execute CTestScriptMode.cmake, which loads CMakeDetermineSystem and CMakeSystemSpecificInformation, so @@ -384,7 +370,7 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg) const std::map<std::string, std::string>& defs = this->CTest->GetDefinitions(); for (auto const& d : defs) { - this->Makefile->AddDefinition(d.first, d.second.c_str()); + this->Makefile->AddDefinition(d.first, d.second); } // finally read in the script @@ -465,12 +451,13 @@ int cmCTestScriptHandler::ExtractVariables() // make sure the required info is here if (this->SourceDir.empty() || this->BinaryDir.empty() || this->CTestCmd.empty()) { - std::string msg = "CTEST_SOURCE_DIRECTORY = "; - msg += (!this->SourceDir.empty()) ? this->SourceDir.c_str() : "(Null)"; - msg += "\nCTEST_BINARY_DIRECTORY = "; - msg += (!this->BinaryDir.empty()) ? this->BinaryDir.c_str() : "(Null)"; - msg += "\nCTEST_COMMAND = "; - msg += (!this->CTestCmd.empty()) ? this->CTestCmd.c_str() : "(Null)"; + std::string msg = + cmStrCat("CTEST_SOURCE_DIRECTORY = ", + (!this->SourceDir.empty()) ? this->SourceDir.c_str() : "(Null)", + "\nCTEST_BINARY_DIRECTORY = ", + (!this->BinaryDir.empty()) ? this->BinaryDir.c_str() : "(Null)", + "\nCTEST_COMMAND = ", + (!this->CTestCmd.empty()) ? this->CTestCmd.c_str() : "(Null)"); cmSystemTools::Error( "Some required settings in the configuration file were missing:\n" + msg); @@ -509,7 +496,7 @@ void cmCTestScriptHandler::SleepInSeconds(unsigned int secondsToWait) int cmCTestScriptHandler::RunConfigurationScript( const std::string& total_script_arg, bool pscope) { -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP cmSystemTools::SaveRestoreEnvironment sre; #endif @@ -557,8 +544,7 @@ int cmCTestScriptHandler::RunCurrentScript() // set any environment variables if (!this->CTestEnv.empty()) { - std::vector<std::string> envArgs; - cmSystemTools::ExpandListArgument(this->CTestEnv, envArgs); + std::vector<std::string> envArgs = cmExpandedList(this->CTestEnv); cmSystemTools::AppendEnv(envArgs); } @@ -624,10 +610,8 @@ int cmCTestScriptHandler::BackupDirectories() int retVal; // compute the backup names - this->BackupSourceDir = this->SourceDir; - this->BackupSourceDir += "_CMakeBackup"; - this->BackupBinaryDir = this->BinaryDir; - this->BackupBinaryDir += "_CMakeBackup"; + this->BackupSourceDir = cmStrCat(this->SourceDir, "_CMakeBackup"); + this->BackupBinaryDir = cmStrCat(this->BinaryDir, "_CMakeBackup"); // backup the binary and src directories if requested if (this->Backup) { @@ -664,12 +648,9 @@ int cmCTestScriptHandler::PerformExtraUpdates() // do an initial cvs update as required command = this->UpdateCmd; for (std::string const& eu : this->ExtraUpdates) { - std::vector<std::string> cvsArgs; - cmSystemTools::ExpandListArgument(eu, cvsArgs); + std::vector<std::string> cvsArgs = cmExpandedList(eu); if (cvsArgs.size() == 2) { - std::string fullCommand = command; - fullCommand += " update "; - fullCommand += cvsArgs[1]; + std::string fullCommand = cmStrCat(command, " update ", cvsArgs[1]); output.clear(); retVal = 0; cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, @@ -678,8 +659,8 @@ int cmCTestScriptHandler::PerformExtraUpdates() fullCommand, &output, &output, &retVal, cvsArgs[0].c_str(), this->HandlerVerbose, cmDuration::zero() /*this->TimeOut*/); if (!res || retVal != 0) { - cmSystemTools::Error("Unable to perform extra updates:\n" + eu + - "\nWith output:\n" + output); + cmSystemTools::Error(cmStrCat("Unable to perform extra updates:\n", eu, + "\nWith output:\n", output)); return 0; } } @@ -770,9 +751,7 @@ int cmCTestScriptHandler::RunConfigurationDashboard() int cmakeFailed = 0; std::string cmakeFailedOuput; if (!this->CMakeCmd.empty()) { - command = this->CMakeCmd; - command += " \""; - command += this->SourceDir; + command = cmStrCat(this->CMakeCmd, " \"", this->SourceDir); output.clear(); command += "\""; retVal = 0; @@ -808,8 +787,7 @@ int cmCTestScriptHandler::RunConfigurationDashboard() } // run ctest, it may be more than one command in here - std::vector<std::string> ctestCommands; - cmSystemTools::ExpandListArgument(this->CTestCmd, ctestCommands); + std::vector<std::string> ctestCommands = cmExpandedList(this->CTestCmd); // for each variable/argument do a putenv for (std::string const& ctestCommand : ctestCommands) { command = ctestCommand; @@ -853,8 +831,7 @@ int cmCTestScriptHandler::RunConfigurationDashboard() bool cmCTestScriptHandler::WriteInitialCache(const char* directory, const char* text) { - std::string cacheFile = directory; - cacheFile += "/CMakeCache.txt"; + std::string cacheFile = cmStrCat(directory, "/CMakeCache.txt"); cmGeneratedFileStream fout(cacheFile); if (!fout) { return false; @@ -919,8 +896,7 @@ bool cmCTestScriptHandler::EmptyBinaryDirectory(const char* sname) } // try to avoid deleting directories that we shouldn't - std::string check = sname; - check += "/CMakeCache.txt"; + std::string check = cmStrCat(sname, "/CMakeCache.txt"); if (!cmSystemTools::FileExists(check)) { return false; @@ -949,7 +925,7 @@ bool cmCTestScriptHandler::TryToRemoveBinaryDirectoryOnce( continue; } - std::string fullPath = directoryPath + std::string("/") + path; + std::string fullPath = cmStrCat(directoryPath, "/", path); bool isDirectory = cmSystemTools::FileIsDirectory(fullPath) && !cmSystemTools::FileIsSymlink(fullPath); diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h index d93b5f8..b2e8cbf 100644 --- a/Source/CTest/cmCTestScriptHandler.h +++ b/Source/CTest/cmCTestScriptHandler.h @@ -9,6 +9,7 @@ #include "cmDuration.h" #include <chrono> +#include <memory> #include <string> #include <vector> @@ -131,7 +132,8 @@ private: int RunConfigurationDashboard(); // Add ctest command - void AddCTestCommand(std::string const& name, cmCTestCommand* command); + void AddCTestCommand(std::string const& name, + std::unique_ptr<cmCTestCommand> command); // Try to remove the binary directory once static bool TryToRemoveBinaryDirectoryOnce(const std::string& directoryPath); diff --git a/Source/CTest/cmCTestSleepCommand.h b/Source/CTest/cmCTestSleepCommand.h index 5cd185a..7b17081 100644 --- a/Source/CTest/cmCTestSleepCommand.h +++ b/Source/CTest/cmCTestSleepCommand.h @@ -6,11 +6,14 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmCTestCommand.h" +#include "cmCommand.h" #include <string> +#include <utility> #include <vector> -class cmCommand; +#include "cm_memory.hxx" + class cmExecutionStatus; /** \class cmCTestSleep @@ -27,12 +30,12 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmCTestSleepCommand* ni = new cmCTestSleepCommand; + auto ni = cm::make_unique<cmCTestSleepCommand>(); ni->CTest = this->CTest; ni->CTestScriptHandler = this->CTestScriptHandler; - return ni; + return std::unique_ptr<cmCommand>(std::move(ni)); } /** diff --git a/Source/CTest/cmCTestStartCommand.cxx b/Source/CTest/cmCTestStartCommand.cxx index 67ff2db..e4a1844 100644 --- a/Source/CTest/cmCTestStartCommand.cxx +++ b/Source/CTest/cmCTestStartCommand.cxx @@ -33,14 +33,16 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args, const char* bld_dir = nullptr; while (cnt < args.size()) { - if (args[cnt] == "TRACK") { + if (args[cnt] == "GROUP" || args[cnt] == "TRACK") { cnt++; if (cnt >= args.size() || args[cnt] == "APPEND" || args[cnt] == "QUIET") { - this->SetError("TRACK argument missing track name"); + std::ostringstream e; + e << args[cnt - 1] << " argument missing group name"; + this->SetError(e.str()); return false; } - this->CTest->SetSpecificTrack(args[cnt].c_str()); + this->CTest->SetSpecificGroup(args[cnt].c_str()); cnt++; } else if (args[cnt] == "APPEND") { cnt++; @@ -113,10 +115,10 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args, << " Build directory: " << bld_dir << std::endl, this->Quiet); } - const char* track = this->CTest->GetSpecificTrack(); - if (track) { + const char* group = this->CTest->GetSpecificGroup(); + if (group) { cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Track: " << track << std::endl, this->Quiet); + " Group: " << group << std::endl, this->Quiet); } // Log startup actions. diff --git a/Source/CTest/cmCTestStartCommand.h b/Source/CTest/cmCTestStartCommand.h index 542f27c..7c71f36 100644 --- a/Source/CTest/cmCTestStartCommand.h +++ b/Source/CTest/cmCTestStartCommand.h @@ -6,12 +6,15 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmCTestCommand.h" +#include "cmCommand.h" #include <iosfwd> #include <string> +#include <utility> #include <vector> -class cmCommand; +#include "cm_memory.hxx" + class cmExecutionStatus; /** \class cmCTestStart @@ -27,14 +30,14 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmCTestStartCommand* ni = new cmCTestStartCommand; + auto ni = cm::make_unique<cmCTestStartCommand>(); ni->CTest = this->CTest; ni->CTestScriptHandler = this->CTestScriptHandler; ni->CreateNewTag = this->CreateNewTag; ni->Quiet = this->Quiet; - return ni; + return std::unique_ptr<cmCommand>(std::move(ni)); } /** diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx index afc3e67..d16aac0 100644 --- a/Source/CTest/cmCTestSubmitCommand.cxx +++ b/Source/CTest/cmCTestSubmitCommand.cxx @@ -4,11 +4,16 @@ #include "cmCTest.h" #include "cmCTestSubmitHandler.h" +#include "cmCommand.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include <sstream> +#include <utility> + +#include "cm_memory.hxx" class cmExecutionStatus; @@ -27,12 +32,12 @@ cmCTestSubmitCommand::cmCTestSubmitCommand() /** * This is a virtual constructor for the command. */ -cmCommand* cmCTestSubmitCommand::Clone() +std::unique_ptr<cmCommand> cmCTestSubmitCommand::Clone() { - cmCTestSubmitCommand* ni = new cmCTestSubmitCommand; + auto ni = cm::make_unique<cmCTestSubmitCommand>(); ni->CTest = this->CTest; ni->CTestScriptHandler = this->CTestScriptHandler; - return ni; + return std::unique_ptr<cmCommand>(std::move(ni)); } cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() @@ -63,16 +68,14 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() const char* notesFilesVariable = this->Makefile->GetDefinition("CTEST_NOTES_FILES"); if (notesFilesVariable) { - std::vector<std::string> notesFiles; - cmSystemTools::ExpandListArgument(notesFilesVariable, notesFiles); + std::vector<std::string> notesFiles = cmExpandedList(notesFilesVariable); this->CTest->GenerateNotesFile(notesFiles); } const char* extraFilesVariable = this->Makefile->GetDefinition("CTEST_EXTRA_SUBMIT_FILES"); if (extraFilesVariable) { - std::vector<std::string> extraFiles; - cmSystemTools::ExpandListArgument(extraFilesVariable, extraFiles); + std::vector<std::string> extraFiles = cmExpandedList(extraFilesVariable); if (!this->CTest->SubmitExtraFiles(extraFiles)) { this->SetError("problem submitting extra files."); return nullptr; @@ -139,7 +142,7 @@ bool cmCTestSubmitCommand::InitialPass(std::vector<std::string> const& args, if (this->Values[cts_BUILD_ID] && *this->Values[cts_BUILD_ID]) { this->Makefile->AddDefinition(this->Values[cts_BUILD_ID], - this->CTest->GetBuildID().c_str()); + this->CTest->GetBuildID()); } return ret; diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h index 1e27046..5bbcd39 100644 --- a/Source/CTest/cmCTestSubmitCommand.h +++ b/Source/CTest/cmCTestSubmitCommand.h @@ -8,12 +8,13 @@ #include "cmCTest.h" #include "cmCTestHandlerCommand.h" +#include <memory> #include <set> #include <string> #include <vector> -class cmCTestGenericHandler; class cmCommand; +class cmCTestGenericHandler; class cmExecutionStatus; /** \class cmCTestSubmit @@ -26,7 +27,7 @@ class cmCTestSubmitCommand : public cmCTestHandlerCommand { public: cmCTestSubmitCommand(); - cmCommand* Clone() override; + std::unique_ptr<cmCommand> Clone() override; bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 54c4bae..a178b44 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -19,6 +19,7 @@ #include "cmDuration.h" #include "cmGeneratedFileStream.h" #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLParser.h" #include "cmake.h" @@ -154,8 +155,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP( /* In windows, this will init the winsock stuff */ ::curl_global_init(CURL_GLOBAL_ALL); std::string curlopt(this->CTest->GetCTestConfiguration("CurlOptions")); - std::vector<std::string> args; - cmSystemTools::ExpandListArgument(curlopt, args); + std::vector<std::string> args = cmExpandedList(curlopt); bool verifyPeerOff = false; bool verifyHostOff = false; for (std::string const& arg : args) { @@ -224,7 +224,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP( std::string local_file = file; bool initialize_cdash_buildid = false; if (!cmSystemTools::FileExists(local_file)) { - local_file = localprefix + "/" + file; + local_file = cmStrCat(localprefix, "/", file); // If this file exists within the local Testing directory we assume // that it will be associated with the current build in CDash. initialize_cdash_buildid = true; @@ -236,9 +236,9 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP( << remote_file << std::endl; std::string ofile = cmSystemTools::EncodeURL(remote_file); - std::string upload_as = url + - ((url.find('?') == std::string::npos) ? '?' : '&') + - "FileName=" + ofile; + std::string upload_as = + cmStrCat(url, ((url.find('?') == std::string::npos) ? '?' : '&'), + "FileName=", ofile); if (initialize_cdash_buildid) { // Provide extra arguments to CDash so that it can initialize and @@ -279,7 +279,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP( upload_as += "&MD5="; - if (cmSystemTools::IsOn(this->GetOption("InternalTest"))) { + if (cmIsOn(this->GetOption("InternalTest"))) { upload_as += "bad_md5sum"; } else { upload_as += @@ -498,8 +498,7 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, cmCTestCurl curl(this->CTest); curl.SetQuiet(this->Quiet); std::string curlopt(this->CTest->GetCTestConfiguration("CurlOptions")); - std::vector<std::string> args; - cmSystemTools::ExpandListArgument(curlopt, args); + std::vector<std::string> args = cmExpandedList(curlopt); curl.SetCurlOptions(args); curl.SetTimeOutSeconds(SUBMIT_TIMEOUT_IN_SECONDS_DEFAULT); curl.SetHttpHeaders(this->HttpHeaders); @@ -516,7 +515,7 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, "Only http and https are supported for CDASH_UPLOAD\n"); return -1; } - bool internalTest = cmSystemTools::IsOn(this->GetOption("InternalTest")); + bool internalTest = cmIsOn(this->GetOption("InternalTest")); // Get RETRY_COUNT and RETRY_DELAY values if they were set. std::string retryDelayString = this->GetOption("RetryDelay") == nullptr @@ -528,8 +527,7 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, auto retryDelay = std::chrono::seconds(0); if (!retryDelayString.empty()) { unsigned long retryDelayValue = 0; - if (!cmSystemTools::StringToULong(retryDelayString.c_str(), - &retryDelayValue)) { + if (!cmStrToULong(retryDelayString, &retryDelayValue)) { cmCTestLog(this->CTest, WARNING, "Invalid value for 'RETRY_DELAY' : " << retryDelayString << std::endl); @@ -539,7 +537,7 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, } unsigned long retryCount = 0; if (!retryCountString.empty()) { - if (!cmSystemTools::StringToULong(retryCountString.c_str(), &retryCount)) { + if (!cmStrToULong(retryCountString, &retryCount)) { cmCTestLog(this->CTest, WARNING, "Invalid value for 'RETRY_DELAY' : " << retryCountString << std::endl); @@ -569,6 +567,11 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, << curl.Escape(this->CTest->GetCTestConfiguration("BuildName")) << "&" << "site=" << curl.Escape(this->CTest->GetCTestConfiguration("Site")) << "&" + << "group=" << curl.Escape(this->CTest->GetTestModelString()) + << "&" + // For now, we send both "track" and "group" to CDash in case we're + // submitting to an older instance that still expects the prior + // terminology. << "track=" << curl.Escape(this->CTest->GetTestModelString()) << "&" << "starttime=" << timeNow << "&" << "endtime=" << timeNow << "&" @@ -837,10 +840,10 @@ int cmCTestSubmitHandler::ProcessHandler() } cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Submit files\n", this->Quiet); - const char* specificTrack = this->CTest->GetSpecificTrack(); - if (specificTrack) { + const char* specificGroup = this->CTest->GetSpecificGroup(); + if (specificGroup) { cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Send to track: " << specificTrack << std::endl, + " Send to group: " << specificGroup << std::endl, this->Quiet); } this->SetLogFile(&ofs); diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx index cfd5e3d..24de5b4 100644 --- a/Source/CTest/cmCTestTestCommand.cxx +++ b/Source/CTest/cmCTestTestCommand.cxx @@ -7,7 +7,7 @@ #include "cmCTestTestHandler.h" #include "cmDuration.h" #include "cmMakefile.h" -#include "cmSystemTools.h" +#include "cmStringAlgorithms.h" #include <chrono> #include <sstream> @@ -110,15 +110,14 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler() unsigned long testLoad; const char* ctestTestLoad = this->Makefile->GetDefinition("CTEST_TEST_LOAD"); if (this->Values[ctt_TEST_LOAD] && *this->Values[ctt_TEST_LOAD]) { - if (!cmSystemTools::StringToULong(this->Values[ctt_TEST_LOAD], - &testLoad)) { + if (!cmStrToULong(this->Values[ctt_TEST_LOAD], &testLoad)) { testLoad = 0; cmCTestLog(this->CTest, WARNING, "Invalid value for 'TEST_LOAD' : " << this->Values[ctt_TEST_LOAD] << std::endl); } } else if (ctestTestLoad && *ctestTestLoad) { - if (!cmSystemTools::StringToULong(ctestTestLoad, &testLoad)) { + if (!cmStrToULong(ctestTestLoad, &testLoad)) { testLoad = 0; cmCTestLog(this->CTest, WARNING, "Invalid value for 'CTEST_TEST_LOAD' : " << ctestTestLoad diff --git a/Source/CTest/cmCTestTestCommand.h b/Source/CTest/cmCTestTestCommand.h index 11c0db9..d74136c 100644 --- a/Source/CTest/cmCTestTestCommand.h +++ b/Source/CTest/cmCTestTestCommand.h @@ -6,11 +6,14 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmCTestHandlerCommand.h" +#include "cmCommand.h" #include <string> +#include <utility> + +#include "cm_memory.hxx" class cmCTestGenericHandler; -class cmCommand; /** \class cmCTestTest * \brief Run a ctest script @@ -25,12 +28,12 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmCTestTestCommand* ni = new cmCTestTestCommand; + auto ni = cm::make_unique<cmCTestTestCommand>(); ni->CTest = this->CTest; ni->CTestScriptHandler = this->CTestScriptHandler; - return ni; + return std::unique_ptr<cmCommand>(std::move(ni)); } /** diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 0ed56c8..9181daa 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -11,12 +11,14 @@ #include <functional> #include <iomanip> #include <iterator> -#include <memory> // IWYU pragma: keep #include <set> #include <sstream> #include <stdio.h> #include <stdlib.h> #include <time.h> +#include <utility> + +#include "cm_memory.hxx" #include "cmAlgorithms.h" #include "cmCTest.h" @@ -28,6 +30,7 @@ #include "cmMakefile.h" #include "cmState.h" #include "cmStateSnapshot.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" #include "cmXMLWriter.h" @@ -43,11 +46,11 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmCTestSubdirCommand* c = new cmCTestSubdirCommand; + auto c = cm::make_unique<cmCTestSubdirCommand>(); c->TestHandler = this->TestHandler; - return c; + return std::unique_ptr<cmCommand>(std::move(c)); } /** @@ -74,9 +77,7 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args, if (cmSystemTools::FileIsFullPath(arg)) { fname = arg; } else { - fname = cwd; - fname += "/"; - fname += arg; + fname = cmStrCat(cwd, '/', arg); } if (!cmSystemTools::FileIsDirectory(fname)) { @@ -107,8 +108,7 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args, readit = this->Makefile->ReadDependentFile(fname); } if (!readit) { - std::string m = "Could not find include file: "; - m += fname; + std::string m = cmStrCat("Could not find include file: ", fname); this->SetError(m); return false; } @@ -122,11 +122,11 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmCTestAddSubdirectoryCommand* c = new cmCTestAddSubdirectoryCommand; + auto c = cm::make_unique<cmCTestAddSubdirectoryCommand>(); c->TestHandler = this->TestHandler; - return c; + return std::unique_ptr<cmCommand>(std::move(c)); } /** @@ -147,9 +147,8 @@ bool cmCTestAddSubdirectoryCommand::InitialPass( return false; } - std::string fname = cmSystemTools::GetCurrentWorkingDirectory(); - fname += "/"; - fname += args[0]; + std::string fname = + cmStrCat(cmSystemTools::GetCurrentWorkingDirectory(), '/', args[0]); if (!cmSystemTools::FileExists(fname)) { // No subdirectory? So what... @@ -173,8 +172,7 @@ bool cmCTestAddSubdirectoryCommand::InitialPass( readit = this->Makefile->ReadDependentFile(fname); } if (!readit) { - std::string m = "Could not find include file: "; - m += fname; + std::string m = cmStrCat("Could not find include file: ", fname); this->SetError(m); return false; } @@ -187,11 +185,11 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmCTestAddTestCommand* c = new cmCTestAddTestCommand; + auto c = cm::make_unique<cmCTestAddTestCommand>(); c->TestHandler = this->TestHandler; - return c; + return std::unique_ptr<cmCommand>(std::move(c)); } /** @@ -220,11 +218,11 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmCTestSetTestsPropertiesCommand* c = new cmCTestSetTestsPropertiesCommand; + auto c = cm::make_unique<cmCTestSetTestsPropertiesCommand>(); c->TestHandler = this->TestHandler; - return c; + return std::unique_ptr<cmCommand>(std::move(c)); } /** @@ -249,12 +247,11 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmCTestSetDirectoryPropertiesCommand* c = - new cmCTestSetDirectoryPropertiesCommand; + auto c = cm::make_unique<cmCTestSetDirectoryPropertiesCommand>(); c->TestHandler = this->TestHandler; - return c; + return std::unique_ptr<cmCommand>(std::move(c)); } /** @@ -422,54 +419,11 @@ int cmCTestTestHandler::PostProcessHandler() return 1; } -// clearly it would be nice if this were broken up into a few smaller -// functions and commented... int cmCTestTestHandler::ProcessHandler() { - // Update internal data structure from generic one - this->SetTestsToRunInformation(this->GetOption("TestsToRunInformation")); - this->SetUseUnion(cmSystemTools::IsOn(this->GetOption("UseUnion"))); - if (cmSystemTools::IsOn(this->GetOption("ScheduleRandom"))) { - this->CTest->SetScheduleType("Random"); - } - if (this->GetOption("ParallelLevel")) { - this->CTest->SetParallelLevel(atoi(this->GetOption("ParallelLevel"))); - } - - const char* val; - val = this->GetOption("LabelRegularExpression"); - if (val) { - this->UseIncludeLabelRegExpFlag = true; - this->IncludeLabelRegExp = val; - } - val = this->GetOption("ExcludeLabelRegularExpression"); - if (val) { - this->UseExcludeLabelRegExpFlag = true; - this->ExcludeLabelRegExp = val; - } - val = this->GetOption("IncludeRegularExpression"); - if (val) { - this->UseIncludeRegExp(); - this->SetIncludeRegExp(val); - } - val = this->GetOption("ExcludeRegularExpression"); - if (val) { - this->UseExcludeRegExp(); - this->SetExcludeRegExp(val); - } - val = this->GetOption("ExcludeFixtureRegularExpression"); - if (val) { - this->ExcludeFixtureRegExp = val; - } - val = this->GetOption("ExcludeFixtureSetupRegularExpression"); - if (val) { - this->ExcludeFixtureSetupRegExp = val; - } - val = this->GetOption("ExcludeFixtureCleanupRegularExpression"); - if (val) { - this->ExcludeFixtureCleanupRegExp = val; + if (!this->ProcessOptions()) { + return -1; } - this->SetRerunFailed(cmSystemTools::IsOn(this->GetOption("RerunFailed"))); this->TestResults.clear(); @@ -489,7 +443,6 @@ int cmCTestTestHandler::ProcessHandler() std::vector<std::string> passed; std::vector<std::string> failed; - int total; // start the real time clock auto clock_start = std::chrono::steady_clock::now(); @@ -498,9 +451,7 @@ int cmCTestTestHandler::ProcessHandler() auto clock_finish = std::chrono::steady_clock::now(); - total = int(passed.size()) + int(failed.size()); - - if (total == 0) { + if (passed.size() + failed.size() == 0) { if (!this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels()) { cmCTestLog(this->CTest, ERROR_MESSAGE, "No tests were found!!!" << std::endl); @@ -518,105 +469,192 @@ int cmCTestTestHandler::ProcessHandler() } } - typedef std::set<cmCTestTestHandler::cmCTestTestResult, - cmCTestTestResultLess> - SetOfTests; SetOfTests resultsSet(this->TestResults.begin(), this->TestResults.end()); std::vector<cmCTestTestHandler::cmCTestTestResult> disabledTests; for (cmCTestTestResult const& ft : resultsSet) { - if (cmHasLiteralPrefix(ft.CompletionStatus, "SKIP_RETURN_CODE=") || + if (cmHasLiteralPrefix(ft.CompletionStatus, "SKIP_") || ft.CompletionStatus == "Disabled") { disabledTests.push_back(ft); } } - float percent = float(passed.size()) * 100.0f / float(total); - if (!failed.empty() && percent > 99) { - percent = 99; - } + cmDuration durationInSecs = clock_finish - clock_start; + this->LogTestSummary(passed, failed, durationInSecs); - std::string passColorCode; - std::string failedColorCode; - if (failed.empty()) { - passColorCode = this->CTest->GetColorCode(cmCTest::Color::GREEN); - } else { - failedColorCode = this->CTest->GetColorCode(cmCTest::Color::RED); - } + this->LogDisabledTests(disabledTests); + + this->LogFailedTests(failed, resultsSet); + } + + if (!this->GenerateXML()) { + return 1; + } + + if (!this->PostProcessHandler()) { + this->LogFile = nullptr; + return -1; + } + + if (!failed.empty()) { + this->LogFile = nullptr; + return -1; + } + this->LogFile = nullptr; + return 0; +} + +bool cmCTestTestHandler::ProcessOptions() +{ + // Update internal data structure from generic one + this->SetTestsToRunInformation(this->GetOption("TestsToRunInformation")); + this->SetUseUnion(cmIsOn(this->GetOption("UseUnion"))); + if (cmIsOn(this->GetOption("ScheduleRandom"))) { + this->CTest->SetScheduleType("Random"); + } + if (this->GetOption("ParallelLevel")) { + this->CTest->SetParallelLevel(atoi(this->GetOption("ParallelLevel"))); + } + + const char* val; + val = this->GetOption("LabelRegularExpression"); + if (val) { + this->UseIncludeLabelRegExpFlag = true; + this->IncludeLabelRegExp = val; + } + val = this->GetOption("ExcludeLabelRegularExpression"); + if (val) { + this->UseExcludeLabelRegExpFlag = true; + this->ExcludeLabelRegExp = val; + } + val = this->GetOption("IncludeRegularExpression"); + if (val) { + this->UseIncludeRegExp(); + this->SetIncludeRegExp(val); + } + val = this->GetOption("ExcludeRegularExpression"); + if (val) { + this->UseExcludeRegExp(); + this->SetExcludeRegExp(val); + } + val = this->GetOption("ExcludeFixtureRegularExpression"); + if (val) { + this->ExcludeFixtureRegExp = val; + } + val = this->GetOption("ExcludeFixtureSetupRegularExpression"); + if (val) { + this->ExcludeFixtureSetupRegExp = val; + } + val = this->GetOption("ExcludeFixtureCleanupRegularExpression"); + if (val) { + this->ExcludeFixtureCleanupRegExp = val; + } + this->SetRerunFailed(cmIsOn(this->GetOption("RerunFailed"))); + + return true; +} + +void cmCTestTestHandler::LogTestSummary(const std::vector<std::string>& passed, + const std::vector<std::string>& failed, + const cmDuration& durationInSecs) +{ + std::size_t total = passed.size() + failed.size(); + + float percent = float(passed.size()) * 100.0f / float(total); + if (!failed.empty() && percent > 99) { + percent = 99; + } + + std::string passColorCode; + std::string failedColorCode; + if (failed.empty()) { + passColorCode = this->CTest->GetColorCode(cmCTest::Color::GREEN); + } else { + failedColorCode = this->CTest->GetColorCode(cmCTest::Color::RED); + } + cmCTestLog(this->CTest, HANDLER_OUTPUT, + std::endl + << passColorCode << std::lround(percent) << "% tests passed" + << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR) + << ", " << failedColorCode << failed.size() << " tests failed" + << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR) + << " out of " << total << std::endl); + if ((!this->CTest->GetLabelsForSubprojects().empty() && + this->CTest->GetSubprojectSummary())) { + this->PrintLabelOrSubprojectSummary(true); + } + if (this->CTest->GetLabelSummary()) { + this->PrintLabelOrSubprojectSummary(false); + } + char realBuf[1024]; + sprintf(realBuf, "%6.2f sec", durationInSecs.count()); + cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, + "\nTotal Test time (real) = " << realBuf << "\n", + this->Quiet); +} + +void cmCTestTestHandler::LogDisabledTests( + const std::vector<cmCTestTestResult>& disabledTests) +{ + if (!disabledTests.empty()) { + cmGeneratedFileStream ofs; cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl - << passColorCode << std::lround(percent) << "% tests passed" - << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR) - << ", " << failedColorCode << failed.size() << " tests failed" - << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR) - << " out of " << total << std::endl); - if ((!this->CTest->GetLabelsForSubprojects().empty() && - this->CTest->GetSubprojectSummary())) { - this->PrintLabelOrSubprojectSummary(true); - } - if (this->CTest->GetLabelSummary()) { - this->PrintLabelOrSubprojectSummary(false); - } - char realBuf[1024]; - cmDuration durationInSecs = clock_finish - clock_start; - sprintf(realBuf, "%6.2f sec", durationInSecs.count()); - cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - "\nTotal Test time (real) = " << realBuf << "\n", - this->Quiet); - - if (!disabledTests.empty()) { - cmGeneratedFileStream ofs; - cmCTestLog(this->CTest, HANDLER_OUTPUT, - std::endl - << "The following tests did not run:" << std::endl); - this->StartLogFile("TestsDisabled", ofs); + << "The following tests did not run:" << std::endl); + this->StartLogFile("TestsDisabled", ofs); - const char* disabled_reason; - cmCTestLog(this->CTest, HANDLER_OUTPUT, - this->CTest->GetColorCode(cmCTest::Color::BLUE)); - for (cmCTestTestResult const& dt : disabledTests) { - ofs << dt.TestCount << ":" << dt.Name << std::endl; - if (dt.CompletionStatus == "Disabled") { - disabled_reason = "Disabled"; - } else { - disabled_reason = "Skipped"; - } - cmCTestLog(this->CTest, HANDLER_OUTPUT, - "\t" << std::setw(3) << dt.TestCount << " - " << dt.Name - << " (" << disabled_reason << ")" << std::endl); + const char* disabled_reason; + cmCTestLog(this->CTest, HANDLER_OUTPUT, + this->CTest->GetColorCode(cmCTest::Color::BLUE)); + for (cmCTestTestResult const& dt : disabledTests) { + ofs << dt.TestCount << ":" << dt.Name << std::endl; + if (dt.CompletionStatus == "Disabled") { + disabled_reason = "Disabled"; + } else { + disabled_reason = "Skipped"; } cmCTestLog(this->CTest, HANDLER_OUTPUT, - this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)); + "\t" << std::setw(3) << dt.TestCount << " - " << dt.Name + << " (" << disabled_reason << ")" << std::endl); } + cmCTestLog(this->CTest, HANDLER_OUTPUT, + this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR)); + } +} - if (!failed.empty()) { - cmGeneratedFileStream ofs; - cmCTestLog(this->CTest, HANDLER_OUTPUT, - std::endl - << "The following tests FAILED:" << std::endl); - this->StartLogFile("TestsFailed", ofs); - - for (cmCTestTestResult const& ft : resultsSet) { - if (ft.Status != cmCTestTestHandler::COMPLETED && - !cmHasLiteralPrefix(ft.CompletionStatus, "SKIP_RETURN_CODE=") && - ft.CompletionStatus != "Disabled") { - ofs << ft.TestCount << ":" << ft.Name << std::endl; - auto testColor = cmCTest::Color::RED; - if (this->GetTestStatus(ft) == "Not Run") { - testColor = cmCTest::Color::YELLOW; - } - cmCTestLog( - this->CTest, HANDLER_OUTPUT, - "\t" << this->CTest->GetColorCode(testColor) << std::setw(3) - << ft.TestCount << " - " << ft.Name << " (" - << this->GetTestStatus(ft) << ")" - << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR) - << std::endl); +void cmCTestTestHandler::LogFailedTests(const std::vector<std::string>& failed, + const SetOfTests& resultsSet) +{ + if (!failed.empty()) { + cmGeneratedFileStream ofs; + cmCTestLog(this->CTest, HANDLER_OUTPUT, + std::endl + << "The following tests FAILED:" << std::endl); + this->StartLogFile("TestsFailed", ofs); + + for (cmCTestTestResult const& ft : resultsSet) { + if (ft.Status != cmCTestTestHandler::COMPLETED && + !cmHasLiteralPrefix(ft.CompletionStatus, "SKIP_") && + ft.CompletionStatus != "Disabled") { + ofs << ft.TestCount << ":" << ft.Name << std::endl; + auto testColor = cmCTest::Color::RED; + if (this->GetTestStatus(ft) == "Not Run") { + testColor = cmCTest::Color::YELLOW; } + cmCTestLog( + this->CTest, HANDLER_OUTPUT, + "\t" << this->CTest->GetColorCode(testColor) << std::setw(3) + << ft.TestCount << " - " << ft.Name << " (" + << this->GetTestStatus(ft) << ")" + << this->CTest->GetColorCode(cmCTest::Color::CLEAR_COLOR) + << std::endl); } } } +} +bool cmCTestTestHandler::GenerateXML() +{ if (this->CTest->GetProduceXML()) { cmGeneratedFileStream xmlfile; if (!this->StartResultingXML( @@ -627,23 +665,13 @@ int cmCTestTestHandler::ProcessHandler() << (this->MemCheck ? "memory check" : "testing") << " XML file" << std::endl); this->LogFile = nullptr; - return 1; + return false; } cmXMLWriter xml(xmlfile); this->GenerateDartOutput(xml); } - if (!this->PostProcessHandler()) { - this->LogFile = nullptr; - return -1; - } - - if (!failed.empty()) { - this->LogFile = nullptr; - return -1; - } - this->LogFile = nullptr; - return 0; + return true; } void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject) @@ -667,8 +695,7 @@ void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject) } // if we are doing sub projects and this label is one, then use it // if we are not doing sub projects and the label is not one use it - if ((doSubProject && isSubprojectLabel) || - (!doSubProject && !isSubprojectLabel)) { + if (doSubProject == isSubprojectLabel) { if (l.size() > maxlen) { maxlen = l.size(); } @@ -683,7 +710,7 @@ void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject) cmCTestTestProperties& p = *result.Properties; for (std::string const& l : p.Labels) { // only use labels found in labels - if (labels.find(l) != labels.end()) { + if (cmContains(labels, l)) { labelTimes[l] += result.ExecutionTime.count() * result.Properties->Processors; ++labelCounts[l]; @@ -825,17 +852,14 @@ void cmCTestTestHandler::ComputeTestList() if (this->UseUnion) { // if it is not in the list and not in the regexp then skip - if ((!this->TestsToRun.empty() && - std::find(this->TestsToRun.begin(), this->TestsToRun.end(), cnt) == - this->TestsToRun.end()) && + if ((!this->TestsToRun.empty() && !cmContains(this->TestsToRun, cnt)) && !tp.IsInBasedOnREOptions) { continue; } } else { // is this test in the list of tests to run? If not then skip it if ((!this->TestsToRun.empty() && - std::find(this->TestsToRun.begin(), this->TestsToRun.end(), - inREcnt) == this->TestsToRun.end()) || + !cmContains(this->TestsToRun, inREcnt)) || !tp.IsInBasedOnREOptions) { continue; } @@ -864,9 +888,7 @@ void cmCTestTestHandler::ComputeTestListForRerunFailed() cnt++; // if this test is not in our list of tests to run, then skip it. - if ((!this->TestsToRun.empty() && - std::find(this->TestsToRun.begin(), this->TestsToRun.end(), cnt) == - this->TestsToRun.end())) { + if (!this->TestsToRun.empty() && !cmContains(this->TestsToRun, cnt)) { continue; } @@ -987,8 +1009,7 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const sIt != setupRange.second; ++sIt) { const std::string& setupTestName = sIt->second->Name; tests[i].RequireSuccessDepends.insert(setupTestName); - if (std::find(tests[i].Depends.begin(), tests[i].Depends.end(), - setupTestName) == tests[i].Depends.end()) { + if (!cmContains(tests[i].Depends, setupTestName)) { tests[i].Depends.push_back(setupTestName); } } @@ -1095,8 +1116,7 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const const std::vector<size_t>& indices = cIt->second; for (size_t index : indices) { const std::string& reqTestName = tests[index].Name; - if (std::find(p.Depends.begin(), p.Depends.end(), reqTestName) == - p.Depends.end()) { + if (!cmContains(p.Depends, reqTestName)) { p.Depends.push_back(reqTestName); } } @@ -1109,8 +1129,7 @@ void cmCTestTestHandler::UpdateForFixtures(ListOfTests& tests) const const std::vector<size_t>& indices = cIt->second; for (size_t index : indices) { const std::string& setupTestName = tests[index].Name; - if (std::find(p.Depends.begin(), p.Depends.end(), setupTestName) == - p.Depends.end()) { + if (!cmContains(p.Depends, setupTestName)) { p.Depends.push_back(setupTestName); } } @@ -1527,50 +1546,32 @@ void cmCTestTestHandler::AddConfigurations( attemptedConfigs.emplace_back(); if (!ctest->GetConfigType().empty()) { - tempPath = filepath; - tempPath += ctest->GetConfigType(); - tempPath += "/"; - tempPath += filename; + tempPath = cmStrCat(filepath, ctest->GetConfigType(), '/', filename); attempted.push_back(tempPath); attemptedConfigs.push_back(ctest->GetConfigType()); // If the file is an OSX bundle then the configtype // will be at the start of the path - tempPath = ctest->GetConfigType(); - tempPath += "/"; - tempPath += filepath; - tempPath += filename; + tempPath = cmStrCat(ctest->GetConfigType(), '/', filepath, filename); attempted.push_back(tempPath); attemptedConfigs.push_back(ctest->GetConfigType()); } else { // no config specified - try some options... - tempPath = filepath; - tempPath += "Release/"; - tempPath += filename; + tempPath = cmStrCat(filepath, "Release/", filename); attempted.push_back(tempPath); attemptedConfigs.emplace_back("Release"); - tempPath = filepath; - tempPath += "Debug/"; - tempPath += filename; + tempPath = cmStrCat(filepath, "Debug/", filename); attempted.push_back(tempPath); attemptedConfigs.emplace_back("Debug"); - tempPath = filepath; - tempPath += "MinSizeRel/"; - tempPath += filename; + tempPath = cmStrCat(filepath, "MinSizeRel/", filename); attempted.push_back(tempPath); attemptedConfigs.emplace_back("MinSizeRel"); - tempPath = filepath; - tempPath += "RelWithDebInfo/"; - tempPath += filename; + tempPath = cmStrCat(filepath, "RelWithDebInfo/", filename); attempted.push_back(tempPath); attemptedConfigs.emplace_back("RelWithDebInfo"); - tempPath = filepath; - tempPath += "Deployment/"; - tempPath += filename; + tempPath = cmStrCat(filepath, "Deployment/", filename); attempted.push_back(tempPath); attemptedConfigs.emplace_back("Deployment"); - tempPath = filepath; - tempPath += "Development/"; - tempPath += filename; + tempPath = cmStrCat(filepath, "Development/", filename); attempted.push_back(tempPath); attemptedConfigs.emplace_back("Deployment"); } @@ -1624,8 +1625,8 @@ std::string cmCTestTestHandler::FindExecutable( // then try with the exe extension else { failed.push_back(attempted[ai]); - tempPath = attempted[ai]; - tempPath += cmSystemTools::GetExecutableExtension(); + tempPath = + cmStrCat(attempted[ai], cmSystemTools::GetExecutableExtension()); if (cmSystemTools::FileExists(tempPath) && !cmSystemTools::FileIsDirectory(tempPath)) { fullPath = cmSystemTools::CollapseFullPath(tempPath); @@ -1682,36 +1683,34 @@ void cmCTestTestHandler::GetListOfTests() cm.GetCurrentSnapshot().SetDefaultDefinitions(); cmGlobalGenerator gg(&cm); cmMakefile mf(&gg, cm.GetCurrentSnapshot()); - mf.AddDefinition("CTEST_CONFIGURATION_TYPE", - this->CTest->GetConfigType().c_str()); + mf.AddDefinition("CTEST_CONFIGURATION_TYPE", this->CTest->GetConfigType()); // Add handler for ADD_TEST - cmCTestAddTestCommand* newCom1 = new cmCTestAddTestCommand; + auto newCom1 = cm::make_unique<cmCTestAddTestCommand>(); newCom1->TestHandler = this; - cm.GetState()->AddBuiltinCommand("add_test", newCom1); + cm.GetState()->AddBuiltinCommand("add_test", std::move(newCom1)); // Add handler for SUBDIRS - cmCTestSubdirCommand* newCom2 = new cmCTestSubdirCommand; + auto newCom2 = cm::make_unique<cmCTestSubdirCommand>(); newCom2->TestHandler = this; - cm.GetState()->AddBuiltinCommand("subdirs", newCom2); + cm.GetState()->AddBuiltinCommand("subdirs", std::move(newCom2)); // Add handler for ADD_SUBDIRECTORY - cmCTestAddSubdirectoryCommand* newCom3 = new cmCTestAddSubdirectoryCommand; + auto newCom3 = cm::make_unique<cmCTestAddSubdirectoryCommand>(); newCom3->TestHandler = this; - cm.GetState()->AddBuiltinCommand("add_subdirectory", newCom3); + cm.GetState()->AddBuiltinCommand("add_subdirectory", std::move(newCom3)); // Add handler for SET_TESTS_PROPERTIES - cmCTestSetTestsPropertiesCommand* newCom4 = - new cmCTestSetTestsPropertiesCommand; + auto newCom4 = cm::make_unique<cmCTestSetTestsPropertiesCommand>(); newCom4->TestHandler = this; - cm.GetState()->AddBuiltinCommand("set_tests_properties", newCom4); + cm.GetState()->AddBuiltinCommand("set_tests_properties", std::move(newCom4)); // Add handler for SET_DIRECTORY_PROPERTIES cm.GetState()->RemoveBuiltinCommand("set_directory_properties"); - cmCTestSetDirectoryPropertiesCommand* newCom5 = - new cmCTestSetDirectoryPropertiesCommand; + auto newCom5 = cm::make_unique<cmCTestSetDirectoryPropertiesCommand>(); newCom5->TestHandler = this; - cm.GetState()->AddBuiltinCommand("set_directory_properties", newCom5); + cm.GetState()->AddBuiltinCommand("set_directory_properties", + std::move(newCom5)); const char* testFilename; if (cmSystemTools::FileExists("CTestTestfile.cmake")) { @@ -2150,7 +2149,7 @@ bool cmCTestTestHandler::SetTestsProperties( if (key == "_BACKTRACE_TRIPLES") { std::vector<std::string> triples; // allow empty args in the triples - cmSystemTools::ExpandListArgument(val, triples, true); + cmExpandList(val, triples, true); // Ensure we have complete triples otherwise the data is corrupt. if (triples.size() % 3 == 0) { @@ -2163,8 +2162,7 @@ bool cmCTestTestHandler::SetTestsProperties( cmListFileContext fc; fc.FilePath = triples[i - 3]; long line = 0; - if (!cmSystemTools::StringToLong(triples[i - 2].c_str(), - &line)) { + if (!cmStrToLong(triples[i - 2], &line)) { line = 0; } fc.Line = line; @@ -2174,38 +2172,34 @@ bool cmCTestTestHandler::SetTestsProperties( } } if (key == "WILL_FAIL") { - rt.WillFail = cmSystemTools::IsOn(val); + rt.WillFail = cmIsOn(val); } if (key == "DISABLED") { - rt.Disabled = cmSystemTools::IsOn(val); + rt.Disabled = cmIsOn(val); } if (key == "ATTACHED_FILES") { - cmSystemTools::ExpandListArgument(val, rt.AttachedFiles); + cmExpandList(val, rt.AttachedFiles); } if (key == "ATTACHED_FILES_ON_FAIL") { - cmSystemTools::ExpandListArgument(val, rt.AttachOnFail); + cmExpandList(val, rt.AttachOnFail); } if (key == "RESOURCE_LOCK") { - std::vector<std::string> lval; - cmSystemTools::ExpandListArgument(val, lval); + std::vector<std::string> lval = cmExpandedList(val); rt.LockedResources.insert(lval.begin(), lval.end()); } if (key == "FIXTURES_SETUP") { - std::vector<std::string> lval; - cmSystemTools::ExpandListArgument(val, lval); + std::vector<std::string> lval = cmExpandedList(val); rt.FixturesSetup.insert(lval.begin(), lval.end()); } if (key == "FIXTURES_CLEANUP") { - std::vector<std::string> lval; - cmSystemTools::ExpandListArgument(val, lval); + std::vector<std::string> lval = cmExpandedList(val); rt.FixturesCleanup.insert(lval.begin(), lval.end()); } if (key == "FIXTURES_REQUIRED") { - std::vector<std::string> lval; - cmSystemTools::ExpandListArgument(val, lval); + std::vector<std::string> lval = cmExpandedList(val); rt.FixturesRequired.insert(lval.begin(), lval.end()); } @@ -2217,18 +2211,23 @@ bool cmCTestTestHandler::SetTestsProperties( rt.Cost = static_cast<float>(atof(val.c_str())); } if (key == "REQUIRED_FILES") { - cmSystemTools::ExpandListArgument(val, rt.RequiredFiles); + cmExpandList(val, rt.RequiredFiles); } if (key == "RUN_SERIAL") { - rt.RunSerial = cmSystemTools::IsOn(val); + rt.RunSerial = cmIsOn(val); } if (key == "FAIL_REGULAR_EXPRESSION") { - std::vector<std::string> lval; - cmSystemTools::ExpandListArgument(val, lval); + std::vector<std::string> lval = cmExpandedList(val); for (std::string const& cr : lval) { rt.ErrorRegularExpressions.emplace_back(cr, cr); } } + if (key == "SKIP_REGULAR_EXPRESSION") { + std::vector<std::string> lval = cmExpandedList(val); + for (std::string const& cr : lval) { + rt.SkipRegularExpressions.emplace_back(cr, cr); + } + } if (key == "PROCESSORS") { rt.Processors = atoi(val.c_str()); if (rt.Processors < 1) { @@ -2236,7 +2235,7 @@ bool cmCTestTestHandler::SetTestsProperties( } } if (key == "PROCESSOR_AFFINITY") { - rt.WantAffinity = cmSystemTools::IsOn(val); + rt.WantAffinity = cmIsOn(val); } if (key == "SKIP_RETURN_CODE") { rt.SkipReturnCode = atoi(val.c_str()); @@ -2245,14 +2244,13 @@ bool cmCTestTestHandler::SetTestsProperties( } } if (key == "DEPENDS") { - cmSystemTools::ExpandListArgument(val, rt.Depends); + cmExpandList(val, rt.Depends); } if (key == "ENVIRONMENT") { - cmSystemTools::ExpandListArgument(val, rt.Environment); + cmExpandList(val, rt.Environment); } if (key == "LABELS") { - std::vector<std::string> Labels; - cmSystemTools::ExpandListArgument(val, Labels); + std::vector<std::string> Labels = cmExpandedList(val); rt.Labels.insert(rt.Labels.end(), Labels.begin(), Labels.end()); // sort the array std::sort(rt.Labels.begin(), rt.Labels.end()); @@ -2272,8 +2270,7 @@ bool cmCTestTestHandler::SetTestsProperties( } } if (key == "PASS_REGULAR_EXPRESSION") { - std::vector<std::string> lval; - cmSystemTools::ExpandListArgument(val, lval); + std::vector<std::string> lval = cmExpandedList(val); for (std::string const& cr : lval) { rt.RequiredRegularExpressions.emplace_back(cr, cr); } @@ -2282,16 +2279,14 @@ bool cmCTestTestHandler::SetTestsProperties( rt.Directory = val; } if (key == "TIMEOUT_AFTER_MATCH") { - std::vector<std::string> propArgs; - cmSystemTools::ExpandListArgument(val, propArgs); + std::vector<std::string> propArgs = cmExpandedList(val); if (propArgs.size() != 2) { cmCTestLog(this->CTest, WARNING, "TIMEOUT_AFTER_MATCH expects two arguments, found " << propArgs.size() << std::endl); } else { rt.AlternateTimeout = cmDuration(atof(propArgs[0].c_str())); - std::vector<std::string> lval; - cmSystemTools::ExpandListArgument(propArgs[1], lval); + std::vector<std::string> lval = cmExpandedList(propArgs[1]); for (std::string const& cr : lval) { rt.TimeoutRegularExpressions.emplace_back(cr, cr); } @@ -2333,8 +2328,7 @@ bool cmCTestTestHandler::SetDirectoryProperties( std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); if (cwd == rt.Directory) { if (key == "LABELS") { - std::vector<std::string> DirectoryLabels; - cmSystemTools::ExpandListArgument(val, DirectoryLabels); + std::vector<std::string> DirectoryLabels = cmExpandedList(val); rt.Labels.insert(rt.Labels.end(), DirectoryLabels.begin(), DirectoryLabels.end()); diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 7f3f5e4..9345185 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -118,6 +118,8 @@ public: std::vector<std::pair<cmsys::RegularExpression, std::string>> RequiredRegularExpressions; std::vector<std::pair<cmsys::RegularExpression, std::string>> + SkipRegularExpressions; + std::vector<std::pair<cmsys::RegularExpression, std::string>> TimeoutRegularExpressions; std::map<std::string, std::string> Measurements; bool IsInBasedOnREOptions; @@ -189,12 +191,25 @@ public: typedef std::vector<cmCTestTestProperties> ListOfTests; protected: + typedef std::set<cmCTestTestHandler::cmCTestTestResult, + cmCTestTestResultLess> + SetOfTests; + // compute a final test list virtual int PreProcessHandler(); virtual int PostProcessHandler(); virtual void GenerateTestCommand(std::vector<std::string>& args, int test); int ExecuteCommands(std::vector<std::string>& vec); + bool ProcessOptions(); + void LogTestSummary(const std::vector<std::string>& passed, + const std::vector<std::string>& failed, + const cmDuration& durationInSecs); + void LogDisabledTests(const std::vector<cmCTestTestResult>& disabledTests); + void LogFailedTests(const std::vector<std::string>& failed, + const SetOfTests& resultsSet); + bool GenerateXML(); + void WriteTestResultHeader(cmXMLWriter& xml, cmCTestTestResult const& result); void WriteTestResultFooter(cmXMLWriter& xml, diff --git a/Source/CTest/cmCTestUpdateCommand.h b/Source/CTest/cmCTestUpdateCommand.h index 3b2f3e1..55c4b80 100644 --- a/Source/CTest/cmCTestUpdateCommand.h +++ b/Source/CTest/cmCTestUpdateCommand.h @@ -6,11 +6,14 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmCTestHandlerCommand.h" +#include "cmCommand.h" #include <string> +#include <utility> + +#include "cm_memory.hxx" class cmCTestGenericHandler; -class cmCommand; /** \class cmCTestUpdate * \brief Run a ctest script @@ -25,12 +28,12 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmCTestUpdateCommand* ni = new cmCTestUpdateCommand; + auto ni = cm::make_unique<cmCTestUpdateCommand>(); ni->CTest = this->CTest; ni->CTestScriptHandler = this->CTestScriptHandler; - return ni; + return std::unique_ptr<cmCommand>(std::move(ni)); } /** diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx index 5cfc4a7..a6a3542 100644 --- a/Source/CTest/cmCTestUpdateHandler.cxx +++ b/Source/CTest/cmCTestUpdateHandler.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestUpdateHandler.h" -#include "cmAlgorithms.h" #include "cmCLocaleEnvironmentScope.h" #include "cmCTest.h" #include "cmCTestBZR.h" @@ -13,14 +12,16 @@ #include "cmCTestSVN.h" #include "cmCTestVC.h" #include "cmGeneratedFileStream.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVersion.h" #include "cmXMLWriter.h" #include <chrono> -#include <memory> // IWYU pragma: keep #include <sstream> +#include "cm_memory.hxx" + static const char* cmCTestUpdateHandlerUpdateStrings[] = { "Unknown", "CVS", "SVN", "BZR", "GIT", "HG", "P4" }; @@ -266,33 +267,27 @@ int cmCTestUpdateHandler::DetectVCS(const char* dir) if (cmSystemTools::FileExists(sourceDirectory)) { return cmCTestUpdateHandler::e_SVN; } - sourceDirectory = dir; - sourceDirectory += "/CVS"; + sourceDirectory = cmStrCat(dir, "/CVS"); if (cmSystemTools::FileExists(sourceDirectory)) { return cmCTestUpdateHandler::e_CVS; } - sourceDirectory = dir; - sourceDirectory += "/.bzr"; + sourceDirectory = cmStrCat(dir, "/.bzr"); if (cmSystemTools::FileExists(sourceDirectory)) { return cmCTestUpdateHandler::e_BZR; } - sourceDirectory = dir; - sourceDirectory += "/.git"; + sourceDirectory = cmStrCat(dir, "/.git"); if (cmSystemTools::FileExists(sourceDirectory)) { return cmCTestUpdateHandler::e_GIT; } - sourceDirectory = dir; - sourceDirectory += "/.hg"; + sourceDirectory = cmStrCat(dir, "/.hg"); if (cmSystemTools::FileExists(sourceDirectory)) { return cmCTestUpdateHandler::e_HG; } - sourceDirectory = dir; - sourceDirectory += "/.p4"; + sourceDirectory = cmStrCat(dir, "/.p4"); if (cmSystemTools::FileExists(sourceDirectory)) { return cmCTestUpdateHandler::e_P4; } - sourceDirectory = dir; - sourceDirectory += "/.p4config"; + sourceDirectory = cmStrCat(dir, "/.p4config"); if (cmSystemTools::FileExists(sourceDirectory)) { return cmCTestUpdateHandler::e_P4; } diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h index 0d3b06e..2bb072f 100644 --- a/Source/CTest/cmCTestUploadCommand.h +++ b/Source/CTest/cmCTestUploadCommand.h @@ -6,12 +6,15 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmCTestHandlerCommand.h" +#include "cmCommand.h" #include <set> #include <string> +#include <utility> + +#include "cm_memory.hxx" class cmCTestGenericHandler; -class cmCommand; /** \class cmCTestUpload * \brief Run a ctest script @@ -25,12 +28,12 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmCTestUploadCommand* ni = new cmCTestUploadCommand; + auto ni = cm::make_unique<cmCTestUploadCommand>(); ni->CTest = this->CTest; ni->CTestScriptHandler = this->CTestScriptHandler; - return ni; + return std::unique_ptr<cmCommand>(std::move(ni)); } /** diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx index eea41cf..773886d 100644 --- a/Source/CTest/cmCTestVC.cxx +++ b/Source/CTest/cmCTestVC.cxx @@ -3,6 +3,7 @@ #include "cmCTestVC.h" #include "cmCTest.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" @@ -152,8 +153,7 @@ bool cmCTestVC::Update() // if update version only is on then do not actually update, // just note the current version and finish - if (!cmSystemTools::IsOn( - this->CTest->GetCTestConfiguration("UpdateVersionOnly"))) { + if (!cmIsOn(this->CTest->GetCTestConfiguration("UpdateVersionOnly"))) { result = this->NoteOldRevision() && result; this->Log << "--- Begin Update ---\n"; result = this->UpdateImpl() && result; diff --git a/Source/CTest/cmParseBlanketJSCoverage.cxx b/Source/CTest/cmParseBlanketJSCoverage.cxx index 63d6a15..b74decb 100644 --- a/Source/CTest/cmParseBlanketJSCoverage.cxx +++ b/Source/CTest/cmParseBlanketJSCoverage.cxx @@ -110,7 +110,8 @@ cmParseBlanketJSCoverage::cmParseBlanketJSCoverage( { } -bool cmParseBlanketJSCoverage::LoadCoverageData(std::vector<std::string> files) +bool cmParseBlanketJSCoverage::LoadCoverageData( + std::vector<std::string> const& files) { cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Found " << files.size() << " Files" << std::endl, diff --git a/Source/CTest/cmParseBlanketJSCoverage.h b/Source/CTest/cmParseBlanketJSCoverage.h index 696121f..cd1b225 100644 --- a/Source/CTest/cmParseBlanketJSCoverage.h +++ b/Source/CTest/cmParseBlanketJSCoverage.h @@ -29,7 +29,7 @@ class cmParseBlanketJSCoverage public: cmParseBlanketJSCoverage(cmCTestCoverageHandlerContainer& cont, cmCTest* ctest); - bool LoadCoverageData(std::vector<std::string> files); + bool LoadCoverageData(std::vector<std::string> const& files); // Read the JSON output bool ReadJSONFile(std::string const& file); diff --git a/Source/CTest/cmParseCacheCoverage.cxx b/Source/CTest/cmParseCacheCoverage.cxx index ca1fe70..cd2bb1a 100644 --- a/Source/CTest/cmParseCacheCoverage.cxx +++ b/Source/CTest/cmParseCacheCoverage.cxx @@ -2,6 +2,7 @@ #include "cmCTest.h" #include "cmCTestCoverageHandler.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmsys/Directory.hxx" @@ -30,9 +31,7 @@ bool cmParseCacheCoverage::LoadCoverageData(const char* d) for (i = 0; i < numf; i++) { std::string file = dir.GetFile(i); if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) { - std::string path = d; - path += "/"; - path += file; + std::string path = cmStrCat(d, '/', file); if (cmSystemTools::GetFilenameLastExtension(path) == ".cmcov") { if (!this->ReadCMCovFile(path.c_str())) { return false; diff --git a/Source/CTest/cmParseCoberturaCoverage.cxx b/Source/CTest/cmParseCoberturaCoverage.cxx index 848a034..e0186c9 100644 --- a/Source/CTest/cmParseCoberturaCoverage.cxx +++ b/Source/CTest/cmParseCoberturaCoverage.cxx @@ -2,6 +2,7 @@ #include "cmCTest.h" #include "cmCTestCoverageHandler.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLParser.h" @@ -75,7 +76,7 @@ protected: // Check if this is a path that is relative to our source or // binary directories. for (std::string const& filePath : FilePaths) { - finalpath = filePath + "/" + filename; + finalpath = cmStrCat(filePath, "/", filename); if (cmSystemTools::FileExists(finalpath)) { this->CurFileName = finalpath; break; @@ -86,7 +87,7 @@ protected: cmsys::ifstream fin(this->CurFileName.c_str()); if (this->CurFileName.empty() || !fin) { this->CurFileName = - this->Coverage.BinaryDir + "/" + atts[tagCount + 1]; + cmStrCat(this->Coverage.BinaryDir, "/", atts[tagCount + 1]); fin.open(this->CurFileName.c_str()); if (!fin) { cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, diff --git a/Source/CTest/cmParseGTMCoverage.cxx b/Source/CTest/cmParseGTMCoverage.cxx index 0722753..621ca79 100644 --- a/Source/CTest/cmParseGTMCoverage.cxx +++ b/Source/CTest/cmParseGTMCoverage.cxx @@ -1,8 +1,8 @@ #include "cmParseGTMCoverage.h" -#include "cmAlgorithms.h" #include "cmCTest.h" #include "cmCTestCoverageHandler.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmsys/Directory.hxx" @@ -31,9 +31,7 @@ bool cmParseGTMCoverage::LoadCoverageData(const char* d) for (i = 0; i < numf; i++) { std::string file = dir.GetFile(i); if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) { - std::string path = d; - path += "/"; - path += file; + std::string path = cmStrCat(d, '/', file); if (cmSystemTools::GetFilenameLastExtension(path) == ".mcov") { if (!this->ReadMCovFile(path.c_str())) { return false; diff --git a/Source/CTest/cmParseJacocoCoverage.cxx b/Source/CTest/cmParseJacocoCoverage.cxx index b78142a..374acad 100644 --- a/Source/CTest/cmParseJacocoCoverage.cxx +++ b/Source/CTest/cmParseJacocoCoverage.cxx @@ -2,6 +2,7 @@ #include "cmCTest.h" #include "cmCTestCoverageHandler.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLParser.h" @@ -103,9 +104,7 @@ protected: std::string const& baseDir) { // Search for the file in the baseDir and its subdirectories. - std::string packageGlob = baseDir; - packageGlob += "/"; - packageGlob += fileName; + std::string packageGlob = cmStrCat(baseDir, '/', fileName); cmsys::Glob gl; gl.RecurseOn(); gl.RecurseThroughSymlinksOn(); @@ -118,7 +117,7 @@ protected: // Check if any of the locations found match our package. for (std::string const& f : files) { std::string dir = cmsys::SystemTools::GetParentDirectory(f); - if (cmsys::SystemTools::StringEndsWith(dir, this->PackageName.c_str())) { + if (cmHasSuffix(dir, this->PackageName)) { cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Found package directory for " << fileName << ": " << dir << std::endl, diff --git a/Source/CTest/cmParseMumpsCoverage.cxx b/Source/CTest/cmParseMumpsCoverage.cxx index 4a81ee4..afd7dc3 100644 --- a/Source/CTest/cmParseMumpsCoverage.cxx +++ b/Source/CTest/cmParseMumpsCoverage.cxx @@ -2,6 +2,7 @@ #include "cmCTest.h" #include "cmCTestCoverageHandler.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmsys/FStream.hxx" @@ -107,8 +108,7 @@ bool cmParseMumpsCoverage::LoadPackages(const char* d) { cmsys::Glob glob; glob.RecurseOn(); - std::string pat = d; - pat += "/*.m"; + std::string pat = cmStrCat(d, "/*.m"); glob.FindFiles(pat); for (std::string& file : glob.GetFiles()) { std::string name = cmSystemTools::GetFilenameName(file); diff --git a/Source/CTest/cmParsePHPCoverage.cxx b/Source/CTest/cmParsePHPCoverage.cxx index a6e65c9..870e222 100644 --- a/Source/CTest/cmParsePHPCoverage.cxx +++ b/Source/CTest/cmParsePHPCoverage.cxx @@ -2,6 +2,7 @@ #include "cmCTest.h" #include "cmCTestCoverageHandler.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmsys/Directory.hxx" @@ -210,9 +211,7 @@ bool cmParsePHPCoverage::ReadPHPCoverageDirectory(const char* d) for (i = 0; i < numf; i++) { std::string file = dir.GetFile(i); if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) { - std::string path = d; - path += "/"; - path += file; + std::string path = cmStrCat(d, '/', file); if (!this->ReadPHPData(path.c_str())) { return false; } diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index 7a3b82e..61d2ed3 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -7,6 +7,7 @@ #include "cmCTestRunTest.h" #include "cmCTestTestHandler.h" #include "cmGetPipes.h" +#include "cmStringAlgorithms.h" #include "cmsys/Process.h" #include <iostream> @@ -694,8 +695,7 @@ std::string cmProcess::GetExitExceptionString() # endif # endif default: - exception_str = "Signal "; - exception_str += std::to_string(this->Signal); + exception_str = cmStrCat("Signal ", this->Signal); } #endif return exception_str; diff --git a/Source/Checks/cm_cxx17_check.cpp b/Source/Checks/cm_cxx17_check.cpp index 593d9b2..29863b1 100644 --- a/Source/Checks/cm_cxx17_check.cpp +++ b/Source/Checks/cm_cxx17_check.cpp @@ -1,6 +1,7 @@ #include <cstdio> #include <iterator> #include <memory> +#include <optional> #include <unordered_map> #ifdef _MSC_VER @@ -27,5 +28,7 @@ int main() IDispatchPtr disp(ptr); #endif - return *u + *ai + *(bi - 1) + (3 - static_cast<int>(ci)); + std::optional<int> oi = 0; + + return *u + *ai + *(bi - 1) + (3 - static_cast<int>(ci)) + oi.value(); } diff --git a/Source/CursesDialog/CMakeLists.txt b/Source/CursesDialog/CMakeLists.txt index c51b0dd..270b07e 100644 --- a/Source/CursesDialog/CMakeLists.txt +++ b/Source/CursesDialog/CMakeLists.txt @@ -23,6 +23,10 @@ include_directories(${CURSES_INCLUDE_PATH}) add_executable(ccmake ${CURSES_SRCS} ) target_link_libraries(ccmake CMakeLib) if(CMAKE_USE_SYSTEM_FORM) + find_path(CURSES_FORM_INCLUDE_DIR NAMES form.h HINTS ${CURSES_INCLUDE_PATH} ${CURSES_INCLUDE_PATH}/ncurses) + if(CURSES_FORM_INCLUDE_DIR) + target_include_directories(ccmake PRIVATE ${CURSES_FORM_INCLUDE_DIR}) + endif() target_link_libraries(ccmake ${CURSES_FORM_LIBRARY} ${CURSES_LIBRARY} diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index 7caed0c..ce32898 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -56,7 +56,8 @@ void onsig(int /*unused*/) cbreak(); /* nl- or cr not needed */ keypad(stdscr, true); /* Use key symbols as KEY_DOWN */ refresh(); - int x, y; + int x; + int y; getmaxyx(stdscr, y, x); cmCursesForm::CurrentForm->Render(1, 1, x, y); cmCursesForm::CurrentForm->UpdateStatusBar(); @@ -127,7 +128,8 @@ int main(int argc, char const* const* argv) signal(SIGWINCH, onsig); - int x, y; + int x; + int y; getmaxyx(stdscr, y, x); if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) { endwin(); diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx index c1dd591..f450a1c 100644 --- a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx +++ b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx @@ -11,6 +11,7 @@ #include "cmCursesWidget.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" @@ -49,7 +50,7 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite( switch (cm->GetState()->GetCacheEntryType(key)) { case cmStateEnums::BOOL: this->Entry = new cmCursesBoolWidget(this->EntryWidth, 1, 1, 1); - if (cmSystemTools::IsOn(value)) { + if (cmIsOn(value)) { static_cast<cmCursesBoolWidget*>(this->Entry)->SetValueAsBool(true); } else { static_cast<cmCursesBoolWidget*>(this->Entry)->SetValueAsBool(false); @@ -70,8 +71,7 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite( cmCursesOptionsWidget* ow = new cmCursesOptionsWidget(this->EntryWidth, 1, 1, 1); this->Entry = ow; - std::vector<std::string> options; - cmSystemTools::ExpandListArgument(stringsProp, options); + std::vector<std::string> options = cmExpandedList(stringsProp); for (auto const& opt : options) { ow->AddOption(opt); } diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx index 4e887d6..95026d5 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.cxx +++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx @@ -38,7 +38,8 @@ cmCursesLongMessageForm::~cmCursesLongMessageForm() void cmCursesLongMessageForm::UpdateStatusBar() { - int x, y; + int x; + int y; getmaxyx(stdscr, y, x); char bar[cmCursesMainForm::MAX_WIDTH]; @@ -81,7 +82,8 @@ void cmCursesLongMessageForm::UpdateStatusBar() void cmCursesLongMessageForm::PrintKeys() { - int x, y; + int x; + int y; getmaxyx(stdscr, y, x); if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) { return; @@ -98,7 +100,8 @@ void cmCursesLongMessageForm::PrintKeys() void cmCursesLongMessageForm::Render(int /*left*/, int /*top*/, int /*width*/, int /*height*/) { - int x, y; + int x; + int y; getmaxyx(stdscr, y, x); if (this->Form) { diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx index 028e852..1b25716 100644 --- a/Source/CursesDialog/cmCursesMainForm.cxx +++ b/Source/CursesDialog/cmCursesMainForm.cxx @@ -13,6 +13,7 @@ #include "cmCursesWidget.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVersion.h" #include "cmake.h" @@ -47,8 +48,8 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args, cmSystemTools::GetCMakeCursesCommand()); // create the arguments for the cmake object - std::string whereCMake = cmSystemTools::GetProgramPath(this->Args[0]); - whereCMake += "/cmake"; + std::string whereCMake = + cmStrCat(cmSystemTools::GetProgramPath(this->Args[0]), "/cmake"); this->Args[0] = whereCMake; this->CMakeInstance->SetArgs(this->Args); this->SearchString = ""; @@ -319,7 +320,8 @@ void cmCursesMainForm::Render(int left, int top, int width, int height) void cmCursesMainForm::PrintKeys(int process /* = 0 */) { - int x, y; + int x; + int y; getmaxyx(stdscr, y, x); if (x < cmCursesMainForm::MIN_WIDTH || x < this->InitialWidth || y < cmCursesMainForm::MIN_HEIGHT) { @@ -390,7 +392,8 @@ void cmCursesMainForm::PrintKeys(int process /* = 0 */) // on the status bar. Designed for a width of 80 chars. void cmCursesMainForm::UpdateStatusBar(const char* message) { - int x, y; + int x; + int y; getmaxyx(stdscr, y, x); // If window size is too small, display error and return if (x < cmCursesMainForm::MIN_WIDTH || x < this->InitialWidth || @@ -508,7 +511,8 @@ void cmCursesMainForm::UpdateProgress(const std::string& msg, float prog) int cmCursesMainForm::Configure(int noconfigure) { - int xi, yi; + int xi; + int yi; getmaxyx(stdscr, yi, xi); curses_move(1, 1); @@ -551,7 +555,8 @@ int cmCursesMainForm::Configure(int noconfigure) if (cmSystemTools::GetErrorOccuredFlag()) { this->OkToGenerate = false; } - int xx, yy; + int xx; + int yy; getmaxyx(stdscr, yy, xx); cmCursesLongMessageForm* msgs = new cmCursesLongMessageForm(this->Errors, @@ -580,7 +585,8 @@ int cmCursesMainForm::Configure(int noconfigure) int cmCursesMainForm::Generate() { - int xi, yi; + int xi; + int yi; getmaxyx(stdscr, yi, xi); curses_move(1, 1); @@ -609,7 +615,8 @@ int cmCursesMainForm::Generate() } // reset error condition cmSystemTools::ResetErrorOccuredFlag(); - int xx, yy; + int xx; + int yy; getmaxyx(stdscr, yy, xx); const char* title = "Messages during last pass."; if (cmSystemTools::GetErrorOccuredFlag()) { @@ -696,7 +703,7 @@ void cmCursesMainForm::FixValue(cmStateEnums::CacheEntryType type, cmSystemTools::ConvertToUnixSlashes(out); } if (type == cmStateEnums::BOOL) { - if (cmSystemTools::IsOff(out)) { + if (cmIsOff(out)) { out = "OFF"; } else { out = "ON"; @@ -706,7 +713,8 @@ void cmCursesMainForm::FixValue(cmStateEnums::CacheEntryType type, void cmCursesMainForm::HandleInput() { - int x = 0, y = 0; + int x = 0; + int y = 0; if (!this->Form) { return; diff --git a/Source/CursesDialog/cmCursesOptionsWidget.cxx b/Source/CursesDialog/cmCursesOptionsWidget.cxx index a8c4933..eb773ad 100644 --- a/Source/CursesDialog/cmCursesOptionsWidget.cxx +++ b/Source/CursesDialog/cmCursesOptionsWidget.cxx @@ -23,6 +23,9 @@ cmCursesOptionsWidget::cmCursesOptionsWidget(int width, int height, int left, bool cmCursesOptionsWidget::HandleInput(int& key, cmCursesMainForm* /*fm*/, WINDOW* w) { + if (this->Options.empty()) { + return false; + } switch (key) { case 10: // 10 == enter case KEY_ENTER: diff --git a/Source/CursesDialog/cmCursesStringWidget.cxx b/Source/CursesDialog/cmCursesStringWidget.cxx index 5e2a329..26724e7 100644 --- a/Source/CursesDialog/cmCursesStringWidget.cxx +++ b/Source/CursesDialog/cmCursesStringWidget.cxx @@ -64,7 +64,8 @@ void cmCursesStringWidget::OnType(int& key, cmCursesMainForm* fm, bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm, WINDOW* w) { - int x, y; + int x; + int y; FORM* form = fm->GetForm(); // when not in edit mode, edit mode is entered by pressing enter or i (vim @@ -179,7 +180,8 @@ const char* cmCursesStringWidget::GetValue() bool cmCursesStringWidget::PrintKeys() { - int x, y; + int x; + int y; getmaxyx(stdscr, y, x); if (x < cmCursesMainForm::MIN_WIDTH || y < cmCursesMainForm::MIN_HEIGHT) { return false; diff --git a/Source/LexerParser/cmCommandArgumentParser.cxx b/Source/LexerParser/cmCommandArgumentParser.cxx index b965b32..ae7fb42 100644 --- a/Source/LexerParser/cmCommandArgumentParser.cxx +++ b/Source/LexerParser/cmCommandArgumentParser.cxx @@ -1,8 +1,9 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.3.2. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,11 +41,14 @@ define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.0.4" +#define YYBISON_VERSION "3.3.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -67,8 +71,8 @@ #define yynerrs cmCommandArgument_yynerrs -/* Copy the first part of user declarations. */ -#line 1 "cmCommandArgumentParser.y" /* yacc.c:339 */ +/* First part of user prologue. */ +#line 1 "cmCommandArgumentParser.y" /* yacc.c:337 */ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ @@ -130,13 +134,16 @@ static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message); # pragma GCC diagnostic ignored "-Wconversion" #endif -#line 134 "cmCommandArgumentParser.cxx" /* yacc.c:339 */ - +#line 138 "cmCommandArgumentParser.cxx" /* yacc.c:337 */ # ifndef YY_NULLPTR -# if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULLPTR nullptr +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif # else -# define YY_NULLPTR 0 +# define YY_NULLPTR ((void*)0) # endif # endif @@ -201,9 +208,7 @@ int cmCommandArgument_yyparse (yyscan_t yyscanner); #endif /* !YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED */ -/* Copy the second part of user declarations. */ -#line 207 "cmCommandArgumentParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -224,13 +229,13 @@ typedef signed char yytype_int8; #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else -typedef unsigned short int yytype_uint16; +typedef unsigned short yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else -typedef short int yytype_int16; +typedef short yytype_int16; #endif #ifndef YYSIZE_T @@ -242,7 +247,7 @@ typedef short int yytype_int16; # include <stddef.h> /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else -# define YYSIZE_T unsigned int +# define YYSIZE_T unsigned # endif #endif @@ -278,15 +283,6 @@ typedef short int yytype_int16; # define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) #endif -#if !defined _Noreturn \ - && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) -# if defined _MSC_VER && 1200 <= _MSC_VER -# define _Noreturn __declspec (noreturn) -# else -# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) -# endif -#endif - /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(E) ((void) (E)) @@ -294,7 +290,7 @@ typedef short int yytype_int16; # define YYUSE(E) /* empty */ #endif -#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ @@ -456,16 +452,16 @@ union yyalloc /* YYNSTATES -- Number of states. */ #define YYNSTATES 33 -/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned - by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 269 +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ #define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, without out-of-bounds checking. */ + as returned by yylex. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -513,7 +509,7 @@ static const yytype_uint8 yyrline[] = static const char *const yytname[] = { "$end", "error", "$undefined", "cal_ENVCURLY", "cal_NCURLY", - "cal_DCURLY", "\"$\"", "\"{\"", "\"}\"", "cal_NAME", R"("\\")", + "cal_DCURLY", "\"$\"", "\"{\"", "\"}\"", "cal_NAME", "\"\\\\\"", "cal_SYMBOL", "\"@\"", "cal_ERROR", "cal_ATNAME", "$accept", "Start", "GoalWithOptionalBackSlash", "Goal", "String", "OuterText", "Variable", "EnvVarName", "MultipleIds", "ID", YY_NULLPTR @@ -633,22 +629,22 @@ static const yytype_uint8 yyr2[] = #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (yyscanner, YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (0) +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (yyscanner, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) /* Error token number */ #define YYTERROR 1 @@ -688,38 +684,38 @@ do { \ } while (0) -/*----------------------------------------. -| Print this symbol's value on YYOUTPUT. | -`----------------------------------------*/ +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) +yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { - FILE *yyo = yyoutput; - YYUSE (yyo); + FILE *yyoutput = yyo; + YYUSE (yyoutput); YYUSE (yyscanner); if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); + YYPRINT (yyo, yytoknum[yytype], *yyvaluep); # endif YYUSE (yytype); } -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) +yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { - YYFPRINTF (yyoutput, "%s %s (", + YYFPRINTF (yyo, "%s %s (", yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner); - YYFPRINTF (yyoutput, ")"); + yy_symbol_value_print (yyo, yytype, yyvaluep, yyscanner); + YYFPRINTF (yyo, ")"); } /*------------------------------------------------------------------. @@ -753,7 +749,7 @@ do { \ static void yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner) { - unsigned long int yylno = yyrline[yyrule]; + unsigned long yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", @@ -764,7 +760,7 @@ yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yysca YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yystos[yyssp[yyi + 1 - yynrhs]], - &(yyvsp[(yyi + 1) - (yynrhs)]) + &yyvsp[(yyi + 1) - (yynrhs)] , yyscanner); YYFPRINTF (stderr, "\n"); } @@ -868,7 +864,10 @@ yytnamerr (char *yyres, const char *yystr) case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; - /* Fall through. */ + else + goto append; + + append: default: if (yyres) yyres[yyn] = *yyp; @@ -886,7 +885,7 @@ yytnamerr (char *yyres, const char *yystr) if (! yyres) return yystrlen (yystr); - return yystpcpy (yyres, yystr) - yyres; + return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres); } # endif @@ -964,10 +963,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yyarg[yycount++] = yytname[yyx]; { YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else return 2; - yysize = yysize1; } } } @@ -979,6 +978,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, case N: \ yyformat = S; \ break + default: /* Avoid compiler warnings. */ YYCASE_(0, YY_("syntax error")); YYCASE_(1, YY_("syntax error, unexpected %s")); YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); @@ -990,9 +990,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, { YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else return 2; - yysize = yysize1; } if (*yymsg_alloc < yysize) @@ -1123,23 +1124,31 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yychar = YYEMPTY; /* Cause a token to be read. */ goto yysetstate; + /*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | +| yynewstate -- push a new state, which is found in yystate. | `------------------------------------------------------------*/ - yynewstate: +yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; - yysetstate: - *yyssp = yystate; + +/*--------------------------------------------------------------------. +| yynewstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + *yyssp = (yytype_int16) yystate; if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + goto yyexhaustedlab; +#else { /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; + YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1); -#ifdef yyoverflow +# if defined yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into @@ -1155,14 +1164,10 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); - yyss = yyss1; yyvs = yyvs1; } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else +# else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; @@ -1178,22 +1183,22 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); -# undef YYSTACK_RELOCATE +# undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif -#endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); + (unsigned long) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ YYDPRINTF ((stderr, "Entering state %d\n", yystate)); @@ -1202,11 +1207,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); goto yybackup; + /*-----------. | yybackup. | `-----------*/ yybackup: - /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ @@ -1279,7 +1284,7 @@ yydefault: /*-----------------------------. -| yyreduce -- Do a reduction. | +| yyreduce -- do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ @@ -1300,192 +1305,192 @@ yyreduce: switch (yyn) { case 2: -#line 99 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 99 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = 0; yyGetParser->SetResult((yyvsp[0].str)); } -#line 1309 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1314 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 3: -#line 105 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 105 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = (yyvsp[0].str); } -#line 1317 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1322 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 4: -#line 108 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 108 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1325 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1330 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 5: -#line 113 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 113 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = 0; } -#line 1333 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1338 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 6: -#line 116 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 116 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1341 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1346 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 7: -#line 121 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 121 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = (yyvsp[0].str); } -#line 1349 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1354 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 8: -#line 124 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 124 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = (yyvsp[0].str); } -#line 1357 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1362 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 9: -#line 129 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 129 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = (yyvsp[0].str); } -#line 1365 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1370 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 10: -#line 132 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 132 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = (yyvsp[0].str); } -#line 1373 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1378 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 11: -#line 135 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 135 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = (yyvsp[0].str); } -#line 1381 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1386 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 12: -#line 138 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 138 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = (yyvsp[0].str); } -#line 1389 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1394 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 13: -#line 141 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 141 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = (yyvsp[0].str); } -#line 1397 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1402 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 14: -#line 144 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 144 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = (yyvsp[0].str); } -#line 1405 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1410 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 15: -#line 149 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 149 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); } -#line 1413 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1418 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 16: -#line 152 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 152 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); } -#line 1421 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1426 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 17: -#line 155 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 155 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str)); } -#line 1429 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1434 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 18: -#line 158 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 158 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str)); } -#line 1437 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1442 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 19: -#line 163 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 163 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = (yyvsp[0].str); } -#line 1445 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1450 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 20: -#line 166 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 166 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = (yyvsp[-1].str); } -#line 1453 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1458 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 21: -#line 171 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 171 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = 0; } -#line 1461 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1466 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 22: -#line 174 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 174 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1469 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1474 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 23: -#line 179 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 179 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = (yyvsp[0].str); } -#line 1477 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1482 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; case 24: -#line 182 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 182 "cmCommandArgumentParser.y" /* yacc.c:1652 */ { (yyval.str) = (yyvsp[0].str); } -#line 1485 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1490 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ break; -#line 1489 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1494 "cmCommandArgumentParser.cxx" /* yacc.c:1652 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1510,14 +1515,13 @@ yyreduce: /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp + ? yytable[yyi] + : yydefgoto[yylhs]); + } goto yynewstate; @@ -1601,12 +1605,10 @@ yyerrlab: | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: - - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ @@ -1669,6 +1671,7 @@ yyacceptlab: yyresult = 0; goto yyreturn; + /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ @@ -1676,6 +1679,7 @@ yyabortlab: yyresult = 1; goto yyreturn; + #if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | @@ -1686,6 +1690,10 @@ yyexhaustedlab: /* Fall through. */ #endif + +/*-----------------------------------------------------. +| yyreturn -- parsing is finished, return the result. | +`-----------------------------------------------------*/ yyreturn: if (yychar != YYEMPTY) { @@ -1715,7 +1723,7 @@ yyreturn: #endif return yyresult; } -#line 187 "cmCommandArgumentParser.y" /* yacc.c:1906 */ +#line 187 "cmCommandArgumentParser.y" /* yacc.c:1918 */ /* End of grammar */ diff --git a/Source/LexerParser/cmCommandArgumentParserTokens.h b/Source/LexerParser/cmCommandArgumentParserTokens.h index 3172182..56c9794 100644 --- a/Source/LexerParser/cmCommandArgumentParserTokens.h +++ b/Source/LexerParser/cmCommandArgumentParserTokens.h @@ -1,8 +1,9 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.3.2. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,6 +31,9 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + #ifndef YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED # define YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED /* Debug traces. */ diff --git a/Source/LexerParser/cmDependsJavaParser.cxx b/Source/LexerParser/cmDependsJavaParser.cxx index e83afa9..6c1fb2c 100644 --- a/Source/LexerParser/cmDependsJavaParser.cxx +++ b/Source/LexerParser/cmDependsJavaParser.cxx @@ -1,8 +1,9 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.3.2. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,11 +41,14 @@ define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.0.4" +#define YYBISON_VERSION "3.3.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -67,8 +71,8 @@ #define yynerrs cmDependsJava_yynerrs -/* Copy the first part of user declarations. */ -#line 1 "cmDependsJavaParser.y" /* yacc.c:339 */ +/* First part of user prologue. */ +#line 1 "cmDependsJavaParser.y" /* yacc.c:337 */ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ @@ -119,13 +123,16 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); # pragma GCC diagnostic ignored "-Wconversion" #endif -#line 123 "cmDependsJavaParser.cxx" /* yacc.c:339 */ - +#line 127 "cmDependsJavaParser.cxx" /* yacc.c:337 */ # ifndef YY_NULLPTR -# if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULLPTR nullptr +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif # else -# define YY_NULLPTR 0 +# define YY_NULLPTR ((void*)0) # endif # endif @@ -372,9 +379,7 @@ int cmDependsJava_yyparse (yyscan_t yyscanner); #endif /* !YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED */ -/* Copy the second part of user declarations. */ -#line 378 "cmDependsJavaParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -395,13 +400,13 @@ typedef signed char yytype_int8; #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else -typedef unsigned short int yytype_uint16; +typedef unsigned short yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else -typedef short int yytype_int16; +typedef short yytype_int16; #endif #ifndef YYSIZE_T @@ -413,7 +418,7 @@ typedef short int yytype_int16; # include <stddef.h> /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else -# define YYSIZE_T unsigned int +# define YYSIZE_T unsigned # endif #endif @@ -449,15 +454,6 @@ typedef short int yytype_int16; # define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) #endif -#if !defined _Noreturn \ - && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) -# if defined _MSC_VER && 1200 <= _MSC_VER -# define _Noreturn __declspec (noreturn) -# else -# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) -# endif -#endif - /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(E) ((void) (E)) @@ -465,7 +461,7 @@ typedef short int yytype_int16; # define YYUSE(E) /* empty */ #endif -#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ @@ -627,16 +623,16 @@ union yyalloc /* YYNSTATES -- Number of states. */ #define YYNSTATES 575 -/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned - by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 360 +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ #define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, without out-of-bounds checking. */ + as returned by yylex. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -1618,22 +1614,22 @@ static const yytype_uint8 yyr2[] = #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (yyscanner, YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (0) +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (yyscanner, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) /* Error token number */ #define YYTERROR 1 @@ -1673,38 +1669,38 @@ do { \ } while (0) -/*----------------------------------------. -| Print this symbol's value on YYOUTPUT. | -`----------------------------------------*/ +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) +yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { - FILE *yyo = yyoutput; - YYUSE (yyo); + FILE *yyoutput = yyo; + YYUSE (yyoutput); YYUSE (yyscanner); if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); + YYPRINT (yyo, yytoknum[yytype], *yyvaluep); # endif YYUSE (yytype); } -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) +yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { - YYFPRINTF (yyoutput, "%s %s (", + YYFPRINTF (yyo, "%s %s (", yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner); - YYFPRINTF (yyoutput, ")"); + yy_symbol_value_print (yyo, yytype, yyvaluep, yyscanner); + YYFPRINTF (yyo, ")"); } /*------------------------------------------------------------------. @@ -1738,7 +1734,7 @@ do { \ static void yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner) { - unsigned long int yylno = yyrline[yyrule]; + unsigned long yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", @@ -1749,7 +1745,7 @@ yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yysca YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yystos[yyssp[yyi + 1 - yynrhs]], - &(yyvsp[(yyi + 1) - (yynrhs)]) + &yyvsp[(yyi + 1) - (yynrhs)] , yyscanner); YYFPRINTF (stderr, "\n"); } @@ -1853,7 +1849,10 @@ yytnamerr (char *yyres, const char *yystr) case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; - /* Fall through. */ + else + goto append; + + append: default: if (yyres) yyres[yyn] = *yyp; @@ -1871,7 +1870,7 @@ yytnamerr (char *yyres, const char *yystr) if (! yyres) return yystrlen (yystr); - return yystpcpy (yyres, yystr) - yyres; + return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres); } # endif @@ -1949,10 +1948,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yyarg[yycount++] = yytname[yyx]; { YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else return 2; - yysize = yysize1; } } } @@ -1964,6 +1963,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, case N: \ yyformat = S; \ break + default: /* Avoid compiler warnings. */ YYCASE_(0, YY_("syntax error")); YYCASE_(1, YY_("syntax error, unexpected %s")); YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); @@ -1975,9 +1975,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, { YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else return 2; - yysize = yysize1; } if (*yymsg_alloc < yysize) @@ -2108,23 +2109,31 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yychar = YYEMPTY; /* Cause a token to be read. */ goto yysetstate; + /*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | +| yynewstate -- push a new state, which is found in yystate. | `------------------------------------------------------------*/ - yynewstate: +yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; - yysetstate: - *yyssp = yystate; + +/*--------------------------------------------------------------------. +| yynewstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + *yyssp = (yytype_int16) yystate; if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + goto yyexhaustedlab; +#else { /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; + YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1); -#ifdef yyoverflow +# if defined yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into @@ -2140,14 +2149,10 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); - yyss = yyss1; yyvs = yyvs1; } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else +# else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; @@ -2163,22 +2168,22 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); -# undef YYSTACK_RELOCATE +# undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif -#endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); + (unsigned long) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ YYDPRINTF ((stderr, "Entering state %d\n", yystate)); @@ -2187,11 +2192,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); goto yybackup; + /*-----------. | yybackup. | `-----------*/ yybackup: - /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ @@ -2264,7 +2269,7 @@ yydefault: /*-----------------------------. -| yyreduce -- Do a reduction. | +| yyreduce -- do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ @@ -2285,214 +2290,214 @@ yyreduce: switch (yyn) { case 2: -#line 183 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 183 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2296 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2301 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 3: -#line 192 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 192 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2307 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2312 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 4: -#line 200 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 200 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2318 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2323 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 5: -#line 208 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 208 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2329 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2334 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 6: -#line 216 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 216 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2340 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2345 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 7: -#line 224 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 224 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2351 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2356 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 8: -#line 232 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 232 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2362 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2367 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 9: -#line 241 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 241 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2373 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2378 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 10: -#line 249 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 249 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2384 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2389 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 11: -#line 258 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 258 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2395 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2400 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 12: -#line 266 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 266 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2406 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2411 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 13: -#line 275 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 275 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); } -#line 2414 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2419 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 14: -#line 280 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 280 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); } -#line 2422 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2427 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 15: -#line 285 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 285 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); } -#line 2430 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2435 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 16: -#line 290 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 290 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); } -#line 2438 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2443 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 17: -#line 295 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 295 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); } -#line 2446 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2451 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 18: -#line 300 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 300 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); } -#line 2454 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2459 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 19: -#line 305 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 305 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); } -#line 2462 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2467 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 20: -#line 310 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 310 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); } -#line 2470 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2475 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 21: -#line 316 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 316 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2481 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2486 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 22: -#line 324 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 324 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2492 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2497 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 23: -#line 333 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 333 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpStoreClass((yyvsp[0].str)); @@ -2500,44 +2505,44 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2504 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2509 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 24: -#line 343 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 343 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2515 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2520 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 25: -#line 352 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 352 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2526 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2531 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 26: -#line 361 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 361 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2537 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2542 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 27: -#line 369 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 369 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpStoreClass((yyvsp[-1].str)); @@ -2545,56 +2550,56 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2549 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2554 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 28: -#line 379 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 379 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2558 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2563 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 29: -#line 385 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 385 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2567 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2572 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 30: -#line 392 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 392 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2576 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2581 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 31: -#line 399 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 399 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2585 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2590 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 32: -#line 405 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 405 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); (yyval.str) = (yyvsp[0].str); } -#line 2594 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2599 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 33: -#line 412 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 412 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); yyGetParser->AddClassFound((yyvsp[-2].str)); @@ -2602,11 +2607,11 @@ yyreduce: yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); (yyval.str) = const_cast<char*>(yyGetParser->GetCurrentCombine()); } -#line 2606 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2611 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 34: -#line 421 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 421 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -2615,11 +2620,11 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2619 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2624 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 35: -#line 431 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 431 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -2628,118 +2633,118 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2632 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2637 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 36: -#line 441 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 441 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2643 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2648 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 37: -#line 450 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 450 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2654 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2659 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 38: -#line 458 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 458 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2665 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2670 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 39: -#line 467 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 467 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2676 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2681 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 40: -#line 475 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 475 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2686 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2691 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 41: -#line 482 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 482 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2697 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2702 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 42: -#line 490 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 490 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2707 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2712 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 43: -#line 497 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 497 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2718 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2723 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 44: -#line 505 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 505 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2728 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2733 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 45: -#line 512 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 512 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2739 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2744 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 46: -#line 521 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 521 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); yyGetParser->SetCurrentPackage((yyvsp[-1].str)); @@ -2749,33 +2754,33 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2753 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2758 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 47: -#line 533 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 533 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2764 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2769 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 48: -#line 541 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 541 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2775 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2780 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 49: -#line 550 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 550 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); yyGetParser->AddPackagesImport((yyvsp[-1].str)); @@ -2785,11 +2790,11 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2789 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2794 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 50: -#line 562 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 562 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(5); std::string str = (yyvsp[-3].str); @@ -2800,77 +2805,77 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2804 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2809 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 51: -#line 575 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 575 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2815 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2820 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 52: -#line 583 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 583 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2826 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2831 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 53: -#line 591 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 591 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2837 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2842 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 54: -#line 600 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 600 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2848 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2853 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 55: -#line 608 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 608 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2859 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2864 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 67: -#line 623 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 623 "cmDependsJavaParser.y" /* yacc.c:1652 */ { yyGetParser->StartClass((yyvsp[0].str)); jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } -#line 2870 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2875 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 68: -#line 633 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 633 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -2878,11 +2883,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2882 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2887 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 69: -#line 642 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 642 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(2); @@ -2890,11 +2895,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2894 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2899 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 70: -#line 651 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 651 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -2902,11 +2907,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2906 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2911 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 71: -#line 660 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 660 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); jpCheckEmpty(4); @@ -2914,226 +2919,226 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2918 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2923 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 72: -#line 669 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 669 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2928 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2933 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 73: -#line 676 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 676 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2939 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2944 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 74: -#line 685 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 685 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2950 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2955 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 75: -#line 694 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 694 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2961 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2966 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 76: -#line 703 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 703 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2972 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2977 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 77: -#line 711 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 711 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2983 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2988 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 78: -#line 720 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 720 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2994 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2999 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 79: -#line 728 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 728 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3004 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3009 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 80: -#line 735 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 735 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3015 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3020 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 81: -#line 744 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 744 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3026 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3031 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 82: -#line 752 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 752 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3037 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3042 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 83: -#line 760 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 760 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3048 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3053 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 84: -#line 768 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 768 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3059 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3064 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 85: -#line 777 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 777 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3070 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3075 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 86: -#line 785 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 785 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3081 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3086 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 87: -#line 794 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 794 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); } -#line 3089 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3094 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 88: -#line 800 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 800 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3100 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3105 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 89: -#line 808 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 808 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3111 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3116 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 90: -#line 817 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 817 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3122 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3127 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 91: -#line 825 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 825 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3133 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3138 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 92: -#line 834 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 834 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -3141,77 +3146,77 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3145 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3150 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 93: -#line 843 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 843 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3156 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3161 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 94: -#line 852 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 852 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3167 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3172 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 95: -#line 860 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 860 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3178 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3183 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 96: -#line 869 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 869 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3189 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3194 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 97: -#line 877 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 877 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3200 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3205 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 98: -#line 885 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 885 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3211 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3216 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 99: -#line 894 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 894 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); jpCheckEmpty(4); @@ -3219,11 +3224,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3223 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3228 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 100: -#line 903 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 903 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); jpCheckEmpty(4); @@ -3231,22 +3236,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3235 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3240 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 101: -#line 912 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 912 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3246 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3251 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 102: -#line 920 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 920 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3254,11 +3259,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3258 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3263 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 103: -#line 930 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 930 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -3267,40 +3272,40 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3271 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3276 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 104: -#line 940 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 940 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); } -#line 3280 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3285 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 105: -#line 946 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 946 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3291 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3296 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 107: -#line 957 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 957 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); } -#line 3300 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3305 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 108: -#line 963 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 963 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3308,11 +3313,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3312 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3317 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 109: -#line 973 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 973 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3320,11 +3325,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3324 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3329 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 110: -#line 983 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 983 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3332,20 +3337,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3336 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3341 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 111: -#line 993 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 993 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); } -#line 3345 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3350 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 112: -#line 999 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 999 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3353,11 +3358,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3357 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3362 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 113: -#line 1009 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1009 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3365,11 +3370,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3369 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3374 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 114: -#line 1019 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1019 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3377,11 +3382,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3381 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3386 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 115: -#line 1029 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1029 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); jpCheckEmpty(4); @@ -3389,11 +3394,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3393 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3398 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 116: -#line 1038 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1038 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(5); jpCheckEmpty(5); @@ -3401,11 +3406,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3405 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3410 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 117: -#line 1048 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1048 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -3414,11 +3419,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3418 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3423 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 118: -#line 1059 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1059 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); jpCheckEmpty(4); @@ -3426,22 +3431,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3430 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3435 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 119: -#line 1068 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1068 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3441 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3446 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 120: -#line 1076 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1076 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3449,11 +3454,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3453 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3458 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 121: -#line 1086 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1086 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(5); jpCheckEmpty(5); @@ -3461,11 +3466,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3465 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3470 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 122: -#line 1095 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1095 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(5); jpCheckEmpty(5); @@ -3473,22 +3478,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3477 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3482 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 123: -#line 1105 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1105 "cmDependsJavaParser.y" /* yacc.c:1652 */ { yyGetParser->StartClass((yyvsp[0].str)); jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } -#line 3488 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3493 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 124: -#line 1114 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1114 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3496,21 +3501,21 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3500 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3505 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 125: -#line 1123 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1123 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3510 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3515 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 126: -#line 1130 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1130 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3518,11 +3523,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3522 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3527 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 127: -#line 1140 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1140 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3530,11 +3535,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3534 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3539 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 128: -#line 1149 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1149 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3542,11 +3547,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3546 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3551 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 129: -#line 1159 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1159 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3554,33 +3559,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3558 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3563 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 130: -#line 1168 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1168 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3569 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3574 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 131: -#line 1176 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1176 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3580 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3585 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 132: -#line 1185 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1185 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3588,11 +3593,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3592 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3597 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 133: -#line 1194 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1194 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3600,11 +3605,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3604 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3609 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 134: -#line 1203 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1203 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3612,22 +3617,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3616 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3621 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 135: -#line 1212 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1212 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3627 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3632 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 136: -#line 1220 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1220 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3635,22 +3640,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3639 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3644 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 137: -#line 1229 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1229 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3650 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3655 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 138: -#line 1238 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1238 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3658,11 +3663,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3662 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3667 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 139: -#line 1248 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1248 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3670,11 +3675,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3674 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3679 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 140: -#line 1258 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1258 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3682,11 +3687,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3686 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3691 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 141: -#line 1267 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1267 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3694,11 +3699,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3698 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3703 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 142: -#line 1277 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1277 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3706,22 +3711,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3710 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3715 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 143: -#line 1286 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1286 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3721 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3726 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 144: -#line 1294 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1294 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3729,11 +3734,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3733 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3738 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 145: -#line 1303 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1303 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3741,11 +3746,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3745 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3750 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 146: -#line 1313 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1313 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3753,11 +3758,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3757 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3762 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 147: -#line 1322 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1322 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3765,33 +3770,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3769 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3774 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 148: -#line 1332 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1332 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3780 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3785 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 149: -#line 1340 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1340 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3791 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3796 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 150: -#line 1348 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1348 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3799,11 +3804,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3803 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3808 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 151: -#line 1358 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1358 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3811,11 +3816,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3815 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3820 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 152: -#line 1367 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1367 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(2); @@ -3823,11 +3828,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3827 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3832 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 153: -#line 1377 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1377 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3835,11 +3840,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3839 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3844 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 154: -#line 1386 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1386 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3847,11 +3852,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3851 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3856 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 155: -#line 1395 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1395 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3859,11 +3864,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3863 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3868 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 156: -#line 1405 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1405 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(2); @@ -3871,11 +3876,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3875 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3880 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 157: -#line 1415 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1415 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(3); @@ -3883,11 +3888,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3887 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3892 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 158: -#line 1424 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1424 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(2); @@ -3895,11 +3900,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3899 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3904 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 159: -#line 1434 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1434 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3907,11 +3912,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3911 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3916 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 160: -#line 1443 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1443 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3919,11 +3924,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3923 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3928 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 161: -#line 1452 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1452 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3931,11 +3936,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3935 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3940 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 162: -#line 1461 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1461 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3943,11 +3948,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3947 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3952 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 163: -#line 1470 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1470 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3955,11 +3960,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3959 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3964 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 164: -#line 1479 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1479 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3967,11 +3972,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3971 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3976 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 165: -#line 1489 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1489 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3979,11 +3984,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3983 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3988 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 166: -#line 1498 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1498 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3991,11 +3996,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3995 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4000 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 167: -#line 1507 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1507 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4003,11 +4008,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4007 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4012 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 168: -#line 1516 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1516 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4015,11 +4020,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4019 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4024 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 169: -#line 1525 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1525 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4027,11 +4032,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4031 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4036 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 170: -#line 1535 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1535 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4039,11 +4044,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4043 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4048 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 171: -#line 1544 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1544 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4051,11 +4056,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4055 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4060 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 172: -#line 1553 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1553 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4063,11 +4068,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4067 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4072 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 173: -#line 1562 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1562 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4075,11 +4080,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4079 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4084 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 174: -#line 1571 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1571 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4087,11 +4092,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4091 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4096 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 175: -#line 1580 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1580 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4099,11 +4104,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4103 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4108 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 176: -#line 1589 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1589 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4111,11 +4116,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4115 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4120 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 177: -#line 1598 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1598 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4123,11 +4128,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4127 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4132 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 178: -#line 1607 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1607 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4135,11 +4140,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4139 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4144 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 179: -#line 1616 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1616 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4147,11 +4152,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4151 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4156 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 180: -#line 1625 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1625 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4159,11 +4164,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4163 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4168 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 181: -#line 1634 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1634 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4171,11 +4176,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4175 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4180 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 182: -#line 1644 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1644 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4183,11 +4188,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4187 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4192 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 183: -#line 1654 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1654 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); @@ -4196,11 +4201,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4200 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4205 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 184: -#line 1665 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1665 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4208,11 +4213,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4212 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4217 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 185: -#line 1675 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1675 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4220,11 +4225,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4224 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4229 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 186: -#line 1685 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1685 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4232,11 +4237,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4236 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4241 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 187: -#line 1694 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1694 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4244,11 +4249,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4248 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4253 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 188: -#line 1703 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1703 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4256,11 +4261,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4260 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4265 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 189: -#line 1712 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1712 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4268,11 +4273,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4272 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4277 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 190: -#line 1721 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1721 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4280,11 +4285,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4284 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4289 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 191: -#line 1730 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1730 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4292,11 +4297,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4296 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4301 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 192: -#line 1739 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1739 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4304,11 +4309,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4308 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4313 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 193: -#line 1749 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1749 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(5); jpCheckEmpty(5); @@ -4316,11 +4321,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4320 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4325 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 194: -#line 1759 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1759 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(7); jpCheckEmpty(7); @@ -4328,11 +4333,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4332 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4337 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 195: -#line 1769 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1769 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(7); jpCheckEmpty(7); @@ -4340,40 +4345,40 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4344 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4349 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 196: -#line 1779 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1779 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(5); } -#line 4353 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4358 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 197: -#line 1786 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1786 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); } -#line 4362 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4367 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 198: -#line 1792 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1792 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4373 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4378 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 199: -#line 1800 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1800 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4381,22 +4386,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4385 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4390 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 200: -#line 1809 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1809 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4396 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4401 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 201: -#line 1817 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1817 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4404,11 +4409,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4408 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4413 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 202: -#line 1827 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1827 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4416,11 +4421,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4420 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4425 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 203: -#line 1837 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1837 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4428,11 +4433,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4432 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4437 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 204: -#line 1846 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1846 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4440,11 +4445,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4444 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4449 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 205: -#line 1856 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1856 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4452,11 +4457,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4456 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4461 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 206: -#line 1865 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1865 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4464,58 +4469,58 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4468 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4473 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 207: -#line 1875 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1875 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(5); } -#line 4477 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4482 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 208: -#line 1882 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1882 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(5); } -#line 4486 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4491 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 209: -#line 1889 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1889 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(7); } -#line 4495 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4500 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 210: -#line 1897 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1897 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(9); } -#line 4504 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4509 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 211: -#line 1903 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1903 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4515 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4520 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 212: -#line 1911 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1911 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4523,22 +4528,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4527 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4532 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 213: -#line 1920 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1920 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4538 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4543 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 214: -#line 1928 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1928 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4546,33 +4551,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4550 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4555 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 215: -#line 1939 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1939 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(9); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4561 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4566 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 216: -#line 1947 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1947 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4572 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4577 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 217: -#line 1955 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1955 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4580,11 +4585,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4584 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4589 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 218: -#line 1965 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1965 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4592,11 +4597,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4596 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4601 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 219: -#line 1974 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1974 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4604,11 +4609,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4608 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4613 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 220: -#line 1984 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1984 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4616,11 +4621,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4620 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4625 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 221: -#line 1994 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1994 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4628,11 +4633,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4632 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4637 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 222: -#line 2003 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2003 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4640,11 +4645,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4644 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4649 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 223: -#line 2013 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2013 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4652,11 +4657,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4656 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4661 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 224: -#line 2022 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2022 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(5); jpCheckEmpty(5); @@ -4664,11 +4669,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4668 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4673 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 225: -#line 2032 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2032 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); @@ -4677,31 +4682,31 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4681 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4686 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 226: -#line 2042 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2042 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4692 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4697 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 227: -#line 2050 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2050 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); } -#line 4701 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4706 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 228: -#line 2057 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2057 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); @@ -4710,11 +4715,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4714 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4719 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 229: -#line 2068 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2068 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4722,11 +4727,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4726 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4731 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 230: -#line 2078 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2078 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4734,11 +4739,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4738 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4743 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 231: -#line 2088 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2088 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(5); jpCheckEmpty(5); @@ -4746,11 +4751,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4750 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4755 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 232: -#line 2098 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2098 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4758,11 +4763,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4762 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4767 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 233: -#line 2107 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2107 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); jpCheckEmpty(4); @@ -4770,22 +4775,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4774 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4779 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 234: -#line 2116 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2116 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4785 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4790 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 235: -#line 2124 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2124 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4793,11 +4798,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4797 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4802 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 236: -#line 2134 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2134 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4805,11 +4810,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4809 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4814 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 237: -#line 2143 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2143 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4817,20 +4822,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4821 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4826 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 238: -#line 2153 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2153 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(5); } -#line 4830 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4835 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 239: -#line 2160 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2160 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4838,11 +4843,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4842 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4847 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 240: -#line 2170 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2170 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4850,11 +4855,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4854 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4859 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 241: -#line 2179 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2179 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4862,11 +4867,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4866 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4871 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 242: -#line 2189 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2189 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4874,20 +4879,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4878 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4883 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 243: -#line 2198 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2198 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); } -#line 4887 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4892 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 244: -#line 2204 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2204 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4895,11 +4900,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4899 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4904 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 245: -#line 2213 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2213 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4907,11 +4912,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4911 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4916 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 246: -#line 2222 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2222 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4919,11 +4924,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4923 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4928 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 247: -#line 2231 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2231 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4931,11 +4936,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4935 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4940 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 248: -#line 2240 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2240 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4943,11 +4948,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4947 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4952 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 249: -#line 2250 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2250 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(6); jpCheckEmpty(6); @@ -4955,22 +4960,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4959 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4964 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 250: -#line 2259 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2259 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4970 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4975 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 251: -#line 2267 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2267 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4978,22 +4983,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4982 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4987 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 252: -#line 2276 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2276 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4993 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4998 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 253: -#line 2284 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2284 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5001,11 +5006,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5005 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5010 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 254: -#line 2294 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2294 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5013,11 +5018,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5017 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5022 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 255: -#line 2303 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2303 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5025,11 +5030,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5029 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5034 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 256: -#line 2313 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2313 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5037,11 +5042,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5041 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5046 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 257: -#line 2322 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2322 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5049,11 +5054,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5053 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5058 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 258: -#line 2331 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2331 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5061,11 +5066,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5065 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5070 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 259: -#line 2340 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2340 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5073,22 +5078,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5077 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5082 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 260: -#line 2349 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2349 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 5088 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5093 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 261: -#line 2357 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2357 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5096,11 +5101,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5100 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5105 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 262: -#line 2367 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2367 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5108,11 +5113,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5112 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5117 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 263: -#line 2376 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2376 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5120,11 +5125,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5124 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5129 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 264: -#line 2386 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2386 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5132,29 +5137,29 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5136 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5141 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 265: -#line 2396 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2396 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); } -#line 5145 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5150 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 266: -#line 2402 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2402 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); } -#line 5154 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5159 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 267: -#line 2409 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2409 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5163,11 +5168,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5167 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5172 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 268: -#line 2419 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2419 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5176,11 +5181,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5180 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5185 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 269: -#line 2429 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2429 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5189,11 +5194,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5193 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5198 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 270: -#line 2439 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2439 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5202,11 +5207,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5206 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5211 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 271: -#line 2450 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2450 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5215,11 +5220,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5219 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5224 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 272: -#line 2460 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2460 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-5].str))); @@ -5229,11 +5234,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5233 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5238 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 273: -#line 2471 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2471 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5242,11 +5247,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5246 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5251 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 274: -#line 2481 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2481 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5255,11 +5260,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5259 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5264 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 275: -#line 2492 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2492 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5268,11 +5273,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5272 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5277 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 276: -#line 2502 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2502 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5280,11 +5285,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5284 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5289 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 277: -#line 2512 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2512 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5292,11 +5297,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5296 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5301 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 278: -#line 2521 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2521 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5304,11 +5309,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5308 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5313 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 279: -#line 2530 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2530 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5316,11 +5321,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5320 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5325 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 280: -#line 2539 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2539 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5328,11 +5333,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5332 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5337 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 281: -#line 2548 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2548 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5340,11 +5345,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5344 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5349 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 282: -#line 2558 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2558 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5352,11 +5357,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5356 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5361 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 283: -#line 2568 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2568 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5364,11 +5369,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5368 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5373 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 284: -#line 2578 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2578 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5376,11 +5381,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5380 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5385 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 285: -#line 2587 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2587 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5388,11 +5393,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5392 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5397 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 286: -#line 2596 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2596 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5400,11 +5405,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5404 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5409 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 287: -#line 2605 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2605 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5412,11 +5417,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5416 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5421 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 288: -#line 2614 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2614 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5424,11 +5429,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5428 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5433 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 289: -#line 2624 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2624 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5436,11 +5441,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5440 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5445 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 290: -#line 2634 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2634 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5448,11 +5453,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5452 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5457 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 291: -#line 2644 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2644 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5460,11 +5465,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5464 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5469 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 292: -#line 2653 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2653 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5472,11 +5477,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5476 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5481 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 293: -#line 2662 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2662 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5484,11 +5489,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5488 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5493 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 294: -#line 2671 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2671 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5496,11 +5501,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5500 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5505 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 295: -#line 2681 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2681 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(5); jpCheckEmpty(5); @@ -5508,11 +5513,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5512 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5517 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 296: -#line 2690 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2690 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5520,20 +5525,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5524 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5529 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 297: -#line 2699 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2699 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(5); } -#line 5533 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5538 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 298: -#line 2706 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2706 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5541,11 +5546,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5545 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5550 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 299: -#line 2715 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2715 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5553,11 +5558,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5557 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5562 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 300: -#line 2724 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2724 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5565,11 +5570,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5569 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5574 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 301: -#line 2733 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2733 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5577,11 +5582,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5581 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5586 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 302: -#line 2743 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2743 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5589,11 +5594,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5593 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5598 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 303: -#line 2752 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2752 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5601,11 +5606,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5605 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5610 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 304: -#line 2761 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2761 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5613,11 +5618,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5617 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5622 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 305: -#line 2771 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2771 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5625,11 +5630,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5629 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5634 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 306: -#line 2780 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2780 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5637,11 +5642,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5641 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5646 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 307: -#line 2789 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2789 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5649,11 +5654,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5653 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5658 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 308: -#line 2798 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2798 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5661,11 +5666,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5665 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5670 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 309: -#line 2808 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2808 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5673,11 +5678,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5677 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5682 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 310: -#line 2817 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2817 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5685,11 +5690,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5689 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5694 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 311: -#line 2826 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2826 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5697,11 +5702,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5701 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5706 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 312: -#line 2835 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2835 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5709,11 +5714,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5713 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5718 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 313: -#line 2844 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2844 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5721,11 +5726,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5725 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5730 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 314: -#line 2853 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2853 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5733,11 +5738,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5737 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5742 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 315: -#line 2863 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2863 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5745,11 +5750,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5749 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5754 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 316: -#line 2872 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2872 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5757,11 +5762,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5761 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5766 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 317: -#line 2881 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2881 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5769,11 +5774,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5773 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5778 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 318: -#line 2891 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2891 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5781,11 +5786,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5785 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5790 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 319: -#line 2900 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2900 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5793,11 +5798,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5797 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5802 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 320: -#line 2910 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2910 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5805,11 +5810,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5809 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5814 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 321: -#line 2919 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2919 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5817,11 +5822,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5821 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5826 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 322: -#line 2929 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2929 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5829,11 +5834,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5833 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5838 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 323: -#line 2938 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2938 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5841,11 +5846,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5845 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5850 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 324: -#line 2948 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2948 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5853,11 +5858,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5857 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5862 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 325: -#line 2957 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2957 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5865,11 +5870,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5869 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5874 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 326: -#line 2967 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2967 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5877,11 +5882,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5881 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5886 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 327: -#line 2976 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2976 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5889,11 +5894,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5893 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5898 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 328: -#line 2986 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2986 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5901,11 +5906,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5905 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5910 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 329: -#line 2995 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2995 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(5); jpCheckEmpty(5); @@ -5913,11 +5918,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5917 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5922 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 330: -#line 3005 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3005 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5925,11 +5930,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5929 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5934 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 331: -#line 3014 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3014 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5937,11 +5942,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5941 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5946 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 332: -#line 3024 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3024 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5949,11 +5954,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5953 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5958 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 333: -#line 3034 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3034 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5962,11 +5967,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5966 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5971 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 334: -#line 3044 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3044 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5974,11 +5979,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5978 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5983 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 335: -#line 3053 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3053 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5986,11 +5991,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5990 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5995 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 336: -#line 3063 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3063 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5998,11 +6003,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6002 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6007 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 337: -#line 3072 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3072 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6010,11 +6015,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6014 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6019 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 338: -#line 3081 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3081 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6022,11 +6027,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6026 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6031 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 339: -#line 3090 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3090 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6034,11 +6039,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6038 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6043 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 340: -#line 3099 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3099 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6046,11 +6051,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6050 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6055 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 341: -#line 3108 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3108 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6058,11 +6063,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6062 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6067 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 342: -#line 3117 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3117 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6070,11 +6075,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6074 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6079 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 343: -#line 3126 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3126 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6082,11 +6087,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6086 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6091 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 344: -#line 3135 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3135 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6094,11 +6099,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6098 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6103 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 345: -#line 3144 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3144 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6106,11 +6111,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6110 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6115 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 346: -#line 3153 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3153 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6118,11 +6123,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6122 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6127 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 347: -#line 3162 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3162 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6130,11 +6135,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6134 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6139 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 348: -#line 3172 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3172 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6142,11 +6147,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6146 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6151 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 349: -#line 3182 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3182 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6154,11 +6159,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6158 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6163 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 350: -#line 3192 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3192 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6166,11 +6171,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6170 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6175 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; case 351: -#line 3201 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3201 "cmDependsJavaParser.y" /* yacc.c:1652 */ { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -6179,11 +6184,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6183 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6188 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ break; -#line 6187 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6192 "cmDependsJavaParser.cxx" /* yacc.c:1652 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -6208,14 +6213,13 @@ yyreduce: /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp + ? yytable[yyi] + : yydefgoto[yylhs]); + } goto yynewstate; @@ -6299,12 +6303,10 @@ yyerrlab: | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: - - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ @@ -6367,6 +6369,7 @@ yyacceptlab: yyresult = 0; goto yyreturn; + /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ @@ -6374,6 +6377,7 @@ yyabortlab: yyresult = 1; goto yyreturn; + #if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | @@ -6384,6 +6388,10 @@ yyexhaustedlab: /* Fall through. */ #endif + +/*-----------------------------------------------------. +| yyreturn -- parsing is finished, return the result. | +`-----------------------------------------------------*/ yyreturn: if (yychar != YYEMPTY) { @@ -6413,7 +6421,7 @@ yyreturn: #endif return yyresult; } -#line 3210 "cmDependsJavaParser.y" /* yacc.c:1906 */ +#line 3210 "cmDependsJavaParser.y" /* yacc.c:1918 */ /* End of grammar */ diff --git a/Source/LexerParser/cmDependsJavaParserTokens.h b/Source/LexerParser/cmDependsJavaParserTokens.h index 7f18f1d..6bbc084 100644 --- a/Source/LexerParser/cmDependsJavaParserTokens.h +++ b/Source/LexerParser/cmDependsJavaParserTokens.h @@ -1,8 +1,9 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.3.2. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,6 +31,9 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + #ifndef YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED # define YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED /* Debug traces. */ diff --git a/Source/LexerParser/cmExprParser.cxx b/Source/LexerParser/cmExprParser.cxx index 73ece2b..8416e72 100644 --- a/Source/LexerParser/cmExprParser.cxx +++ b/Source/LexerParser/cmExprParser.cxx @@ -1,8 +1,9 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.3.2. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,11 +41,14 @@ define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.0.4" +#define YYBISON_VERSION "3.3.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -67,8 +71,8 @@ #define yynerrs cmExpr_yynerrs -/* Copy the first part of user declarations. */ -#line 1 "cmExprParser.y" /* yacc.c:339 */ +/* First part of user prologue. */ +#line 1 "cmExprParser.y" /* yacc.c:337 */ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ @@ -112,13 +116,16 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message); # pragma GCC diagnostic ignored "-Wconversion" #endif -#line 116 "cmExprParser.cxx" /* yacc.c:339 */ - +#line 120 "cmExprParser.cxx" /* yacc.c:337 */ # ifndef YY_NULLPTR -# if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULLPTR nullptr +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif # else -# define YY_NULLPTR 0 +# define YY_NULLPTR ((void*)0) # endif # endif @@ -187,9 +194,7 @@ int cmExpr_yyparse (yyscan_t yyscanner); #endif /* !YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED */ -/* Copy the second part of user declarations. */ -#line 193 "cmExprParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -210,13 +215,13 @@ typedef signed char yytype_int8; #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else -typedef unsigned short int yytype_uint16; +typedef unsigned short yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else -typedef short int yytype_int16; +typedef short yytype_int16; #endif #ifndef YYSIZE_T @@ -228,7 +233,7 @@ typedef short int yytype_int16; # include <stddef.h> /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else -# define YYSIZE_T unsigned int +# define YYSIZE_T unsigned # endif #endif @@ -264,15 +269,6 @@ typedef short int yytype_int16; # define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) #endif -#if !defined _Noreturn \ - && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) -# if defined _MSC_VER && 1200 <= _MSC_VER -# define _Noreturn __declspec (noreturn) -# else -# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) -# endif -#endif - /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(E) ((void) (E)) @@ -280,7 +276,7 @@ typedef short int yytype_int16; # define YYUSE(E) /* empty */ #endif -#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ @@ -429,29 +425,29 @@ union yyalloc #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 17 +#define YYFINAL 19 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 30 +#define YYLAST 34 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 17 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 10 /* YYNRULES -- Number of rules. */ -#define YYNRULES 23 +#define YYNRULES 24 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 39 +#define YYNSTATES 41 -/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned - by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 271 +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ #define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, without out-of-bounds checking. */ + as returned by yylex. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -490,7 +486,7 @@ static const yytype_uint8 yyrline[] = { 0, 77, 77, 82, 85, 90, 93, 98, 101, 106, 109, 112, 117, 120, 123, 128, 131, 134, 140, 145, - 148, 151, 156, 159 + 148, 151, 154, 159, 162 }; #endif @@ -517,10 +513,10 @@ static const yytype_uint16 yytoknum[] = }; # endif -#define YYPACT_NINF -8 +#define YYPACT_NINF -11 #define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-8))) + (!!((Yystate) == (-11))) #define YYTABLE_NINF -1 @@ -531,10 +527,11 @@ static const yytype_uint16 yytoknum[] = STATE-NUM. */ static const yytype_int8 yypact[] = { - 0, 0, 0, 0, -8, 2, -7, -5, 8, 3, - 10, 1, -8, -8, -8, -8, 6, -8, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -8, -5, - 8, 3, 10, 10, 1, 1, -8, -8, -8 + 1, 1, 1, 1, 1, -11, 6, -10, -4, 9, + 4, 11, 2, -11, -11, -11, -11, 7, -11, -11, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + -11, -4, 9, 4, 11, 11, 2, 2, -11, -11, + -11 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -542,22 +539,23 @@ static const yytype_int8 yypact[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 0, 0, 0, 0, 22, 0, 2, 3, 5, 7, - 9, 12, 15, 19, 20, 21, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 23, 4, - 6, 8, 10, 11, 13, 14, 16, 17, 18 + 0, 0, 0, 0, 0, 23, 0, 2, 3, 5, + 7, 9, 12, 15, 19, 20, 21, 0, 22, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 24, 4, 6, 8, 10, 11, 13, 14, 16, 17, + 18 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { - -8, -8, 12, 5, 11, 9, -2, 4, -1, -8 + -11, -11, 22, 10, 8, 12, -3, -2, -1, -11 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 5, 6, 7, 8, 9, 10, 11, 12, 13 + -1, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -565,28 +563,29 @@ static const yytype_int8 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_uint8 yytable[] = { - 14, 15, 17, 1, 2, 18, 25, 26, 27, 19, - 3, 21, 22, 23, 24, 16, 4, 28, 18, 32, - 33, 20, 0, 29, 36, 37, 38, 34, 35, 31, - 30 + 15, 16, 20, 18, 1, 2, 19, 27, 28, 29, + 21, 3, 23, 24, 25, 26, 4, 5, 30, 20, + 34, 35, 22, 36, 37, 17, 38, 39, 40, 32, + 31, 0, 0, 0, 33 }; static const yytype_int8 yycheck[] = { - 1, 2, 0, 3, 4, 12, 5, 6, 7, 14, - 10, 8, 9, 3, 4, 3, 16, 11, 12, 21, - 22, 13, -1, 18, 25, 26, 27, 23, 24, 20, - 19 + 1, 2, 12, 4, 3, 4, 0, 5, 6, 7, + 14, 10, 8, 9, 3, 4, 15, 16, 11, 12, + 23, 24, 13, 25, 26, 3, 27, 28, 29, 21, + 20, -1, -1, -1, 22 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 3, 4, 10, 16, 18, 19, 20, 21, 22, - 23, 24, 25, 26, 25, 25, 19, 0, 12, 14, - 13, 8, 9, 3, 4, 5, 6, 7, 11, 20, - 21, 22, 23, 23, 24, 24, 25, 25, 25 + 0, 3, 4, 10, 15, 16, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 25, 25, 19, 25, 0, + 12, 14, 13, 8, 9, 3, 4, 5, 6, 7, + 11, 20, 21, 22, 23, 23, 24, 24, 25, 25, + 25 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ @@ -594,7 +593,7 @@ static const yytype_uint8 yyr1[] = { 0, 17, 18, 19, 19, 20, 20, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 24, 25, - 25, 25, 26, 26 + 25, 25, 25, 26, 26 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ @@ -602,7 +601,7 @@ static const yytype_uint8 yyr2[] = { 0, 2, 1, 1, 3, 1, 3, 1, 3, 1, 3, 3, 1, 3, 3, 1, 3, 3, 3, 1, - 2, 2, 1, 3 + 2, 2, 2, 1, 3 }; @@ -618,22 +617,22 @@ static const yytype_uint8 yyr2[] = #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (yyscanner, YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (0) +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (yyscanner, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) /* Error token number */ #define YYTERROR 1 @@ -673,38 +672,38 @@ do { \ } while (0) -/*----------------------------------------. -| Print this symbol's value on YYOUTPUT. | -`----------------------------------------*/ +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) +yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { - FILE *yyo = yyoutput; - YYUSE (yyo); + FILE *yyoutput = yyo; + YYUSE (yyoutput); YYUSE (yyscanner); if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); + YYPRINT (yyo, yytoknum[yytype], *yyvaluep); # endif YYUSE (yytype); } -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) +yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { - YYFPRINTF (yyoutput, "%s %s (", + YYFPRINTF (yyo, "%s %s (", yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner); - YYFPRINTF (yyoutput, ")"); + yy_symbol_value_print (yyo, yytype, yyvaluep, yyscanner); + YYFPRINTF (yyo, ")"); } /*------------------------------------------------------------------. @@ -738,7 +737,7 @@ do { \ static void yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner) { - unsigned long int yylno = yyrline[yyrule]; + unsigned long yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", @@ -749,7 +748,7 @@ yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yysca YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yystos[yyssp[yyi + 1 - yynrhs]], - &(yyvsp[(yyi + 1) - (yynrhs)]) + &yyvsp[(yyi + 1) - (yynrhs)] , yyscanner); YYFPRINTF (stderr, "\n"); } @@ -853,7 +852,10 @@ yytnamerr (char *yyres, const char *yystr) case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; - /* Fall through. */ + else + goto append; + + append: default: if (yyres) yyres[yyn] = *yyp; @@ -871,7 +873,7 @@ yytnamerr (char *yyres, const char *yystr) if (! yyres) return yystrlen (yystr); - return yystpcpy (yyres, yystr) - yyres; + return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres); } # endif @@ -949,10 +951,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yyarg[yycount++] = yytname[yyx]; { YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else return 2; - yysize = yysize1; } } } @@ -964,6 +966,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, case N: \ yyformat = S; \ break + default: /* Avoid compiler warnings. */ YYCASE_(0, YY_("syntax error")); YYCASE_(1, YY_("syntax error, unexpected %s")); YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); @@ -975,9 +978,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, { YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else return 2; - yysize = yysize1; } if (*yymsg_alloc < yysize) @@ -1108,23 +1112,31 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yychar = YYEMPTY; /* Cause a token to be read. */ goto yysetstate; + /*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | +| yynewstate -- push a new state, which is found in yystate. | `------------------------------------------------------------*/ - yynewstate: +yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; - yysetstate: - *yyssp = yystate; + +/*--------------------------------------------------------------------. +| yynewstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + *yyssp = (yytype_int16) yystate; if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + goto yyexhaustedlab; +#else { /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; + YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1); -#ifdef yyoverflow +# if defined yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into @@ -1140,14 +1152,10 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); - yyss = yyss1; yyvs = yyvs1; } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else +# else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; @@ -1163,22 +1171,22 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); -# undef YYSTACK_RELOCATE +# undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif -#endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); + (unsigned long) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ YYDPRINTF ((stderr, "Entering state %d\n", yystate)); @@ -1187,11 +1195,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); goto yybackup; + /*-----------. | yybackup. | `-----------*/ yybackup: - /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ @@ -1264,7 +1272,7 @@ yydefault: /*-----------------------------. -| yyreduce -- Do a reduction. | +| yyreduce -- do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ @@ -1285,186 +1293,194 @@ yyreduce: switch (yyn) { case 2: -#line 77 "cmExprParser.y" /* yacc.c:1646 */ +#line 77 "cmExprParser.y" /* yacc.c:1652 */ { cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number)); } -#line 1293 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1301 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 3: -#line 82 "cmExprParser.y" /* yacc.c:1646 */ +#line 82 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1301 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1309 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 4: -#line 85 "cmExprParser.y" /* yacc.c:1646 */ +#line 85 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number); } -#line 1309 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1317 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 5: -#line 90 "cmExprParser.y" /* yacc.c:1646 */ +#line 90 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1317 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1325 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 6: -#line 93 "cmExprParser.y" /* yacc.c:1646 */ +#line 93 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number); } -#line 1325 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1333 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 7: -#line 98 "cmExprParser.y" /* yacc.c:1646 */ +#line 98 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1333 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1341 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 8: -#line 101 "cmExprParser.y" /* yacc.c:1646 */ +#line 101 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number); } -#line 1341 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1349 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 9: -#line 106 "cmExprParser.y" /* yacc.c:1646 */ +#line 106 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1349 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1357 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 10: -#line 109 "cmExprParser.y" /* yacc.c:1646 */ +#line 109 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number); } -#line 1357 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1365 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 11: -#line 112 "cmExprParser.y" /* yacc.c:1646 */ +#line 112 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number); } -#line 1365 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1373 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 12: -#line 117 "cmExprParser.y" /* yacc.c:1646 */ +#line 117 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1373 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1381 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 13: -#line 120 "cmExprParser.y" /* yacc.c:1646 */ +#line 120 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number); } -#line 1381 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1389 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 14: -#line 123 "cmExprParser.y" /* yacc.c:1646 */ +#line 123 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number); } -#line 1389 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1397 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 15: -#line 128 "cmExprParser.y" /* yacc.c:1646 */ +#line 128 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1397 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1405 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 16: -#line 131 "cmExprParser.y" /* yacc.c:1646 */ +#line 131 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number); } -#line 1405 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1413 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 17: -#line 134 "cmExprParser.y" /* yacc.c:1646 */ +#line 134 "cmExprParser.y" /* yacc.c:1652 */ { if (yyvsp[0].Number == 0) { throw std::overflow_error("divide by zero"); } (yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number); } -#line 1416 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1424 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 18: -#line 140 "cmExprParser.y" /* yacc.c:1646 */ +#line 140 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number); } -#line 1424 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1432 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 19: -#line 145 "cmExprParser.y" /* yacc.c:1646 */ +#line 145 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1432 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1440 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 20: -#line 148 "cmExprParser.y" /* yacc.c:1646 */ +#line 148 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = + (yyvsp[0].Number); } -#line 1440 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1448 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 21: -#line 151 "cmExprParser.y" /* yacc.c:1646 */ +#line 151 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = - (yyvsp[0].Number); } -#line 1448 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1456 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 22: -#line 156 "cmExprParser.y" /* yacc.c:1646 */ +#line 154 "cmExprParser.y" /* yacc.c:1652 */ { - (yyval.Number) = (yyvsp[0].Number); + (yyval.Number) = ~ (yyvsp[0].Number); } -#line 1456 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1464 "cmExprParser.cxx" /* yacc.c:1652 */ break; case 23: -#line 159 "cmExprParser.y" /* yacc.c:1646 */ +#line 159 "cmExprParser.y" /* yacc.c:1652 */ + { + (yyval.Number) = (yyvsp[0].Number); + } +#line 1472 "cmExprParser.cxx" /* yacc.c:1652 */ + break; + + case 24: +#line 162 "cmExprParser.y" /* yacc.c:1652 */ { (yyval.Number) = (yyvsp[-1].Number); } -#line 1464 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1480 "cmExprParser.cxx" /* yacc.c:1652 */ break; -#line 1468 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1484 "cmExprParser.cxx" /* yacc.c:1652 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1489,14 +1505,13 @@ yyreduce: /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp + ? yytable[yyi] + : yydefgoto[yylhs]); + } goto yynewstate; @@ -1580,12 +1595,10 @@ yyerrlab: | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: - - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ @@ -1648,6 +1661,7 @@ yyacceptlab: yyresult = 0; goto yyreturn; + /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ @@ -1655,6 +1669,7 @@ yyabortlab: yyresult = 1; goto yyreturn; + #if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | @@ -1665,6 +1680,10 @@ yyexhaustedlab: /* Fall through. */ #endif + +/*-----------------------------------------------------. +| yyreturn -- parsing is finished, return the result. | +`-----------------------------------------------------*/ yyreturn: if (yychar != YYEMPTY) { @@ -1694,7 +1713,7 @@ yyreturn: #endif return yyresult; } -#line 164 "cmExprParser.y" /* yacc.c:1906 */ +#line 167 "cmExprParser.y" /* yacc.c:1918 */ /* End of grammar */ diff --git a/Source/LexerParser/cmExprParser.y b/Source/LexerParser/cmExprParser.y index 2137473..7ae2118 100644 --- a/Source/LexerParser/cmExprParser.y +++ b/Source/LexerParser/cmExprParser.y @@ -151,6 +151,9 @@ unary: | exp_MINUS unary { $<Number>$ = - $<Number>2; } +| exp_NOT unary { + $<Number>$ = ~ $<Number>2; + } factor: exp_NUMBER { diff --git a/Source/LexerParser/cmExprParserTokens.h b/Source/LexerParser/cmExprParserTokens.h index 84b2bbd..5ffd7c5 100644 --- a/Source/LexerParser/cmExprParserTokens.h +++ b/Source/LexerParser/cmExprParserTokens.h @@ -1,8 +1,9 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.3.2. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,6 +31,9 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + #ifndef YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED # define YY_CMEXPR_YY_CMEXPRPARSERTOKENS_H_INCLUDED /* Debug traces. */ diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx index 015cab9..2ca7927 100644 --- a/Source/LexerParser/cmFortranParser.cxx +++ b/Source/LexerParser/cmFortranParser.cxx @@ -1,8 +1,9 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.3.2. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,11 +41,14 @@ define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "3.0.4" +#define YYBISON_VERSION "3.3.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -67,8 +71,8 @@ #define yynerrs cmFortran_yynerrs -/* Copy the first part of user declarations. */ -#line 1 "cmFortranParser.y" /* yacc.c:339 */ +/* First part of user prologue. */ +#line 1 "cmFortranParser.y" /* yacc.c:337 */ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ @@ -131,13 +135,16 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message) # pragma GCC diagnostic ignored "-Wconversion" #endif -#line 135 "cmFortranParser.cxx" /* yacc.c:339 */ - +#line 139 "cmFortranParser.cxx" /* yacc.c:337 */ # ifndef YY_NULLPTR -# if defined __cplusplus && 201103L <= __cplusplus -# define YY_NULLPTR nullptr +# if defined __cplusplus +# if 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif # else -# define YY_NULLPTR 0 +# define YY_NULLPTR ((void*)0) # endif # endif @@ -251,11 +258,11 @@ extern int cmFortran_yydebug; union YYSTYPE { -#line 73 "cmFortranParser.y" /* yacc.c:355 */ +#line 73 "cmFortranParser.y" /* yacc.c:352 */ char* string; -#line 259 "cmFortranParser.cxx" /* yacc.c:355 */ +#line 266 "cmFortranParser.cxx" /* yacc.c:352 */ }; typedef union YYSTYPE YYSTYPE; @@ -269,9 +276,7 @@ int cmFortran_yyparse (yyscan_t yyscanner); #endif /* !YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED */ -/* Copy the second part of user declarations. */ -#line 275 "cmFortranParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -292,13 +297,13 @@ typedef signed char yytype_int8; #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else -typedef unsigned short int yytype_uint16; +typedef unsigned short yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else -typedef short int yytype_int16; +typedef short yytype_int16; #endif #ifndef YYSIZE_T @@ -310,7 +315,7 @@ typedef short int yytype_int16; # include <stddef.h> /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else -# define YYSIZE_T unsigned int +# define YYSIZE_T unsigned # endif #endif @@ -346,15 +351,6 @@ typedef short int yytype_int16; # define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) #endif -#if !defined _Noreturn \ - && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) -# if defined _MSC_VER && 1200 <= _MSC_VER -# define _Noreturn __declspec (noreturn) -# else -# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) -# endif -#endif - /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(E) ((void) (E)) @@ -362,7 +358,7 @@ typedef short int yytype_int16; # define YYUSE(E) /* empty */ #endif -#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ @@ -524,16 +520,16 @@ union yyalloc /* YYNSTATES -- Number of states. */ #define YYNSTATES 126 -/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned - by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 295 +/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, with out-of-bounds checking. */ #define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, without out-of-bounds checking. */ + as returned by yylex. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -863,22 +859,22 @@ static const yytype_uint8 yyr2[] = #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (yyscanner, YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (0) +#define YYBACKUP(Token, Value) \ + do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (yyscanner, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ + while (0) /* Error token number */ #define YYTERROR 1 @@ -918,38 +914,38 @@ do { \ } while (0) -/*----------------------------------------. -| Print this symbol's value on YYOUTPUT. | -`----------------------------------------*/ +/*-----------------------------------. +| Print this symbol's value on YYO. | +`-----------------------------------*/ static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) +yy_symbol_value_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { - FILE *yyo = yyoutput; - YYUSE (yyo); + FILE *yyoutput = yyo; + YYUSE (yyoutput); YYUSE (yyscanner); if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); + YYPRINT (yyo, yytoknum[yytype], *yyvaluep); # endif YYUSE (yytype); } -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ +/*---------------------------. +| Print this symbol on YYO. | +`---------------------------*/ static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) +yy_symbol_print (FILE *yyo, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { - YYFPRINTF (yyoutput, "%s %s (", + YYFPRINTF (yyo, "%s %s (", yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner); - YYFPRINTF (yyoutput, ")"); + yy_symbol_value_print (yyo, yytype, yyvaluep, yyscanner); + YYFPRINTF (yyo, ")"); } /*------------------------------------------------------------------. @@ -983,7 +979,7 @@ do { \ static void yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner) { - unsigned long int yylno = yyrline[yyrule]; + unsigned long yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", @@ -994,7 +990,7 @@ yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yysca YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yystos[yyssp[yyi + 1 - yynrhs]], - &(yyvsp[(yyi + 1) - (yynrhs)]) + &yyvsp[(yyi + 1) - (yynrhs)] , yyscanner); YYFPRINTF (stderr, "\n"); } @@ -1098,7 +1094,10 @@ yytnamerr (char *yyres, const char *yystr) case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; - /* Fall through. */ + else + goto append; + + append: default: if (yyres) yyres[yyn] = *yyp; @@ -1116,7 +1115,7 @@ yytnamerr (char *yyres, const char *yystr) if (! yyres) return yystrlen (yystr); - return yystpcpy (yyres, yystr) - yyres; + return (YYSIZE_T) (yystpcpy (yyres, yystr) - yyres); } # endif @@ -1194,10 +1193,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yyarg[yycount++] = yytname[yyx]; { YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else return 2; - yysize = yysize1; } } } @@ -1209,6 +1208,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, case N: \ yyformat = S; \ break + default: /* Avoid compiler warnings. */ YYCASE_(0, YY_("syntax error")); YYCASE_(1, YY_("syntax error, unexpected %s")); YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); @@ -1220,9 +1220,10 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, { YYSIZE_T yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) + yysize = yysize1; + else return 2; - yysize = yysize1; } if (*yymsg_alloc < yysize) @@ -1353,23 +1354,31 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); yychar = YYEMPTY; /* Cause a token to be read. */ goto yysetstate; + /*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | +| yynewstate -- push a new state, which is found in yystate. | `------------------------------------------------------------*/ - yynewstate: +yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; - yysetstate: - *yyssp = yystate; + +/*--------------------------------------------------------------------. +| yynewstate -- set current state (the top of the stack) to yystate. | +`--------------------------------------------------------------------*/ +yysetstate: + *yyssp = (yytype_int16) yystate; if (yyss + yystacksize - 1 <= yyssp) +#if !defined yyoverflow && !defined YYSTACK_RELOCATE + goto yyexhaustedlab; +#else { /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; + YYSIZE_T yysize = (YYSIZE_T) (yyssp - yyss + 1); -#ifdef yyoverflow +# if defined yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into @@ -1385,14 +1394,10 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); - yyss = yyss1; yyvs = yyvs1; } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else +# else /* defined YYSTACK_RELOCATE */ /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; @@ -1408,22 +1413,22 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); -# undef YYSTACK_RELOCATE +# undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif -#endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); + (unsigned long) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } +#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ YYDPRINTF ((stderr, "Entering state %d\n", yystate)); @@ -1432,11 +1437,11 @@ YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); goto yybackup; + /*-----------. | yybackup. | `-----------*/ yybackup: - /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ @@ -1509,7 +1514,7 @@ yydefault: /*-----------------------------. -| yyreduce -- Do a reduction. | +| yyreduce -- do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ @@ -1530,26 +1535,26 @@ yyreduce: switch (yyn) { case 4: -#line 104 "cmFortranParser.y" /* yacc.c:1646 */ +#line 104 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); } -#line 1539 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1544 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 5: -#line 108 "cmFortranParser.y" /* yacc.c:1646 */ +#line 108 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1549 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1554 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 6: -#line 113 "cmFortranParser.y" /* yacc.c:1646 */ +#line 113 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 && @@ -1559,22 +1564,22 @@ yyreduce: } free((yyvsp[-2].string)); } -#line 1563 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1568 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 7: -#line 122 "cmFortranParser.y" /* yacc.c:1646 */ +#line 122 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleSubmodule(parser, (yyvsp[-4].string), (yyvsp[-2].string)); free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1574 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1579 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 8: -#line 128 "cmFortranParser.y" /* yacc.c:1646 */ +#line 128 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string)); @@ -1582,40 +1587,40 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1586 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1591 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 9: -#line 135 "cmFortranParser.y" /* yacc.c:1646 */ +#line 135 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); free((yyvsp[-2].string)); } -#line 1596 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1601 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 10: -#line 140 "cmFortranParser.y" /* yacc.c:1646 */ +#line 140 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, false); } -#line 1605 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1610 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 11: -#line 144 "cmFortranParser.y" /* yacc.c:1646 */ +#line 144 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1615 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1620 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 12: -#line 149 "cmFortranParser.y" /* yacc.c:1646 */ +#line 149 "cmFortranParser.y" /* yacc.c:1652 */ { if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); @@ -1624,139 +1629,139 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1628 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1633 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 13: -#line 157 "cmFortranParser.y" /* yacc.c:1646 */ +#line 157 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1638 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1643 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 14: -#line 162 "cmFortranParser.y" /* yacc.c:1646 */ +#line 162 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1648 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1653 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 15: -#line 167 "cmFortranParser.y" /* yacc.c:1646 */ +#line 167 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1658 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1663 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 16: -#line 172 "cmFortranParser.y" /* yacc.c:1646 */ +#line 172 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1668 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1673 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 17: -#line 177 "cmFortranParser.y" /* yacc.c:1646 */ +#line 177 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleDefine(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1678 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1683 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 18: -#line 182 "cmFortranParser.y" /* yacc.c:1646 */ +#line 182 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1688 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1693 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 19: -#line 187 "cmFortranParser.y" /* yacc.c:1646 */ +#line 187 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1698 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1703 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 20: -#line 192 "cmFortranParser.y" /* yacc.c:1646 */ +#line 192 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1708 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1713 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 21: -#line 197 "cmFortranParser.y" /* yacc.c:1646 */ +#line 197 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIf(parser); } -#line 1717 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1722 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 22: -#line 201 "cmFortranParser.y" /* yacc.c:1646 */ +#line 201 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElif(parser); } -#line 1726 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1731 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 23: -#line 205 "cmFortranParser.y" /* yacc.c:1646 */ +#line 205 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElse(parser); } -#line 1735 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1740 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 24: -#line 209 "cmFortranParser.y" /* yacc.c:1646 */ +#line 209 "cmFortranParser.y" /* yacc.c:1652 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleEndif(parser); } -#line 1744 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1749 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 48: -#line 231 "cmFortranParser.y" /* yacc.c:1646 */ +#line 231 "cmFortranParser.y" /* yacc.c:1652 */ { free ((yyvsp[0].string)); } -#line 1750 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1755 "cmFortranParser.cxx" /* yacc.c:1652 */ break; case 55: -#line 238 "cmFortranParser.y" /* yacc.c:1646 */ +#line 238 "cmFortranParser.y" /* yacc.c:1652 */ { free ((yyvsp[0].string)); } -#line 1756 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1761 "cmFortranParser.cxx" /* yacc.c:1652 */ break; -#line 1760 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1765 "cmFortranParser.cxx" /* yacc.c:1652 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1781,14 +1786,13 @@ yyreduce: /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; + { + const int yylhs = yyr1[yyn] - YYNTOKENS; + const int yyi = yypgoto[yylhs] + *yyssp; + yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp + ? yytable[yyi] + : yydefgoto[yylhs]); + } goto yynewstate; @@ -1872,12 +1876,10 @@ yyerrlab: | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: - - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; + /* Pacify compilers when the user code never invokes YYERROR and the + label yyerrorlab therefore never appears in user code. */ + if (0) + YYERROR; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ @@ -1940,6 +1942,7 @@ yyacceptlab: yyresult = 0; goto yyreturn; + /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ @@ -1947,6 +1950,7 @@ yyabortlab: yyresult = 1; goto yyreturn; + #if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | @@ -1957,6 +1961,10 @@ yyexhaustedlab: /* Fall through. */ #endif + +/*-----------------------------------------------------. +| yyreturn -- parsing is finished, return the result. | +`-----------------------------------------------------*/ yyreturn: if (yychar != YYEMPTY) { @@ -1986,6 +1994,6 @@ yyreturn: #endif return yyresult; } -#line 249 "cmFortranParser.y" /* yacc.c:1906 */ +#line 249 "cmFortranParser.y" /* yacc.c:1918 */ /* End of grammar */ diff --git a/Source/LexerParser/cmFortranParserTokens.h b/Source/LexerParser/cmFortranParserTokens.h index 29c6d60..0da4c1c 100644 --- a/Source/LexerParser/cmFortranParserTokens.h +++ b/Source/LexerParser/cmFortranParserTokens.h @@ -1,8 +1,9 @@ -/* A Bison parser, made by GNU Bison 3.0.4. */ +/* A Bison parser, made by GNU Bison 3.3.2. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, + Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,6 +31,9 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ +/* Undocumented macros, especially those whose name start with YY_, + are private implementation details. Do not rely on them. */ + #ifndef YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED # define YY_CMFORTRAN_YY_CMFORTRANPARSERTOKENS_H_INCLUDED /* Debug traces. */ @@ -130,11 +134,11 @@ extern int cmFortran_yydebug; union YYSTYPE { -#line 73 "cmFortranParser.y" /* yacc.c:1909 */ +#line 73 "cmFortranParser.y" /* yacc.c:1921 */ char* string; -#line 138 "cmFortranParserTokens.h" /* yacc.c:1909 */ +#line 142 "cmFortranParserTokens.h" /* yacc.c:1921 */ }; typedef union YYSTYPE YYSTYPE; diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx index c9ebba8..287a482 100644 --- a/Source/QtDialog/CMakeSetup.cxx +++ b/Source/QtDialog/CMakeSetup.cxx @@ -6,6 +6,7 @@ #include "cmAlgorithms.h" #include "cmDocumentation.h" #include "cmDocumentationEntry.h" +#include "cmStringAlgorithms.h" #include "cmVersion.h" #include "cmake.h" #include "cmsys/CommandLineArguments.hxx" diff --git a/Source/QtDialog/FirstConfigure.cxx b/Source/QtDialog/FirstConfigure.cxx index 364a378..d9a8aff 100644 --- a/Source/QtDialog/FirstConfigure.cxx +++ b/Source/QtDialog/FirstConfigure.cxx @@ -2,6 +2,7 @@ #include "FirstConfigure.h" #include "Compilers.h" +#include "cmStringAlgorithms.h" #include <QComboBox> #include <QRadioButton> @@ -183,10 +184,9 @@ void StartCompilerSetup::onGeneratorChanged(QString const& name) if (GeneratorsSupportingPlatform.contains(name)) { // Change the label title to include the default platform - std::string label = "Optional platform for generator"; - label += "(if empty, generator uses: "; - label += this->GeneratorDefaultPlatform[name].toStdString(); - label += ")"; + std::string label = + cmStrCat("Optional platform for generator(if empty, generator uses: ", + this->GeneratorDefaultPlatform[name].toStdString(), ')'); this->PlatformLabel->setText(tr(label.c_str())); // Regenerate the list of supported platform diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index f357f90..ece3307 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -7,6 +7,7 @@ #include "cmExternalMakefileProjectGenerator.h" #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #ifdef Q_OS_WIN @@ -312,7 +313,7 @@ QCMakePropertyList QCMake::properties() const prop.Advanced = state->GetCacheEntryPropertyAsBool(key, "ADVANCED"); if (t == cmStateEnums::BOOL) { prop.Type = QCMakeProperty::BOOL; - prop.Value = cmSystemTools::IsOn(cachedValue); + prop.Value = cmIsOn(cachedValue); } else if (t == cmStateEnums::PATH) { prop.Type = QCMakeProperty::PATH; } else if (t == cmStateEnums::FILEPATH) { diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx index 78a2710..5e8636a 100644 --- a/Source/QtDialog/QCMakeCacheView.cxx +++ b/Source/QtDialog/QCMakeCacheView.cxx @@ -210,7 +210,8 @@ void QCMakeCacheModel::clear() void QCMakeCacheModel::setProperties(const QCMakePropertyList& props) { - QSet<QCMakeProperty> newProps, newProps2; + QSet<QCMakeProperty> newProps; + QSet<QCMakeProperty> newProps2; if (this->ShowNewProperties) { newProps = props.toSet(); diff --git a/Source/cmAddCompileDefinitionsCommand.cxx b/Source/cmAddCompileDefinitionsCommand.cxx index 0474819..b00a4a7 100644 --- a/Source/cmAddCompileDefinitionsCommand.cxx +++ b/Source/cmAddCompileDefinitionsCommand.cxx @@ -2,19 +2,15 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAddCompileDefinitionsCommand.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" -class cmExecutionStatus; - -bool cmAddCompileDefinitionsCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmAddCompileDefinitionsCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { - if (args.empty()) { - return true; - } - + cmMakefile& mf = status.GetMakefile(); for (std::string const& i : args) { - this->Makefile->AddCompileDefinition(i); + mf.AddCompileDefinition(i); } return true; } diff --git a/Source/cmAddCompileDefinitionsCommand.h b/Source/cmAddCompileDefinitionsCommand.h index e985dca..4bd621c 100644 --- a/Source/cmAddCompileDefinitionsCommand.h +++ b/Source/cmAddCompileDefinitionsCommand.h @@ -8,24 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -class cmAddCompileDefinitionsCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmAddCompileDefinitionsCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmAddCompileDefinitionsCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmAddCompileOptionsCommand.cxx b/Source/cmAddCompileOptionsCommand.cxx index 412fb38..8ccb512 100644 --- a/Source/cmAddCompileOptionsCommand.cxx +++ b/Source/cmAddCompileOptionsCommand.cxx @@ -2,19 +2,15 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAddCompileOptionsCommand.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" -class cmExecutionStatus; - -bool cmAddCompileOptionsCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmAddCompileOptionsCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { - if (args.empty()) { - return true; - } - + cmMakefile& mf = status.GetMakefile(); for (std::string const& i : args) { - this->Makefile->AddCompileOption(i); + mf.AddCompileOption(i); } return true; } diff --git a/Source/cmAddCompileOptionsCommand.h b/Source/cmAddCompileOptionsCommand.h index 3d53d09..b172412 100644 --- a/Source/cmAddCompileOptionsCommand.h +++ b/Source/cmAddCompileOptionsCommand.h @@ -8,24 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -class cmAddCompileOptionsCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmAddCompileOptionsCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmAddCompileOptionsCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx index 0be3c85..d2330e1 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -8,33 +8,44 @@ #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" +#include "cmExecutionStatus.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" #include "cmSourceFile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" -class cmExecutionStatus; +static bool cmAddCustomCommandCommandCheckOutputs( + const std::vector<std::string>& outputs, cmExecutionStatus& status); -// cmAddCustomCommandCommand -bool cmAddCustomCommandCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmAddCustomCommandCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { /* Let's complain at the end of this function about the lack of a particular arg. For the moment, let's say that COMMAND, and either TARGET or SOURCE are required. */ if (args.size() < 4) { - this->SetError("called with wrong number of arguments."); + status.SetError("called with wrong number of arguments."); return false; } - std::string source, target, main_dependency, working, depfile, job_pool; + cmMakefile& mf = status.GetMakefile(); + std::string source; + std::string target; + std::string main_dependency; + std::string working; + std::string depfile; + std::string job_pool; std::string comment_buffer; const char* comment = nullptr; - std::vector<std::string> depends, outputs, output, byproducts; + std::vector<std::string> depends; + std::vector<std::string> outputs; + std::vector<std::string> output; + std::vector<std::string> byproducts; bool verbatim = false; bool append = false; bool uses_terminal = false; @@ -95,30 +106,29 @@ bool cmAddCustomCommandCommand::InitialPass( MAKE_STATIC_KEYWORD(VERBATIM); MAKE_STATIC_KEYWORD(WORKING_DIRECTORY); #undef MAKE_STATIC_KEYWORD - static std::unordered_set<std::string> keywords; - if (keywords.empty()) { - keywords.insert(keyAPPEND); - keywords.insert(keyARGS); - keywords.insert(keyBYPRODUCTS); - keywords.insert(keyCOMMAND); - keywords.insert(keyCOMMAND_EXPAND_LISTS); - keywords.insert(keyCOMMENT); - keywords.insert(keyDEPENDS); - keywords.insert(keyDEPFILE); - keywords.insert(keyIMPLICIT_DEPENDS); - keywords.insert(keyJOB_POOL); - keywords.insert(keyMAIN_DEPENDENCY); - keywords.insert(keyOUTPUT); - keywords.insert(keyOUTPUTS); - keywords.insert(keyPOST_BUILD); - keywords.insert(keyPRE_BUILD); - keywords.insert(keyPRE_LINK); - keywords.insert(keySOURCE); - keywords.insert(keyTARGET); - keywords.insert(keyUSES_TERMINAL); - keywords.insert(keyVERBATIM); - keywords.insert(keyWORKING_DIRECTORY); - } + static std::unordered_set<std::string> const keywords{ + keyAPPEND, + keyARGS, + keyBYPRODUCTS, + keyCOMMAND, + keyCOMMAND_EXPAND_LISTS, + keyCOMMENT, + keyDEPENDS, + keyDEPFILE, + keyIMPLICIT_DEPENDS, + keyJOB_POOL, + keyMAIN_DEPENDENCY, + keyOUTPUT, + keyOUTPUTS, + keyPOST_BUILD, + keyPRE_BUILD, + keyPRE_LINK, + keySOURCE, + keyTARGET, + keyUSES_TERMINAL, + keyVERBATIM, + keyWORKING_DIRECTORY + }; for (std::string const& copy : args) { if (keywords.count(copy)) { @@ -168,9 +178,9 @@ bool cmAddCustomCommandCommand::InitialPass( doing = doing_comment; } else if (copy == keyDEPFILE) { doing = doing_depfile; - if (this->Makefile->GetGlobalGenerator()->GetName() != "Ninja") { - this->SetError("Option DEPFILE not supported by " + - this->Makefile->GetGlobalGenerator()->GetName()); + if (mf.GetGlobalGenerator()->GetName() != "Ninja") { + status.SetError("Option DEPFILE not supported by " + + mf.GetGlobalGenerator()->GetName()); return false; } } else if (copy == keyJOB_POOL) { @@ -193,8 +203,7 @@ bool cmAddCustomCommandCommand::InitialPass( // and later references "${CMAKE_CURRENT_SOURCE_DIR}/out.txt". // This is fairly obscure so we can wait for someone to // complain. - filename = this->Makefile->GetCurrentBinaryDirectory(); - filename += "/"; + filename = cmStrCat(mf.GetCurrentBinaryDirectory(), '/'); } filename += copy; cmSystemTools::ConvertToUnixSlashes(filename); @@ -270,7 +279,7 @@ bool cmAddCustomCommandCommand::InitialPass( comment = comment_buffer.c_str(); break; default: - this->SetError("Wrong syntax. Unknown type of argument."); + status.SetError("Wrong syntax. Unknown type of argument."); return false; } } @@ -285,31 +294,31 @@ bool cmAddCustomCommandCommand::InitialPass( // At this point we could complain about the lack of arguments. For // the moment, let's say that COMMAND, TARGET are always required. if (output.empty() && target.empty()) { - this->SetError("Wrong syntax. A TARGET or OUTPUT must be specified."); + status.SetError("Wrong syntax. A TARGET or OUTPUT must be specified."); return false; } if (source.empty() && !target.empty() && !output.empty()) { - this->SetError( + status.SetError( "Wrong syntax. A TARGET and OUTPUT can not both be specified."); return false; } if (append && output.empty()) { - this->SetError("given APPEND option with no OUTPUT."); + status.SetError("given APPEND option with no OUTPUT."); return false; } // Make sure the output names and locations are safe. - if (!this->CheckOutputs(output) || !this->CheckOutputs(outputs) || - !this->CheckOutputs(byproducts)) { + if (!cmAddCustomCommandCommandCheckOutputs(output, status) || + !cmAddCustomCommandCommandCheckOutputs(outputs, status) || + !cmAddCustomCommandCommandCheckOutputs(byproducts, status)) { return false; } // Check for an append request. if (append) { // Lookup an existing command. - if (cmSourceFile* sf = - this->Makefile->GetSourceFileWithOutput(output[0])) { + if (cmSourceFile* sf = mf.GetSourceFileWithOutput(output[0])) { if (cmCustomCommand* cc = sf->GetCustomCommand()) { cc->AppendCommands(commandLines); cc->AppendDepends(depends); @@ -322,12 +331,12 @@ bool cmAddCustomCommandCommand::InitialPass( std::ostringstream e; e << "given APPEND option with output\n\"" << output[0] << "\"\nwhich is not already a custom command output."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } if (uses_terminal && !job_pool.empty()) { - this->SetError("JOB_POOL is shadowed by USES_TERMINAL."); + status.SetError("JOB_POOL is shadowed by USES_TERMINAL."); return false; } @@ -336,22 +345,21 @@ bool cmAddCustomCommandCommand::InitialPass( if (source.empty() && output.empty()) { // Source is empty, use the target. std::vector<std::string> no_depends; - this->Makefile->AddCustomCommandToTarget( - target, byproducts, no_depends, commandLines, cctype, comment, - working.c_str(), escapeOldStyle, uses_terminal, depfile, job_pool, - command_expand_lists); + mf.AddCustomCommandToTarget(target, byproducts, no_depends, commandLines, + cctype, comment, working.c_str(), + escapeOldStyle, uses_terminal, depfile, + job_pool, command_expand_lists); } else if (target.empty()) { // Target is empty, use the output. - this->Makefile->AddCustomCommandToOutput( - output, byproducts, depends, main_dependency, commandLines, comment, - working.c_str(), false, escapeOldStyle, uses_terminal, - command_expand_lists, depfile, job_pool); + mf.AddCustomCommandToOutput(output, byproducts, depends, main_dependency, + commandLines, comment, working.c_str(), false, + escapeOldStyle, uses_terminal, + command_expand_lists, depfile, job_pool); // Add implicit dependency scanning requests if any were given. if (!implicit_depends.empty()) { bool okay = false; - if (cmSourceFile* sf = - this->Makefile->GetSourceFileWithOutput(output[0])) { + if (cmSourceFile* sf = mf.GetSourceFileWithOutput(output[0])) { if (cmCustomCommand* cc = sf->GetCustomCommand()) { okay = true; cc->SetImplicitDepends(implicit_depends); @@ -361,21 +369,21 @@ bool cmAddCustomCommandCommand::InitialPass( std::ostringstream e; e << "could not locate source file with a custom command producing \"" << output[0] << "\" even though this command tried to create it!"; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } } else if (!byproducts.empty()) { - this->SetError("BYPRODUCTS may not be specified with SOURCE signatures"); + status.SetError("BYPRODUCTS may not be specified with SOURCE signatures"); return false; } else if (uses_terminal) { - this->SetError("USES_TERMINAL may not be used with SOURCE signatures"); + status.SetError("USES_TERMINAL may not be used with SOURCE signatures"); return false; } else { bool issueMessage = true; std::ostringstream e; MessageType messageType = MessageType::AUTHOR_WARNING; - switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0050)) { + switch (mf.GetPolicyStatus(cmPolicies::CMP0050)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0050) << "\n"; break; @@ -392,30 +400,31 @@ bool cmAddCustomCommandCommand::InitialPass( if (issueMessage) { e << "The SOURCE signatures of add_custom_command are no longer " "supported."; - this->Makefile->IssueMessage(messageType, e.str()); + mf.IssueMessage(messageType, e.str()); if (messageType == MessageType::FATAL_ERROR) { return false; } } // Use the old-style mode for backward compatibility. - this->Makefile->AddCustomCommandOldStyle(target, outputs, depends, source, - commandLines, comment); + mf.AddCustomCommandOldStyle(target, outputs, depends, source, commandLines, + comment); } return true; } -bool cmAddCustomCommandCommand::CheckOutputs( - const std::vector<std::string>& outputs) +bool cmAddCustomCommandCommandCheckOutputs( + const std::vector<std::string>& outputs, cmExecutionStatus& status) { + cmMakefile& mf = status.GetMakefile(); for (std::string const& o : outputs) { // Make sure the file will not be generated into the source // directory during an out of source build. - if (!this->Makefile->CanIWriteThisFile(o)) { + if (!mf.CanIWriteThisFile(o)) { std::string e = "attempted to have a file \"" + o + "\" in a source directory as an output of custom command."; - this->SetError(e); + status.SetError(e); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -426,7 +435,7 @@ bool cmAddCustomCommandCommand::CheckOutputs( std::ostringstream msg; msg << "called with OUTPUT containing a \"" << o[pos] << "\". This character is not allowed."; - this->SetError(msg.str()); + status.SetError(msg.str()); return false; } } diff --git a/Source/cmAddCustomCommandCommand.h b/Source/cmAddCustomCommandCommand.h index 6af4f10..4f8c58f 100644 --- a/Source/cmAddCustomCommandCommand.h +++ b/Source/cmAddCustomCommandCommand.h @@ -8,33 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmAddCustomCommandCommand - * \brief cmAddCustomCommandCommand defines a new command (rule) that can - * be executed within the build process - * - */ - -class cmAddCustomCommandCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmAddCustomCommandCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -protected: - bool CheckOutputs(const std::vector<std::string>& outputs); -}; +bool cmAddCustomCommandCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx index 0ecd5f5..caea510 100644 --- a/Source/cmAddCustomTargetCommand.cxx +++ b/Source/cmAddCustomTargetCommand.cxx @@ -6,25 +6,25 @@ #include <utility> #include "cmCustomCommandLines.h" +#include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" -class cmExecutionStatus; - -// cmAddCustomTargetCommand -bool cmAddCustomTargetCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmAddCustomTargetCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } + cmMakefile& mf = status.GetMakefile(); std::string const& targetName = args[0]; // Check the target name. @@ -33,7 +33,7 @@ bool cmAddCustomTargetCommand::InitialPass( e << "called with invalid target name \"" << targetName << "\". Target names may not contain a slash. " << "Use ADD_CUSTOM_COMMAND to generate files."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } @@ -44,7 +44,8 @@ bool cmAddCustomTargetCommand::InitialPass( cmCustomCommandLines commandLines; // Accumulate dependencies. - std::vector<std::string> depends, byproducts; + std::vector<std::string> depends; + std::vector<std::string> byproducts; std::string working_directory; bool verbatim = false; bool uses_terminal = false; @@ -122,8 +123,7 @@ bool cmAddCustomTargetCommand::InitialPass( case doing_byproducts: { std::string filename; if (!cmSystemTools::FileIsFullPath(copy)) { - filename = this->Makefile->GetCurrentBinaryDirectory(); - filename += "/"; + filename = cmStrCat(mf.GetCurrentBinaryDirectory(), '/'); } filename += copy; cmSystemTools::ConvertToUnixSlashes(filename); @@ -145,7 +145,7 @@ bool cmAddCustomTargetCommand::InitialPass( job_pool = copy; break; default: - this->SetError("Wrong syntax. Unknown type of argument."); + status.SetError("Wrong syntax. Unknown type of argument."); return false; } } @@ -156,7 +156,7 @@ bool cmAddCustomTargetCommand::InitialPass( std::ostringstream msg; msg << "called with target name containing a \"" << targetName[pos] << "\". This character is not allowed."; - this->SetError(msg.str()); + status.SetError(msg.str()); return false; } @@ -168,8 +168,7 @@ bool cmAddCustomTargetCommand::InitialPass( if (nameOk) { nameOk = targetName.find(':') == std::string::npos; } - if (!nameOk && - !this->Makefile->CheckCMP0037(targetName, cmStateEnums::UTILITY)) { + if (!nameOk && !mf.CheckCMP0037(targetName, cmStateEnums::UTILITY)) { return false; } @@ -182,39 +181,37 @@ bool cmAddCustomTargetCommand::InitialPass( // Enforce name uniqueness. { std::string msg; - if (!this->Makefile->EnforceUniqueName(targetName, msg, true)) { - this->SetError(msg); + if (!mf.EnforceUniqueName(targetName, msg, true)) { + status.SetError(msg); return false; } } if (commandLines.empty() && !byproducts.empty()) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "BYPRODUCTS may not be specified without any COMMAND"); + mf.IssueMessage(MessageType::FATAL_ERROR, + "BYPRODUCTS may not be specified without any COMMAND"); return true; } if (commandLines.empty() && uses_terminal) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "USES_TERMINAL may not be specified without any COMMAND"); + mf.IssueMessage(MessageType::FATAL_ERROR, + "USES_TERMINAL may not be specified without any COMMAND"); return true; } if (commandLines.empty() && command_expand_lists) { - this->Makefile->IssueMessage( + mf.IssueMessage( MessageType::FATAL_ERROR, "COMMAND_EXPAND_LISTS may not be specified without any COMMAND"); return true; } if (uses_terminal && !job_pool.empty()) { - this->SetError("JOB_POOL is shadowed by USES_TERMINAL."); + status.SetError("JOB_POOL is shadowed by USES_TERMINAL."); return false; } // Add the utility target to the makefile. bool escapeOldStyle = !verbatim; - cmTarget* target = this->Makefile->AddUtilityCommand( + cmTarget* target = mf.AddUtilityCommand( targetName, cmMakefile::TargetOrigin::Project, excludeFromAll, working_directory.c_str(), byproducts, depends, commandLines, escapeOldStyle, comment, uses_terminal, command_expand_lists, job_pool); diff --git a/Source/cmAddCustomTargetCommand.h b/Source/cmAddCustomTargetCommand.h index 1a55116..e23ef9f 100644 --- a/Source/cmAddCustomTargetCommand.h +++ b/Source/cmAddCustomTargetCommand.h @@ -8,31 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmAddCustomTargetCommand - * \brief Command that adds a target to the build system. - * - * cmAddCustomTargetCommand adds an extra target to the build system. - * This is useful when you would like to add special - * targets like "install,", "clean," and so on. - */ -class cmAddCustomTargetCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmAddCustomTargetCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmAddCustomTargetCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmAddDefinitionsCommand.cxx b/Source/cmAddDefinitionsCommand.cxx index 62e57a3..0b10aee 100644 --- a/Source/cmAddDefinitionsCommand.cxx +++ b/Source/cmAddDefinitionsCommand.cxx @@ -2,21 +2,15 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAddDefinitionsCommand.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" -class cmExecutionStatus; - -// cmAddDefinitionsCommand -bool cmAddDefinitionsCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmAddDefinitionsCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { - // it is OK to have no arguments - if (args.empty()) { - return true; - } - + cmMakefile& mf = status.GetMakefile(); for (std::string const& i : args) { - this->Makefile->AddDefineFlag(i); + mf.AddDefineFlag(i); } return true; } diff --git a/Source/cmAddDefinitionsCommand.h b/Source/cmAddDefinitionsCommand.h index 7b75638..a67f095 100644 --- a/Source/cmAddDefinitionsCommand.h +++ b/Source/cmAddDefinitionsCommand.h @@ -8,30 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmAddDefinitionsCommand - * \brief Specify a list of compiler defines - * - * cmAddDefinitionsCommand specifies a list of compiler defines. These defines - * will be added to the compile command. - */ -class cmAddDefinitionsCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmAddDefinitionsCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmAddDefinitionsCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmAddDependenciesCommand.cxx b/Source/cmAddDependenciesCommand.cxx index 4956a47..0ddbda8 100644 --- a/Source/cmAddDependenciesCommand.cxx +++ b/Source/cmAddDependenciesCommand.cxx @@ -4,34 +4,33 @@ #include <sstream> +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmRange.h" #include "cmTarget.h" -class cmExecutionStatus; - -// cmDependenciesCommand -bool cmAddDependenciesCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmAddDependenciesCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 2) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } + cmMakefile& mf = status.GetMakefile(); std::string const& target_name = args[0]; - if (this->Makefile->IsAlias(target_name)) { + if (mf.IsAlias(target_name)) { std::ostringstream e; e << "Cannot add target-level dependencies to alias target \"" << target_name << "\".\n"; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + mf.IssueMessage(MessageType::FATAL_ERROR, e.str()); } - if (cmTarget* target = this->Makefile->FindTargetToUse(target_name)) { + if (cmTarget* target = mf.FindTargetToUse(target_name)) { // skip over target_name for (std::string const& arg : cmMakeRange(args).advance(1)) { - target->AddUtility(arg, this->Makefile); + target->AddUtility(arg, &mf); } } else { std::ostringstream e; @@ -41,7 +40,7 @@ bool cmAddDependenciesCommand::InitialPass( << "by the add_executable, add_library, or add_custom_target commands. " << "If you want to add file-level dependencies see the DEPENDS option " << "of the add_custom_target and add_custom_command commands."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + mf.IssueMessage(MessageType::FATAL_ERROR, e.str()); } return true; diff --git a/Source/cmAddDependenciesCommand.h b/Source/cmAddDependenciesCommand.h index e10df71..0c60e3a 100644 --- a/Source/cmAddDependenciesCommand.h +++ b/Source/cmAddDependenciesCommand.h @@ -8,29 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmAddDependenciesCommand - * \brief Add a dependency to a target - * - * cmAddDependenciesCommand adds a dependency to a target - */ -class cmAddDependenciesCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmAddDependenciesCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmAddDependenciesCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx index 5685fdf..f1264d5 100644 --- a/Source/cmAddExecutableCommand.cxx +++ b/Source/cmAddExecutableCommand.cxx @@ -4,22 +4,22 @@ #include <sstream> +#include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmStateTypes.h" #include "cmTarget.h" -class cmExecutionStatus; - -// cmExecutableCommand -bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmAddExecutableCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } + + cmMakefile& mf = status.GetMakefile(); std::vector<std::string>::const_iterator s = args.begin(); std::string const& exename = *s; @@ -61,59 +61,56 @@ bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args, if (nameOk && !importTarget && !isAlias) { nameOk = exename.find(':') == std::string::npos; } - if (!nameOk && - !this->Makefile->CheckCMP0037(exename, cmStateEnums::EXECUTABLE)) { + if (!nameOk && !mf.CheckCMP0037(exename, cmStateEnums::EXECUTABLE)) { return false; } // Special modifiers are not allowed with IMPORTED signature. if (importTarget && (use_win32 || use_macbundle || excludeFromAll)) { if (use_win32) { - this->SetError("may not be given WIN32 for an IMPORTED target."); + status.SetError("may not be given WIN32 for an IMPORTED target."); } else if (use_macbundle) { - this->SetError("may not be given MACOSX_BUNDLE for an IMPORTED target."); + status.SetError( + "may not be given MACOSX_BUNDLE for an IMPORTED target."); } else // if(excludeFromAll) { - this->SetError( + status.SetError( "may not be given EXCLUDE_FROM_ALL for an IMPORTED target."); } return false; } if (isAlias) { if (!cmGeneratorExpression::IsValidTargetName(exename)) { - this->SetError("Invalid name for ALIAS: " + exename); + status.SetError("Invalid name for ALIAS: " + exename); return false; } if (excludeFromAll) { - this->SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense."); + status.SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense."); return false; } if (importTarget || importGlobal) { - this->SetError("IMPORTED with ALIAS is not allowed."); + status.SetError("IMPORTED with ALIAS is not allowed."); return false; } if (args.size() != 3) { - std::ostringstream e; - e << "ALIAS requires exactly one target argument."; - this->SetError(e.str()); + status.SetError("ALIAS requires exactly one target argument."); return false; } std::string const& aliasedName = *s; - if (this->Makefile->IsAlias(aliasedName)) { + if (mf.IsAlias(aliasedName)) { std::ostringstream e; e << "cannot create ALIAS target \"" << exename << "\" because target \"" << aliasedName << "\" is itself an ALIAS."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } - cmTarget* aliasedTarget = - this->Makefile->FindTargetToUse(aliasedName, true); + cmTarget* aliasedTarget = mf.FindTargetToUse(aliasedName, true); if (!aliasedTarget) { std::ostringstream e; e << "cannot create ALIAS target \"" << exename << "\" because target \"" << aliasedName << "\" does not already exist."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } cmStateEnums::TargetType type = aliasedTarget->GetType(); @@ -121,7 +118,7 @@ bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args, std::ostringstream e; e << "cannot create ALIAS target \"" << exename << "\" because target \"" << aliasedName << "\" is not an executable."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } if (aliasedTarget->IsImported() && @@ -129,42 +126,40 @@ bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args, std::ostringstream e; e << "cannot create ALIAS target \"" << exename << "\" because target \"" << aliasedName << "\" is imported but not globally visible."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } - this->Makefile->AddAlias(exename, aliasedName); + mf.AddAlias(exename, aliasedName); return true; } // Handle imported target creation. if (importTarget) { // Make sure the target does not already exist. - if (this->Makefile->FindTargetToUse(exename)) { + if (mf.FindTargetToUse(exename)) { std::ostringstream e; e << "cannot create imported target \"" << exename << "\" because another target with the same name already exists."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } // Create the imported target. - this->Makefile->AddImportedTarget(exename, cmStateEnums::EXECUTABLE, - importGlobal); + mf.AddImportedTarget(exename, cmStateEnums::EXECUTABLE, importGlobal); return true; } // Enforce name uniqueness. { std::string msg; - if (!this->Makefile->EnforceUniqueName(exename, msg)) { - this->SetError(msg); + if (!mf.EnforceUniqueName(exename, msg)) { + status.SetError(msg); return false; } } std::vector<std::string> srclists(s, args.end()); - cmTarget* tgt = - this->Makefile->AddExecutable(exename, srclists, excludeFromAll); + cmTarget* tgt = mf.AddExecutable(exename, srclists, excludeFromAll); if (use_win32) { tgt->SetProperty("WIN32_EXECUTABLE", "ON"); } diff --git a/Source/cmAddExecutableCommand.h b/Source/cmAddExecutableCommand.h index bdf607d..f7bc273 100644 --- a/Source/cmAddExecutableCommand.h +++ b/Source/cmAddExecutableCommand.h @@ -8,30 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmExecutablesCommand - * \brief Defines a list of executables to build. - * - * cmExecutablesCommand defines a list of executable (i.e., test) - * programs to create. - */ -class cmAddExecutableCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmAddExecutableCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmAddExecutableCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index ad12e89..c067aea 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -5,30 +5,29 @@ #include <sstream> #include "cmAlgorithms.h" +#include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmState.h" #include "cmStateTypes.h" -#include "cmSystemTools.h" +#include "cmStringAlgorithms.h" #include "cmTarget.h" -class cmExecutionStatus; - -// cmLibraryCommand -bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmAddLibraryCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } + + cmMakefile& mf = status.GetMakefile(); // Library type defaults to value of BUILD_SHARED_LIBS, if it exists, // otherwise it defaults to static library. cmStateEnums::TargetType type = cmStateEnums::SHARED_LIBRARY; - if (cmSystemTools::IsOff( - this->Makefile->GetDefinition("BUILD_SHARED_LIBS"))) { + if (cmIsOff(mf.GetDefinition("BUILD_SHARED_LIBS"))) { type = cmStateEnums::STATIC_LIBRARY; } bool excludeFromAll = false; @@ -50,9 +49,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, std::string libType = *s; if (libType == "STATIC") { if (type == cmStateEnums::INTERFACE_LIBRARY) { - std::ostringstream e; - e << "INTERFACE library specified with conflicting STATIC type."; - this->SetError(e.str()); + status.SetError( + "INTERFACE library specified with conflicting STATIC type."); return false; } ++s; @@ -60,9 +58,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, haveSpecifiedType = true; } else if (libType == "SHARED") { if (type == cmStateEnums::INTERFACE_LIBRARY) { - std::ostringstream e; - e << "INTERFACE library specified with conflicting SHARED type."; - this->SetError(e.str()); + status.SetError( + "INTERFACE library specified with conflicting SHARED type."); return false; } ++s; @@ -70,9 +67,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, haveSpecifiedType = true; } else if (libType == "MODULE") { if (type == cmStateEnums::INTERFACE_LIBRARY) { - std::ostringstream e; - e << "INTERFACE library specified with conflicting MODULE type."; - this->SetError(e.str()); + status.SetError( + "INTERFACE library specified with conflicting MODULE type."); return false; } ++s; @@ -80,9 +76,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, haveSpecifiedType = true; } else if (libType == "OBJECT") { if (type == cmStateEnums::INTERFACE_LIBRARY) { - std::ostringstream e; - e << "INTERFACE library specified with conflicting OBJECT type."; - this->SetError(e.str()); + status.SetError( + "INTERFACE library specified with conflicting OBJECT type."); return false; } ++s; @@ -90,9 +85,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, haveSpecifiedType = true; } else if (libType == "UNKNOWN") { if (type == cmStateEnums::INTERFACE_LIBRARY) { - std::ostringstream e; - e << "INTERFACE library specified with conflicting UNKNOWN type."; - this->SetError(e.str()); + status.SetError( + "INTERFACE library specified with conflicting UNKNOWN type."); return false; } ++s; @@ -100,30 +94,26 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, haveSpecifiedType = true; } else if (libType == "ALIAS") { if (type == cmStateEnums::INTERFACE_LIBRARY) { - std::ostringstream e; - e << "INTERFACE library specified with conflicting ALIAS type."; - this->SetError(e.str()); + status.SetError( + "INTERFACE library specified with conflicting ALIAS type."); return false; } ++s; isAlias = true; } else if (libType == "INTERFACE") { if (haveSpecifiedType) { - std::ostringstream e; - e << "INTERFACE library specified with conflicting/multiple types."; - this->SetError(e.str()); + status.SetError( + "INTERFACE library specified with conflicting/multiple types."); return false; } if (isAlias) { - std::ostringstream e; - e << "INTERFACE library specified with conflicting ALIAS type."; - this->SetError(e.str()); + status.SetError( + "INTERFACE library specified with conflicting ALIAS type."); return false; } if (excludeFromAll) { - std::ostringstream e; - e << "INTERFACE library may not be used with EXCLUDE_FROM_ALL."; - this->SetError(e.str()); + status.SetError( + "INTERFACE library may not be used with EXCLUDE_FROM_ALL."); return false; } ++s; @@ -131,9 +121,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, haveSpecifiedType = true; } else if (*s == "EXCLUDE_FROM_ALL") { if (type == cmStateEnums::INTERFACE_LIBRARY) { - std::ostringstream e; - e << "INTERFACE library may not be used with EXCLUDE_FROM_ALL."; - this->SetError(e.str()); + status.SetError( + "INTERFACE library may not be used with EXCLUDE_FROM_ALL."); return false; } ++s; @@ -145,9 +134,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, ++s; importGlobal = true; } else if (type == cmStateEnums::INTERFACE_LIBRARY && *s == "GLOBAL") { - std::ostringstream e; - e << "GLOBAL option may only be used with IMPORTED libraries."; - this->SetError(e.str()); + status.SetError( + "GLOBAL option may only be used with IMPORTED libraries."); return false; } else { break; @@ -156,15 +144,12 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, if (type == cmStateEnums::INTERFACE_LIBRARY) { if (s != args.end()) { - std::ostringstream e; - e << "INTERFACE library requires no source arguments."; - this->SetError(e.str()); + status.SetError("INTERFACE library requires no source arguments."); return false; } if (importGlobal && !importTarget) { - std::ostringstream e; - e << "INTERFACE library specified as GLOBAL, but not as IMPORTED."; - this->SetError(e.str()); + status.SetError( + "INTERFACE library specified as GLOBAL, but not as IMPORTED."); return false; } } @@ -175,47 +160,44 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, if (nameOk && !importTarget && !isAlias) { nameOk = libName.find(':') == std::string::npos; } - if (!nameOk && !this->Makefile->CheckCMP0037(libName, type)) { + if (!nameOk && !mf.CheckCMP0037(libName, type)) { return false; } if (isAlias) { if (!cmGeneratorExpression::IsValidTargetName(libName)) { - this->SetError("Invalid name for ALIAS: " + libName); + status.SetError("Invalid name for ALIAS: " + libName); return false; } if (excludeFromAll) { - this->SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense."); + status.SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense."); return false; } if (importTarget || importGlobal) { - this->SetError("IMPORTED with ALIAS is not allowed."); + status.SetError("IMPORTED with ALIAS is not allowed."); return false; } if (args.size() != 3) { - std::ostringstream e; - e << "ALIAS requires exactly one target argument."; - this->SetError(e.str()); + status.SetError("ALIAS requires exactly one target argument."); return false; } std::string const& aliasedName = *s; - if (this->Makefile->IsAlias(aliasedName)) { + if (mf.IsAlias(aliasedName)) { std::ostringstream e; e << "cannot create ALIAS target \"" << libName << "\" because target \"" << aliasedName << "\" is itself an ALIAS."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } - cmTarget* aliasedTarget = - this->Makefile->FindTargetToUse(aliasedName, true); + cmTarget* aliasedTarget = mf.FindTargetToUse(aliasedName, true); if (!aliasedTarget) { std::ostringstream e; e << "cannot create ALIAS target \"" << libName << "\" because target \"" << aliasedName << "\" does not already " "exist."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } cmStateEnums::TargetType aliasedType = aliasedTarget->GetType(); @@ -229,7 +211,7 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, std::ostringstream e; e << "cannot create ALIAS target \"" << libName << "\" because target \"" << aliasedName << "\" is not a library."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } if (aliasedTarget->IsImported() && @@ -237,15 +219,15 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, std::ostringstream e; e << "cannot create ALIAS target \"" << libName << "\" because target \"" << aliasedName << "\" is imported but not globally visible."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } - this->Makefile->AddAlias(libName, aliasedName); + mf.AddAlias(libName, aliasedName); return true; } if (importTarget && excludeFromAll) { - this->SetError("excludeFromAll with IMPORTED target makes no sense."); + status.SetError("excludeFromAll with IMPORTED target makes no sense."); return false; } @@ -255,14 +237,13 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, yet its linker language. */ if ((type == cmStateEnums::SHARED_LIBRARY || type == cmStateEnums::MODULE_LIBRARY) && - !this->Makefile->GetState()->GetGlobalPropertyAsBool( - "TARGET_SUPPORTS_SHARED_LIBS")) { + !mf.GetState()->GetGlobalPropertyAsBool("TARGET_SUPPORTS_SHARED_LIBS")) { std::ostringstream w; w << "ADD_LIBRARY called with " << (type == cmStateEnums::SHARED_LIBRARY ? "SHARED" : "MODULE") << " option but the target platform does not support dynamic linking. " "Building a STATIC library instead. This may lead to problems."; - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); + mf.IssueMessage(MessageType::AUTHOR_WARNING, w.str()); type = cmStateEnums::STATIC_LIBRARY; } @@ -270,14 +251,13 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, if (importTarget) { // The IMPORTED signature requires a type to be specified explicitly. if (!haveSpecifiedType) { - this->SetError("called with IMPORTED argument but no library type."); + status.SetError("called with IMPORTED argument but no library type."); return false; } if (type == cmStateEnums::OBJECT_LIBRARY) { std::string reason; - if (!this->Makefile->GetGlobalGenerator()->HasKnownObjectFileLocation( - &reason)) { - this->Makefile->IssueMessage( + if (!mf.GetGlobalGenerator()->HasKnownObjectFileLocation(&reason)) { + mf.IssueMessage( MessageType::FATAL_ERROR, "The OBJECT library type may not be used for IMPORTED libraries" + reason + "."); @@ -288,28 +268,28 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, if (!cmGeneratorExpression::IsValidTargetName(libName)) { std::ostringstream e; e << "Invalid name for IMPORTED INTERFACE library target: " << libName; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } // Make sure the target does not already exist. - if (this->Makefile->FindTargetToUse(libName)) { + if (mf.FindTargetToUse(libName)) { std::ostringstream e; e << "cannot create imported target \"" << libName << "\" because another target with the same name already exists."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } // Create the imported target. - this->Makefile->AddImportedTarget(libName, type, importGlobal); + mf.AddImportedTarget(libName, type, importGlobal); return true; } // A non-imported target may not have UNKNOWN type. if (type == cmStateEnums::UNKNOWN_LIBRARY) { - this->Makefile->IssueMessage( + mf.IssueMessage( MessageType::FATAL_ERROR, "The UNKNOWN library type may be used only for IMPORTED libraries."); return true; @@ -318,8 +298,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, // Enforce name uniqueness. { std::string msg; - if (!this->Makefile->EnforceUniqueName(libName, msg)) { - this->SetError(msg); + if (!mf.EnforceUniqueName(libName, msg)) { + status.SetError(msg); return false; } } @@ -331,17 +311,17 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args, libName.find("::") != std::string::npos) { std::ostringstream e; e << "Invalid name for INTERFACE library target: " << libName; - this->SetError(e.str()); + status.SetError(e.str()); return false; } - this->Makefile->AddLibrary(libName, type, srclists, excludeFromAll); + mf.AddLibrary(libName, type, srclists, excludeFromAll); return true; } cmAppend(srclists, s, args.end()); - this->Makefile->AddLibrary(libName, type, srclists, excludeFromAll); + mf.AddLibrary(libName, type, srclists, excludeFromAll); return true; } diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h index aa21261..609449c 100644 --- a/Source/cmAddLibraryCommand.h +++ b/Source/cmAddLibraryCommand.h @@ -8,30 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmLibrarysCommand - * \brief Defines a list of executables to build. - * - * cmLibrarysCommand defines a list of executable (i.e., test) - * programs to create. - */ -class cmAddLibraryCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmAddLibraryCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmAddLibraryCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmAddLinkOptionsCommand.cxx b/Source/cmAddLinkOptionsCommand.cxx index 10ebd12..7ed31bd 100644 --- a/Source/cmAddLinkOptionsCommand.cxx +++ b/Source/cmAddLinkOptionsCommand.cxx @@ -2,19 +2,15 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAddLinkOptionsCommand.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" -class cmExecutionStatus; - -bool cmAddLinkOptionsCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmAddLinkOptionsCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { - if (args.empty()) { - return true; - } - + cmMakefile& mf = status.GetMakefile(); for (std::string const& i : args) { - this->Makefile->AddLinkOption(i); + mf.AddLinkOption(i); } return true; } diff --git a/Source/cmAddLinkOptionsCommand.h b/Source/cmAddLinkOptionsCommand.h index 30fff00..466fc32 100644 --- a/Source/cmAddLinkOptionsCommand.h +++ b/Source/cmAddLinkOptionsCommand.h @@ -8,24 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -class cmAddLinkOptionsCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmAddLinkOptionsCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmAddLinkOptionsCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx index 7947188..17bdc4a 100644 --- a/Source/cmAddSubDirectoryCommand.cxx +++ b/Source/cmAddSubDirectoryCommand.cxx @@ -5,21 +5,21 @@ #include <sstream> #include <string.h> +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmRange.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmExecutionStatus; - -// cmAddSubDirectoryCommand -bool cmAddSubDirectoryCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmAddSubDirectoryCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } + cmMakefile& mf = status.GetMakefile(); // store the binpath std::string const& srcArg = args.front(); std::string binArg; @@ -35,7 +35,7 @@ bool cmAddSubDirectoryCommand::InitialPass( if (binArg.empty()) { binArg = arg; } else { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } } @@ -46,15 +46,12 @@ bool cmAddSubDirectoryCommand::InitialPass( if (cmSystemTools::FileIsFullPath(srcArg)) { srcPath = srcArg; } else { - srcPath = this->Makefile->GetCurrentSourceDirectory(); - srcPath += "/"; - srcPath += srcArg; + srcPath = cmStrCat(mf.GetCurrentSourceDirectory(), '/', srcArg); } if (!cmSystemTools::FileIsDirectory(srcPath)) { - std::string error = "given source \""; - error += srcArg; - error += "\" which is not an existing directory."; - this->SetError(error); + std::string error = cmStrCat("given source \"", srcArg, + "\" which is not an existing directory."); + status.SetError(error); return false; } srcPath = cmSystemTools::CollapseFullPath(srcPath); @@ -65,22 +62,22 @@ bool cmAddSubDirectoryCommand::InitialPass( // No binary directory was specified. If the source directory is // not a subdirectory of the current directory then it is an // error. - if (!cmSystemTools::IsSubDirectory( - srcPath, this->Makefile->GetCurrentSourceDirectory())) { + if (!cmSystemTools::IsSubDirectory(srcPath, + mf.GetCurrentSourceDirectory())) { std::ostringstream e; e << "not given a binary directory but the given source directory " << "\"" << srcPath << "\" is not a subdirectory of \"" - << this->Makefile->GetCurrentSourceDirectory() << "\". " + << mf.GetCurrentSourceDirectory() << "\". " << "When specifying an out-of-tree source a binary directory " << "must be explicitly specified."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } // Remove the CurrentDirectory from the srcPath and replace it // with the CurrentOutputDirectory. - const std::string& src = this->Makefile->GetCurrentSourceDirectory(); - const std::string& bin = this->Makefile->GetCurrentBinaryDirectory(); + const std::string& src = mf.GetCurrentSourceDirectory(); + const std::string& bin = mf.GetCurrentBinaryDirectory(); size_t srcLen = src.length(); size_t binLen = bin.length(); if (srcLen > 0 && src.back() == '/') { @@ -96,15 +93,13 @@ bool cmAddSubDirectoryCommand::InitialPass( if (cmSystemTools::FileIsFullPath(binArg)) { binPath = binArg; } else { - binPath = this->Makefile->GetCurrentBinaryDirectory(); - binPath += "/"; - binPath += binArg; + binPath = cmStrCat(mf.GetCurrentBinaryDirectory(), '/', binArg); } } binPath = cmSystemTools::CollapseFullPath(binPath); // Add the subdirectory using the computed full paths. - this->Makefile->AddSubDirectory(srcPath, binPath, excludeFromAll, true); + mf.AddSubDirectory(srcPath, binPath, excludeFromAll, true); return true; } diff --git a/Source/cmAddSubDirectoryCommand.h b/Source/cmAddSubDirectoryCommand.h index 0ea4423..87da840 100644 --- a/Source/cmAddSubDirectoryCommand.h +++ b/Source/cmAddSubDirectoryCommand.h @@ -8,31 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmAddSubDirectoryCommand - * \brief Specify a subdirectory to build - * - * cmAddSubDirectoryCommand specifies a subdirectory to process - * by CMake. CMake will descend - * into the specified source directory and process any CMakeLists.txt found. - */ -class cmAddSubDirectoryCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmAddSubDirectoryCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmAddSubDirectoryCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmAddTestCommand.cxx b/Source/cmAddTestCommand.cxx index bf28702..7904bf5 100644 --- a/Source/cmAddTestCommand.cxx +++ b/Source/cmAddTestCommand.cxx @@ -4,34 +4,36 @@ #include <sstream> +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmTest.h" #include "cmTestGenerator.h" -class cmExecutionStatus; +static bool cmAddTestCommandHandleNameMode( + std::vector<std::string> const& args, cmExecutionStatus& status); -// cmExecutableCommand -bool cmAddTestCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmAddTestCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (!args.empty() && args[0] == "NAME") { - return this->HandleNameMode(args); + return cmAddTestCommandHandleNameMode(args, status); } // First argument is the name of the test Second argument is the name of // the executable to run (a target or external program) Remaining arguments // are the arguments to pass to the executable if (args.size() < 2) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } + cmMakefile& mf = status.GetMakefile(); // Collect the command with arguments. std::vector<std::string> command(args.begin() + 1, args.end()); // Create the test but add a generator only the first time it is // seen. This preserves behavior from before test generators. - cmTest* test = this->Makefile->GetTest(args[0]); + cmTest* test = mf.GetTest(args[0]); if (test) { // If the test was already added by a new-style signature do not // allow it to be duplicated. @@ -39,25 +41,27 @@ bool cmAddTestCommand::InitialPass(std::vector<std::string> const& args, std::ostringstream e; e << " given test name \"" << args[0] << "\" which already exists in this directory."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } else { - test = this->Makefile->CreateTest(args[0]); + test = mf.CreateTest(args[0]); test->SetOldStyle(true); - this->Makefile->AddTestGenerator(new cmTestGenerator(test)); + mf.AddTestGenerator(new cmTestGenerator(test)); } test->SetCommand(command); return true; } -bool cmAddTestCommand::HandleNameMode(std::vector<std::string> const& args) +bool cmAddTestCommandHandleNameMode(std::vector<std::string> const& args, + cmExecutionStatus& status) { std::string name; std::vector<std::string> configurations; std::string working_directory; std::vector<std::string> command; + bool command_expand_lists = false; // Read the arguments. enum Doing @@ -72,22 +76,29 @@ bool cmAddTestCommand::HandleNameMode(std::vector<std::string> const& args) for (unsigned int i = 1; i < args.size(); ++i) { if (args[i] == "COMMAND") { if (!command.empty()) { - this->SetError(" may be given at most one COMMAND."); + status.SetError(" may be given at most one COMMAND."); return false; } doing = DoingCommand; } else if (args[i] == "CONFIGURATIONS") { if (!configurations.empty()) { - this->SetError(" may be given at most one set of CONFIGURATIONS."); + status.SetError(" may be given at most one set of CONFIGURATIONS."); return false; } doing = DoingConfigs; } else if (args[i] == "WORKING_DIRECTORY") { if (!working_directory.empty()) { - this->SetError(" may be given at most one WORKING_DIRECTORY."); + status.SetError(" may be given at most one WORKING_DIRECTORY."); return false; } doing = DoingWorkingDirectory; + } else if (args[i] == "COMMAND_EXPAND_LISTS") { + if (command_expand_lists) { + status.SetError(" may be given at most one COMMAND_EXPAND_LISTS."); + return false; + } + command_expand_lists = true; + doing = DoingNone; } else if (doing == DoingName) { name = args[i]; doing = DoingNone; @@ -101,40 +112,43 @@ bool cmAddTestCommand::HandleNameMode(std::vector<std::string> const& args) } else { std::ostringstream e; e << " given unknown argument:\n " << args[i] << "\n"; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } // Require a test name. if (name.empty()) { - this->SetError(" must be given non-empty NAME."); + status.SetError(" must be given non-empty NAME."); return false; } // Require a command. if (command.empty()) { - this->SetError(" must be given non-empty COMMAND."); + status.SetError(" must be given non-empty COMMAND."); return false; } + cmMakefile& mf = status.GetMakefile(); + // Require a unique test name within the directory. - if (this->Makefile->GetTest(name)) { + if (mf.GetTest(name)) { std::ostringstream e; e << " given test NAME \"" << name << "\" which already exists in this directory."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } // Add the test. - cmTest* test = this->Makefile->CreateTest(name); + cmTest* test = mf.CreateTest(name); test->SetOldStyle(false); test->SetCommand(command); if (!working_directory.empty()) { test->SetProperty("WORKING_DIRECTORY", working_directory.c_str()); } - this->Makefile->AddTestGenerator(new cmTestGenerator(test, configurations)); + test->SetCommandExpandLists(command_expand_lists); + mf.AddTestGenerator(new cmTestGenerator(test, configurations)); return true; } diff --git a/Source/cmAddTestCommand.h b/Source/cmAddTestCommand.h index bea3f3d..5877547 100644 --- a/Source/cmAddTestCommand.h +++ b/Source/cmAddTestCommand.h @@ -8,32 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmAddTestCommand - * \brief Add a test to the lists of tests to run. - * - * cmAddTestCommand adds a test to the list of tests to run . - */ -class cmAddTestCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmAddTestCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - bool HandleNameMode(std::vector<std::string> const& args); -}; +bool cmAddTestCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h index d1e32b0..59aa86f 100644 --- a/Source/cmAlgorithms.h +++ b/Source/cmAlgorithms.h @@ -6,93 +6,66 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmRange.h" - #include "cm_kwiml.h" #include <algorithm> #include <functional> #include <iterator> -#include <memory> -#include <sstream> -#include <string.h> -#include <string> #include <unordered_set> #include <utility> #include <vector> -inline bool cmHasLiteralPrefixImpl(const std::string& str1, const char* str2, - size_t N) +template <std::size_t N> +struct cmOverloadPriority : cmOverloadPriority<N - 1> { - return strncmp(str1.c_str(), str2, N) == 0; -} +}; -inline bool cmHasLiteralPrefixImpl(const char* str1, const char* str2, - size_t N) +template <> +struct cmOverloadPriority<0> { - return strncmp(str1, str2, N) == 0; -} +}; -inline bool cmHasLiteralSuffixImpl(const std::string& str1, const char* str2, - size_t N) +template <typename FwdIt> +FwdIt cmRotate(FwdIt first, FwdIt middle, FwdIt last) { - size_t len = str1.size(); - return len >= N && strcmp(str1.c_str() + len - N, str2) == 0; + const typename std::iterator_traits<FwdIt>::difference_type dist = + std::distance(middle, last); + std::rotate(first, middle, last); + std::advance(first, dist); + return first; } -inline bool cmHasLiteralSuffixImpl(const char* str1, const char* str2, - size_t N) +template <typename Container, typename Predicate> +void cmEraseIf(Container& cont, Predicate pred) { - size_t len = strlen(str1); - return len >= N && strcmp(str1 + len - N, str2) == 0; + cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end()); } -template <typename T, size_t N> -bool cmHasLiteralPrefix(const T& str1, const char (&str2)[N]) +template <typename Range, typename Key> +auto cmContainsImpl(Range const& range, Key const& key, cmOverloadPriority<2>) + -> decltype(range.exists(key)) { - return cmHasLiteralPrefixImpl(str1, str2, N - 1); + return range.exists(key); } -template <typename T, size_t N> -bool cmHasLiteralSuffix(const T& str1, const char (&str2)[N]) +template <typename Range, typename Key> +auto cmContainsImpl(Range const& range, Key const& key, cmOverloadPriority<1>) + -> decltype(range.find(key) != range.end()) { - return cmHasLiteralSuffixImpl(str1, str2, N - 1); + return range.find(key) != range.end(); } -struct cmStrCmp +template <typename Range, typename Key> +bool cmContainsImpl(Range const& range, Key const& key, cmOverloadPriority<0>) { - cmStrCmp(const char* test) - : m_test(test) - { - } - cmStrCmp(std::string test) - : m_test(std::move(test)) - { - } - - bool operator()(const std::string& input) const { return m_test == input; } - - bool operator()(const char* input) const - { - return strcmp(input, m_test.c_str()) == 0; - } - -private: - const std::string m_test; -}; - -template <typename FwdIt> -FwdIt cmRotate(FwdIt first, FwdIt middle, FwdIt last) -{ - const typename std::iterator_traits<FwdIt>::difference_type dist = - std::distance(middle, last); - std::rotate(first, middle, last); - std::advance(first, dist); - return first; + using std::begin; + using std::end; + return std::find(begin(range), end(range), key) != end(range); } -template <typename Container, typename Predicate> -void cmEraseIf(Container& cont, Predicate pred) +template <typename Range, typename Key> +bool cmContains(Range const& range, Key const& key) { - cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end()); + return cmContainsImpl(range, key, cmOverloadPriority<2>{}); } namespace ContainerAlgorithms { @@ -158,8 +131,6 @@ private: }; } -typedef cmRange<std::vector<std::string>::const_iterator> cmStringRange; - class cmListFileBacktrace; typedef cmRange<std::vector<cmListFileBacktrace>::const_iterator> cmBacktraceRange; @@ -184,31 +155,6 @@ void cmAppend(std::vector<T>& v, InputIt first, InputIt last) } template <typename Range> -std::string cmJoin(Range const& r, const char* delimiter) -{ - if (r.empty()) { - return std::string(); - } - std::ostringstream os; - typedef typename Range::value_type ValueType; - typedef typename Range::const_iterator InputIt; - const InputIt first = r.begin(); - InputIt last = r.end(); - --last; - std::copy(first, last, std::ostream_iterator<ValueType>(os, delimiter)); - - os << *last; - - return os.str(); -} - -template <typename Range> -std::string cmJoin(Range const& r, std::string const& delimiter) -{ - return cmJoin(r, delimiter.c_str()); -} - -template <typename Range> typename Range::const_iterator cmRemoveN(Range& r, size_t n) { return ContainerAlgorithms::RemoveN(r.begin(), r.end(), n); @@ -268,7 +214,7 @@ ForwardIterator cmRemoveDuplicates(ForwardIterator first, ForwardIterator last) ForwardIterator result = first; while (first != last) { - if (uniq.find(first) == uniq.end()) { + if (!cmContains(uniq, first)) { if (result != first) { *result = std::move(*first); } @@ -286,23 +232,6 @@ typename Range::const_iterator cmRemoveDuplicates(Range& r) return cmRemoveDuplicates(r.begin(), r.end()); } -template <typename Range> -std::string cmWrap(std::string const& prefix, Range const& r, - std::string const& suffix, std::string const& sep) -{ - if (r.empty()) { - return std::string(); - } - return prefix + cmJoin(r, suffix + sep + prefix) + suffix; -} - -template <typename Range> -std::string cmWrap(char prefix, Range const& r, char suffix, - std::string const& sep) -{ - return cmWrap(std::string(1, prefix), r, std::string(1, suffix), sep); -} - template <typename Range, typename T> typename Range::const_iterator cmFindNot(Range const& r, T const& t) { @@ -315,45 +244,8 @@ std::reverse_iterator<Iter> cmMakeReverseIterator(Iter it) return std::reverse_iterator<Iter>(it); } -inline bool cmHasPrefix(std::string const& str, std::string const& prefix) -{ - if (str.size() < prefix.size()) { - return false; - } - return str.compare(0, prefix.size(), prefix) == 0; -} - -inline bool cmHasSuffix(const std::string& str, const std::string& suffix) -{ - if (str.size() < suffix.size()) { - return false; - } - return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; -} - -inline void cmStripSuffixIfExists(std::string& str, const std::string& suffix) -{ - if (cmHasSuffix(str, suffix)) { - str.resize(str.size() - suffix.size()); - } -} - namespace cm { -#if defined(CMake_HAVE_CXX_MAKE_UNIQUE) - -using std::make_unique; - -#else - -template <typename T, typename... Args> -std::unique_ptr<T> make_unique(Args&&... args) -{ - return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); -} - -#endif - #if __cplusplus >= 201703L || defined(_MSVC_LANG) && _MSVC_LANG >= 201703L using std::size; diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index 359d57a..a063fd9 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -3,12 +3,14 @@ #include "cmArchiveWrite.h" #include "cmLocale.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cm_get_date.h" #include "cm_libarchive.h" #include "cmsys/Directory.hxx" #include "cmsys/Encoding.hxx" #include "cmsys/FStream.hxx" + #include <iostream> #include <sstream> #include <string.h> @@ -85,22 +87,22 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c, switch (c) { case CompressNone: if (archive_write_add_filter_none(this->Archive) != ARCHIVE_OK) { - this->Error = "archive_write_add_filter_none: "; - this->Error += cm_archive_error_string(this->Archive); + this->Error = cmStrCat("archive_write_add_filter_none: ", + cm_archive_error_string(this->Archive)); return; } break; case CompressCompress: if (archive_write_add_filter_compress(this->Archive) != ARCHIVE_OK) { - this->Error = "archive_write_add_filter_compress: "; - this->Error += cm_archive_error_string(this->Archive); + this->Error = cmStrCat("archive_write_add_filter_compress: ", + cm_archive_error_string(this->Archive)); return; } break; case CompressGZip: { if (archive_write_add_filter_gzip(this->Archive) != ARCHIVE_OK) { - this->Error = "archive_write_add_filter_gzip: "; - this->Error += cm_archive_error_string(this->Archive); + this->Error = cmStrCat("archive_write_add_filter_gzip: ", + cm_archive_error_string(this->Archive)); return; } std::string source_date_epoch; @@ -110,60 +112,60 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c, // The next best thing is to omit the timestamp entirely. if (archive_write_set_filter_option(this->Archive, "gzip", "timestamp", nullptr) != ARCHIVE_OK) { - this->Error = "archive_write_set_filter_option: "; - this->Error += cm_archive_error_string(this->Archive); + this->Error = cmStrCat("archive_write_set_filter_option: ", + cm_archive_error_string(this->Archive)); return; } } } break; case CompressBZip2: if (archive_write_add_filter_bzip2(this->Archive) != ARCHIVE_OK) { - this->Error = "archive_write_add_filter_bzip2: "; - this->Error += cm_archive_error_string(this->Archive); + this->Error = cmStrCat("archive_write_add_filter_bzip2: ", + cm_archive_error_string(this->Archive)); return; } break; case CompressLZMA: if (archive_write_add_filter_lzma(this->Archive) != ARCHIVE_OK) { - this->Error = "archive_write_add_filter_lzma: "; - this->Error += cm_archive_error_string(this->Archive); + this->Error = cmStrCat("archive_write_add_filter_lzma: ", + cm_archive_error_string(this->Archive)); return; } break; case CompressXZ: if (archive_write_add_filter_xz(this->Archive) != ARCHIVE_OK) { - this->Error = "archive_write_add_filter_xz: "; - this->Error += cm_archive_error_string(this->Archive); + this->Error = cmStrCat("archive_write_add_filter_xz: ", + cm_archive_error_string(this->Archive)); return; } break; case CompressZstd: if (archive_write_add_filter_zstd(this->Archive) != ARCHIVE_OK) { - this->Error = "archive_write_add_filter_zstd: "; - this->Error += cm_archive_error_string(this->Archive); + this->Error = cmStrCat("archive_write_add_filter_zstd: ", + cm_archive_error_string(this->Archive)); return; } break; } #if !defined(_WIN32) || defined(__CYGWIN__) if (archive_read_disk_set_standard_lookup(this->Disk) != ARCHIVE_OK) { - this->Error = "archive_read_disk_set_standard_lookup: "; - this->Error += cm_archive_error_string(this->Archive); + this->Error = cmStrCat("archive_read_disk_set_standard_lookup: ", + cm_archive_error_string(this->Archive)); return; } #endif if (archive_write_set_format_by_name(this->Archive, format.c_str()) != ARCHIVE_OK) { - this->Error = "archive_write_set_format_by_name: "; - this->Error += cm_archive_error_string(this->Archive); + this->Error = cmStrCat("archive_write_set_format_by_name: ", + cm_archive_error_string(this->Archive)); return; } // do not pad the last block!! if (archive_write_set_bytes_in_last_block(this->Archive, 1)) { - this->Error = "archive_write_set_bytes_in_last_block: "; - this->Error += cm_archive_error_string(this->Archive); + this->Error = cmStrCat("archive_write_set_bytes_in_last_block: ", + cm_archive_error_string(this->Archive)); return; } @@ -171,8 +173,8 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c, this->Archive, this, nullptr, reinterpret_cast<archive_write_callback*>(&Callback::Write), nullptr) != ARCHIVE_OK) { - this->Error = "archive_write_open: "; - this->Error += cm_archive_error_string(this->Archive); + this->Error = + cmStrCat("archive_write_open: ", cm_archive_error_string(this->Archive)); return; } } @@ -205,8 +207,7 @@ bool cmArchiveWrite::AddPath(const char* path, size_t skip, const char* prefix, } cmsys::Directory d; if (d.Load(path)) { - std::string next = path; - next += "/"; + std::string next = cmStrCat(path, '/'); std::string::size_type end = next.size(); unsigned long n = d.GetNumberOfFiles(); for (unsigned long i = 0; i < n; ++i) { @@ -237,8 +238,7 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix) static_cast<void>(localeRAII); // Meta-data. - std::string dest = prefix ? prefix : ""; - dest += out; + std::string dest = cmStrCat(prefix ? prefix : "", out); if (this->Verbose) { std::cout << dest << "\n"; } @@ -247,10 +247,8 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix) cm_archive_entry_copy_pathname(e, dest); if (archive_read_disk_entry_from_file(this->Disk, e, -1, nullptr) != ARCHIVE_OK) { - this->Error = "Unable to read from file '"; - this->Error += file; - this->Error += "': "; - this->Error += cm_archive_error_string(this->Disk); + this->Error = cmStrCat("Unable to read from file '", file, + "': ", cm_archive_error_string(this->Disk)); return false; } if (!this->MTime.empty()) { @@ -258,9 +256,7 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix) time(&now); time_t t = cm_get_date(now, this->MTime.c_str()); if (t == -1) { - this->Error = "unable to parse mtime '"; - this->Error += this->MTime; - this->Error += "'"; + this->Error = cmStrCat("unable to parse mtime '", this->MTime, '\''); return false; } archive_entry_set_mtime(e, t, 0); @@ -310,8 +306,8 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix) } if (archive_write_header(this->Archive, e) != ARCHIVE_OK) { - this->Error = "archive_write_header: "; - this->Error += cm_archive_error_string(this->Archive); + this->Error = cmStrCat("archive_write_header: ", + cm_archive_error_string(this->Archive)); return false; } @@ -329,10 +325,8 @@ bool cmArchiveWrite::AddData(const char* file, size_t size) { cmsys::ifstream fin(file, std::ios::in | std::ios::binary); if (!fin) { - this->Error = "Error opening \""; - this->Error += file; - this->Error += "\": "; - this->Error += cmSystemTools::GetLastSystemError(); + this->Error = cmStrCat("Error opening \"", file, + "\": ", cmSystemTools::GetLastSystemError()); return false; } @@ -350,17 +344,15 @@ bool cmArchiveWrite::AddData(const char* file, size_t size) break; } if (archive_write_data(this->Archive, buffer, nnext) != nnext_s) { - this->Error = "archive_write_data: "; - this->Error += cm_archive_error_string(this->Archive); + this->Error = cmStrCat("archive_write_data: ", + cm_archive_error_string(this->Archive)); return false; } nleft -= nnext; } if (nleft > 0) { - this->Error = "Error reading \""; - this->Error += file; - this->Error += "\": "; - this->Error += cmSystemTools::GetLastSystemError(); + this->Error = cmStrCat("Error reading \"", file, + "\": ", cmSystemTools::GetLastSystemError()); return false; } return true; diff --git a/Source/cmArchiveWrite.h b/Source/cmArchiveWrite.h index 9ea88d3..e90a603 100644 --- a/Source/cmArchiveWrite.h +++ b/Source/cmArchiveWrite.h @@ -9,7 +9,7 @@ #include <stddef.h> #include <string> -#if !defined(CMAKE_BUILD_WITH_CMAKE) +#if defined(CMAKE_BOOTSTRAP) # error "cmArchiveWrite not allowed during bootstrap build!" #endif diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx index 106e7a7..7bf19d0 100644 --- a/Source/cmAuxSourceDirectoryCommand.cxx +++ b/Source/cmAuxSourceDirectoryCommand.cxx @@ -7,36 +7,33 @@ #include <stddef.h> #include <utility> -#include "cmAlgorithms.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmSourceFile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" -class cmExecutionStatus; - -// cmAuxSourceDirectoryCommand -bool cmAuxSourceDirectoryCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmAuxSourceDirectoryCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 2) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } + cmMakefile& mf = status.GetMakefile(); std::string sourceListValue; std::string const& templateDirectory = args[0]; std::string tdir; if (!cmSystemTools::FileIsFullPath(templateDirectory)) { - tdir = this->Makefile->GetCurrentSourceDirectory(); - tdir += "/"; - tdir += templateDirectory; + tdir = cmStrCat(mf.GetCurrentSourceDirectory(), '/', templateDirectory); } else { tdir = templateDirectory; } // was the list already populated - const char* def = this->Makefile->GetDefinition(args[1]); + const char* def = mf.GetDefinition(args[1]); if (def) { sourceListValue = def; } @@ -55,14 +52,12 @@ bool cmAuxSourceDirectoryCommand::InitialPass( std::string ext = file.substr(dotpos + 1); std::string base = file.substr(0, dotpos); // Process only source files - auto cm = this->Makefile->GetCMakeInstance(); + auto cm = mf.GetCMakeInstance(); if (!base.empty() && cm->IsSourceExtension(ext)) { - std::string fullname = templateDirectory; - fullname += "/"; - fullname += file; + std::string fullname = cmStrCat(templateDirectory, '/', file); // add the file as a class file so // depends can be done - cmSourceFile* sf = this->Makefile->GetOrCreateSource(fullname); + cmSourceFile* sf = mf.GetOrCreateSource(fullname); sf->SetProperty("ABSTRACT", "0"); files.push_back(std::move(fullname)); } @@ -74,6 +69,6 @@ bool cmAuxSourceDirectoryCommand::InitialPass( sourceListValue += ";"; } sourceListValue += cmJoin(files, ";"); - this->Makefile->AddDefinition(args[1], sourceListValue.c_str()); + mf.AddDefinition(args[1], sourceListValue); return true; } diff --git a/Source/cmAuxSourceDirectoryCommand.h b/Source/cmAuxSourceDirectoryCommand.h index 3742e3e..ae26092 100644 --- a/Source/cmAuxSourceDirectoryCommand.h +++ b/Source/cmAuxSourceDirectoryCommand.h @@ -8,33 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmAuxSourceDirectoryCommand - * \brief Specify auxiliary source code directories. - * - * cmAuxSourceDirectoryCommand specifies source code directories - * that must be built as part of this build process. This directories - * are not recursively processed like the SUBDIR command (cmSubdirCommand). - * A side effect of this command is to create a subdirectory in the build - * directory structure. - */ -class cmAuxSourceDirectoryCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmAuxSourceDirectoryCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmAuxSourceDirectoryCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmBinUtilsLinker.cxx b/Source/cmBinUtilsLinker.cxx new file mode 100644 index 0000000..3dac85c --- /dev/null +++ b/Source/cmBinUtilsLinker.cxx @@ -0,0 +1,15 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmBinUtilsLinker.h" +#include "cmRuntimeDependencyArchive.h" + +cmBinUtilsLinker::cmBinUtilsLinker(cmRuntimeDependencyArchive* archive) + : Archive(archive) +{ +} + +void cmBinUtilsLinker::SetError(const std::string& e) +{ + this->Archive->SetError(e); +} diff --git a/Source/cmBinUtilsLinker.h b/Source/cmBinUtilsLinker.h new file mode 100644 index 0000000..29853a5 --- /dev/null +++ b/Source/cmBinUtilsLinker.h @@ -0,0 +1,30 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#ifndef cmBinUtilsLinker_h +#define cmBinUtilsLinker_h + +#include "cmStateTypes.h" + +#include <string> + +class cmRuntimeDependencyArchive; + +class cmBinUtilsLinker +{ +public: + cmBinUtilsLinker(cmRuntimeDependencyArchive* archive); + virtual ~cmBinUtilsLinker() = default; + + virtual bool Prepare() { return true; } + + virtual bool ScanDependencies(std::string const& file, + cmStateEnums::TargetType type) = 0; + +protected: + cmRuntimeDependencyArchive* Archive; + + void SetError(const std::string& e); +}; + +#endif // cmBinUtilsLinker_h diff --git a/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.cxx new file mode 100644 index 0000000..40de592 --- /dev/null +++ b/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.cxx @@ -0,0 +1,18 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h" +#include "cmRuntimeDependencyArchive.h" + +cmBinUtilsLinuxELFGetRuntimeDependenciesTool:: + cmBinUtilsLinuxELFGetRuntimeDependenciesTool( + cmRuntimeDependencyArchive* archive) + : Archive(archive) +{ +} + +void cmBinUtilsLinuxELFGetRuntimeDependenciesTool::SetError( + const std::string& error) +{ + this->Archive->SetError(error); +} diff --git a/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h b/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h new file mode 100644 index 0000000..d514e7f --- /dev/null +++ b/Source/cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h @@ -0,0 +1,30 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#ifndef cmBinUtilsLinuxELFGetRuntimeDependenciesTool_h +#define cmBinUtilsLinuxELFGetRuntimeDependenciesTool_h + +#include <string> +#include <vector> + +class cmRuntimeDependencyArchive; + +class cmBinUtilsLinuxELFGetRuntimeDependenciesTool +{ +public: + cmBinUtilsLinuxELFGetRuntimeDependenciesTool( + cmRuntimeDependencyArchive* archive); + virtual ~cmBinUtilsLinuxELFGetRuntimeDependenciesTool() = default; + + virtual bool GetFileInfo(std::string const& file, + std::vector<std::string>& needed, + std::vector<std::string>& rpaths, + std::vector<std::string>& runpaths) = 0; + +protected: + cmRuntimeDependencyArchive* Archive; + + void SetError(const std::string& e); +}; + +#endif // cmBinUtilsLinuxELFGetRuntimeDependenciesTool_h diff --git a/Source/cmBinUtilsLinuxELFLinker.cxx b/Source/cmBinUtilsLinuxELFLinker.cxx new file mode 100644 index 0000000..6316a29 --- /dev/null +++ b/Source/cmBinUtilsLinuxELFLinker.cxx @@ -0,0 +1,179 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmBinUtilsLinuxELFLinker.h" + +#include "cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h" +#include "cmLDConfigLDConfigTool.h" +#include "cmMakefile.h" +#include "cmMessageType.h" +#include "cmRuntimeDependencyArchive.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" + +#include <cmsys/RegularExpression.hxx> + +#include <sstream> + +#include "cm_memory.hxx" + +static std::string ReplaceOrigin(const std::string& rpath, + const std::string& origin) +{ + static const cmsys::RegularExpression originRegex( + "(\\$ORIGIN)([^a-zA-Z0-9_]|$)"); + static const cmsys::RegularExpression originCurlyRegex("\\${ORIGIN}"); + + cmsys::RegularExpressionMatch match; + if (originRegex.find(rpath.c_str(), match)) { + std::string begin = rpath.substr(0, match.start(1)); + std::string end = rpath.substr(match.end(1)); + return begin + origin + end; + } + if (originCurlyRegex.find(rpath.c_str(), match)) { + std::string begin = rpath.substr(0, match.start()); + std::string end = rpath.substr(match.end()); + return begin + origin + end; + } + return rpath; +} + +cmBinUtilsLinuxELFLinker::cmBinUtilsLinuxELFLinker( + cmRuntimeDependencyArchive* archive) + : cmBinUtilsLinker(archive) +{ +} + +bool cmBinUtilsLinuxELFLinker::Prepare() +{ + std::string tool = this->Archive->GetGetRuntimeDependenciesTool(); + if (tool.empty()) { + tool = "objdump"; + } + if (tool == "objdump") { + this->Tool = + cm::make_unique<cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool>( + this->Archive); + } else { + std::ostringstream e; + e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL: " << tool; + this->SetError(e.str()); + return false; + } + + std::string ldConfigTool = + this->Archive->GetMakefile()->GetSafeDefinition("CMAKE_LDCONFIG_TOOL"); + if (ldConfigTool.empty()) { + ldConfigTool = "ldconfig"; + } + if (ldConfigTool == "ldconfig") { + this->LDConfigTool = + cm::make_unique<cmLDConfigLDConfigTool>(this->Archive); + } else { + std::ostringstream e; + e << "Invalid value for CMAKE_LDCONFIG_TOOL: " << ldConfigTool; + this->SetError(e.str()); + return false; + } + + return true; +} + +bool cmBinUtilsLinuxELFLinker::ScanDependencies( + std::string const& file, cmStateEnums::TargetType /* unused */) +{ + std::vector<std::string> parentRpaths; + return this->ScanDependencies(file, parentRpaths); +} + +bool cmBinUtilsLinuxELFLinker::ScanDependencies( + std::string const& file, std::vector<std::string> const& parentRpaths) +{ + std::string origin = cmSystemTools::GetFilenamePath(file); + std::vector<std::string> needed; + std::vector<std::string> rpaths; + std::vector<std::string> runpaths; + if (!this->Tool->GetFileInfo(file, needed, rpaths, runpaths)) { + return false; + } + for (auto& runpath : runpaths) { + runpath = ReplaceOrigin(runpath, origin); + } + for (auto& rpath : rpaths) { + rpath = ReplaceOrigin(rpath, origin); + } + + std::vector<std::string> searchPaths; + if (!runpaths.empty()) { + searchPaths = runpaths; + } else { + searchPaths = rpaths; + searchPaths.insert(searchPaths.end(), parentRpaths.begin(), + parentRpaths.end()); + } + + std::vector<std::string> ldConfigPaths; + if (!this->LDConfigTool->GetLDConfigPaths(ldConfigPaths)) { + return false; + } + searchPaths.insert(searchPaths.end(), ldConfigPaths.begin(), + ldConfigPaths.end()); + + for (auto const& dep : needed) { + if (!this->Archive->IsPreExcluded(dep)) { + std::string path; + bool resolved = false; + if (dep.find('/') != std::string::npos) { + this->SetError("Paths to dependencies are not supported"); + return false; + } + if (!this->ResolveDependency(dep, searchPaths, path, resolved)) { + return false; + } + if (resolved) { + if (!this->Archive->IsPostExcluded(path)) { + bool unique; + this->Archive->AddResolvedPath(dep, path, unique); + if (unique && !this->ScanDependencies(path, rpaths)) { + return false; + } + } + } else { + this->Archive->AddUnresolvedPath(dep); + } + } + } + + return true; +} + +bool cmBinUtilsLinuxELFLinker::ResolveDependency( + std::string const& name, std::vector<std::string> const& searchPaths, + std::string& path, bool& resolved) +{ + for (auto const& searchPath : searchPaths) { + path = cmStrCat(searchPath, '/', name); + if (cmSystemTools::PathExists(path)) { + resolved = true; + return true; + } + } + + for (auto const& searchPath : this->Archive->GetSearchDirectories()) { + path = cmStrCat(searchPath, '/', name); + if (cmSystemTools::PathExists(path)) { + std::ostringstream warning; + warning << "Dependency " << name << " found in search directory:\n " + << searchPath + << "\nSee file(GET_RUNTIME_DEPENDENCIES) documentation for " + << "more information."; + this->Archive->GetMakefile()->IssueMessage(MessageType::WARNING, + warning.str()); + resolved = true; + return true; + } + } + + resolved = false; + return true; +} diff --git a/Source/cmBinUtilsLinuxELFLinker.h b/Source/cmBinUtilsLinuxELFLinker.h new file mode 100644 index 0000000..e209637 --- /dev/null +++ b/Source/cmBinUtilsLinuxELFLinker.h @@ -0,0 +1,44 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#ifndef cmBinUtilsLinuxELFLinker_h +#define cmBinUtilsLinuxELFLinker_h + +#include "cmBinUtilsLinker.h" +#include "cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h" +#include "cmLDConfigTool.h" +#include "cmStateTypes.h" + +#include <memory> +#include <string> +#include <vector> + +class cmRuntimeDependencyArchive; + +class cmBinUtilsLinuxELFLinker : public cmBinUtilsLinker +{ +public: + cmBinUtilsLinuxELFLinker(cmRuntimeDependencyArchive* archive); + + bool Prepare() override; + + bool ScanDependencies(std::string const& file, + cmStateEnums::TargetType type) override; + +private: + std::unique_ptr<cmBinUtilsLinuxELFGetRuntimeDependenciesTool> Tool; + std::unique_ptr<cmLDConfigTool> LDConfigTool; + bool HaveLDConfigPaths = false; + std::vector<std::string> LDConfigPaths; + + bool ScanDependencies(std::string const& file, + std::vector<std::string> const& parentRpaths); + + bool ResolveDependency(std::string const& name, + std::vector<std::string> const& searchPaths, + std::string& path, bool& resolved); + + bool GetLDConfigPaths(); +}; + +#endif // cmBinUtilsLinuxELFLinker_h diff --git a/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx new file mode 100644 index 0000000..3bf7bf8 --- /dev/null +++ b/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx @@ -0,0 +1,84 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h" +#include "cmRuntimeDependencyArchive.h" +#include "cmSystemTools.h" +#include "cmUVProcessChain.h" + +#include <cmsys/RegularExpression.hxx> + +#include <sstream> + +cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool:: + cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool( + cmRuntimeDependencyArchive* archive) + : cmBinUtilsLinuxELFGetRuntimeDependenciesTool(archive) +{ +} + +bool cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool::GetFileInfo( + std::string const& file, std::vector<std::string>& needed, + std::vector<std::string>& rpaths, std::vector<std::string>& runpaths) +{ + cmUVProcessChainBuilder builder; + builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT); + + std::vector<std::string> command; + if (!this->Archive->GetGetRuntimeDependenciesCommand("objdump", command)) { + this->SetError("Could not find objdump"); + return false; + } + command.emplace_back("-p"); + command.push_back(file); + builder.AddCommand(command); + + auto process = builder.Start(); + if (!process.Valid()) { + std::ostringstream e; + e << "Failed to start objdump process for:\n " << file; + this->SetError(e.str()); + return false; + } + + std::string line; + static const cmsys::RegularExpression neededRegex("^ *NEEDED *([^\n]*)$"); + static const cmsys::RegularExpression rpathRegex("^ *RPATH *([^\n]*)$"); + static const cmsys::RegularExpression runpathRegex("^ *RUNPATH *([^\n]*)$"); + while (std::getline(*process.OutputStream(), line)) { + cmsys::RegularExpressionMatch match; + if (neededRegex.find(line.c_str(), match)) { + needed.push_back(match.match(1)); + } else if (rpathRegex.find(line.c_str(), match)) { + std::vector<std::string> rpathSplit = + cmSystemTools::SplitString(match.match(1), ':'); + rpaths.reserve(rpaths.size() + rpathSplit.size()); + for (auto const& rpath : rpathSplit) { + rpaths.push_back(rpath); + } + } else if (runpathRegex.find(line.c_str(), match)) { + std::vector<std::string> runpathSplit = + cmSystemTools::SplitString(match.match(1), ':'); + runpaths.reserve(runpaths.size() + runpathSplit.size()); + for (auto const& runpath : runpathSplit) { + runpaths.push_back(runpath); + } + } + } + + if (!process.Wait()) { + std::ostringstream e; + e << "Failed to wait on objdump process for:\n " << file; + this->SetError(e.str()); + return false; + } + auto status = process.GetStatus(); + if (!status[0] || status[0]->ExitStatus != 0) { + std::ostringstream e; + e << "Failed to run objdump on:\n " << file; + this->SetError(e.str()); + return false; + } + + return true; +} diff --git a/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h b/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h new file mode 100644 index 0000000..286337f --- /dev/null +++ b/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.h @@ -0,0 +1,26 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#ifndef cmBinUtilsLinuxELFGetRuntimeCollectDependenciesTool_h +#define cmBinUtilsLinuxELFGetRuntimeCollectDependenciesTool_h + +#include "cmBinUtilsLinuxELFGetRuntimeDependenciesTool.h" + +#include <string> +#include <vector> + +class cmRuntimeDependencyArchive; + +class cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool + : public cmBinUtilsLinuxELFGetRuntimeDependenciesTool +{ +public: + cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool( + cmRuntimeDependencyArchive* archive); + + bool GetFileInfo(std::string const& file, std::vector<std::string>& needed, + std::vector<std::string>& rpaths, + std::vector<std::string>& runpaths) override; +}; + +#endif // cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool_h diff --git a/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.cxx new file mode 100644 index 0000000..a296a47 --- /dev/null +++ b/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.cxx @@ -0,0 +1,19 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h" + +#include "cmRuntimeDependencyArchive.h" + +cmBinUtilsMacOSMachOGetRuntimeDependenciesTool:: + cmBinUtilsMacOSMachOGetRuntimeDependenciesTool( + cmRuntimeDependencyArchive* archive) + : Archive(archive) +{ +} + +void cmBinUtilsMacOSMachOGetRuntimeDependenciesTool::SetError( + const std::string& error) +{ + this->Archive->SetError(error); +} diff --git a/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h b/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h new file mode 100644 index 0000000..dbb2882 --- /dev/null +++ b/Source/cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h @@ -0,0 +1,29 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#ifndef cmBinUtilsMacOSMachOGetRuntimeDependenciesTool_h +#define cmBinUtilsMacOSMachOGetRuntimeDependenciesTool_h + +#include <string> +#include <vector> + +class cmRuntimeDependencyArchive; + +class cmBinUtilsMacOSMachOGetRuntimeDependenciesTool +{ +public: + cmBinUtilsMacOSMachOGetRuntimeDependenciesTool( + cmRuntimeDependencyArchive* archive); + virtual ~cmBinUtilsMacOSMachOGetRuntimeDependenciesTool() = default; + + virtual bool GetFileInfo(std::string const& file, + std::vector<std::string>& libs, + std::vector<std::string>& rpaths) = 0; + +protected: + cmRuntimeDependencyArchive* Archive; + + void SetError(const std::string& error); +}; + +#endif // cmBinUtilsMacOSMachOGetRuntimeDependenciesTool_h diff --git a/Source/cmBinUtilsMacOSMachOLinker.cxx b/Source/cmBinUtilsMacOSMachOLinker.cxx new file mode 100644 index 0000000..7ff8584 --- /dev/null +++ b/Source/cmBinUtilsMacOSMachOLinker.cxx @@ -0,0 +1,231 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmBinUtilsMacOSMachOLinker.h" + +#include "cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h" +#include "cmRuntimeDependencyArchive.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" + +#include <sstream> +#include <string> +#include <vector> + +#include "cm_memory.hxx" + +cmBinUtilsMacOSMachOLinker::cmBinUtilsMacOSMachOLinker( + cmRuntimeDependencyArchive* archive) + : cmBinUtilsLinker(archive) +{ +} + +bool cmBinUtilsMacOSMachOLinker::Prepare() +{ + std::string tool = this->Archive->GetGetRuntimeDependenciesTool(); + if (tool.empty()) { + tool = "otool"; + } + if (tool == "otool") { + this->Tool = + cm::make_unique<cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool>( + this->Archive); + } else { + std::ostringstream e; + e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL: " << tool; + this->SetError(e.str()); + return false; + } + + return true; +} + +bool cmBinUtilsMacOSMachOLinker::ScanDependencies( + std::string const& file, cmStateEnums::TargetType type) +{ + std::string executableFile; + if (type == cmStateEnums::EXECUTABLE) { + executableFile = file; + } else { + executableFile = this->Archive->GetBundleExecutable(); + } + std::string executablePath; + if (!executableFile.empty()) { + executablePath = cmSystemTools::GetFilenamePath(executableFile); + } + return this->ScanDependencies(file, executablePath); +} + +bool cmBinUtilsMacOSMachOLinker::ScanDependencies( + std::string const& file, std::string const& executablePath) +{ + std::vector<std::string> libs; + std::vector<std::string> rpaths; + if (!this->Tool->GetFileInfo(file, libs, rpaths)) { + return false; + } + + std::string loaderPath = cmSystemTools::GetFilenamePath(file); + return this->GetFileDependencies(libs, executablePath, loaderPath, rpaths); +} + +bool cmBinUtilsMacOSMachOLinker::GetFileDependencies( + std::vector<std::string> const& names, std::string const& executablePath, + std::string const& loaderPath, std::vector<std::string> const& rpaths) +{ + for (std::string const& name : names) { + if (!this->Archive->IsPreExcluded(name)) { + std::string path; + bool resolved; + if (!this->ResolveDependency(name, executablePath, loaderPath, rpaths, + path, resolved)) { + return false; + } + if (resolved) { + if (!this->Archive->IsPostExcluded(path)) { + auto filename = cmSystemTools::GetFilenameName(path); + bool unique; + this->Archive->AddResolvedPath(filename, path, unique); + if (unique && !this->ScanDependencies(path, executablePath)) { + return false; + } + } + } else { + this->Archive->AddUnresolvedPath(name); + } + } + } + + return true; +} + +bool cmBinUtilsMacOSMachOLinker::ResolveDependency( + std::string const& name, std::string const& executablePath, + std::string const& loaderPath, std::vector<std::string> const& rpaths, + std::string& path, bool& resolved) +{ + resolved = false; + if (cmHasLiteralPrefix(name, "@rpath/")) { + if (!this->ResolveRPathDependency(name, executablePath, loaderPath, rpaths, + path, resolved)) { + return false; + } + } else if (cmHasLiteralPrefix(name, "@loader_path/")) { + if (!this->ResolveLoaderPathDependency(name, loaderPath, path, resolved)) { + return false; + } + } else if (cmHasLiteralPrefix(name, "@executable_path/")) { + if (!this->ResolveExecutablePathDependency(name, executablePath, path, + resolved)) { + return false; + } + } else { + resolved = true; + path = name; + } + + if (resolved && !cmSystemTools::FileIsFullPath(path)) { + this->SetError("Resolved path is not absolute"); + return false; + } + + return true; +} + +bool cmBinUtilsMacOSMachOLinker::ResolveExecutablePathDependency( + std::string const& name, std::string const& executablePath, + std::string& path, bool& resolved) +{ + if (executablePath.empty()) { + resolved = false; + return true; + } + + // 16 is == "@executable_path".length() + path = name; + path.replace(0, 16, executablePath); + + if (!cmSystemTools::PathExists(path)) { + resolved = false; + return true; + } + + resolved = true; + return true; +} + +bool cmBinUtilsMacOSMachOLinker::ResolveLoaderPathDependency( + std::string const& name, std::string const& loaderPath, std::string& path, + bool& resolved) +{ + if (loaderPath.empty()) { + resolved = false; + return true; + } + + // 12 is "@loader_path".length(); + path = name; + path.replace(0, 12, loaderPath); + + if (!cmSystemTools::PathExists(path)) { + resolved = false; + return true; + } + + resolved = true; + return true; +} + +bool cmBinUtilsMacOSMachOLinker::ResolveRPathDependency( + std::string const& name, std::string const& executablePath, + std::string const& loaderPath, std::vector<std::string> const& rpaths, + std::string& path, bool& resolved) +{ + for (std::string const& rpath : rpaths) { + std::string searchFile = name; + searchFile.replace(0, 6, rpath); + if (cmHasLiteralPrefix(searchFile, "@loader_path/")) { + if (!this->ResolveLoaderPathDependency(searchFile, loaderPath, path, + resolved)) { + return false; + } + if (resolved) { + return true; + } + } else if (cmHasLiteralPrefix(searchFile, "@executable_path/")) { + if (!this->ResolveExecutablePathDependency(searchFile, executablePath, + path, resolved)) { + return false; + } + if (resolved) { + return true; + } + } else if (cmSystemTools::PathExists(searchFile)) { + /* + * paraphrasing @ben.boeckel: + * if /b/libB.dylib is supposed to be used, + * /a/libbB.dylib will be found first if it exists. CMake tries to + * sort rpath directories to avoid this, but sometimes there is no + * right answer. + * + * I believe it is possible to resolve this using otools -l + * then checking the LC_LOAD_DYLIB command whose name is + * equal to the value of search_file, UNLESS the build + * specifically sets the RPath to paths that will match + * duplicate libs; at this point can we just point to + * user error, or is there a reason why the advantages + * to this scenario outweigh its disadvantages? + * + * Also priority seems to be the order as passed in when compiled + * so as long as this method's resolution guarantees priority + * in that manner further checking should not be necessary? + */ + path = searchFile; + resolved = true; + return true; + } + } + + resolved = false; + return true; +} diff --git a/Source/cmBinUtilsMacOSMachOLinker.h b/Source/cmBinUtilsMacOSMachOLinker.h new file mode 100644 index 0000000..f4f309d --- /dev/null +++ b/Source/cmBinUtilsMacOSMachOLinker.h @@ -0,0 +1,59 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#ifndef cmBinUtilsMacOSMachOLinker_h +#define cmBinUtilsMacOSMachOLinker_h + +#include "cmBinUtilsLinker.h" +#include "cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h" +#include "cmStateTypes.h" + +#include <memory> +#include <string> +#include <vector> + +class cmRuntimeDependencyArchive; + +class cmBinUtilsMacOSMachOLinker : public cmBinUtilsLinker +{ +public: + cmBinUtilsMacOSMachOLinker(cmRuntimeDependencyArchive* archive); + + bool Prepare() override; + + bool ScanDependencies(std::string const& file, + cmStateEnums::TargetType type) override; + +private: + std::unique_ptr<cmBinUtilsMacOSMachOGetRuntimeDependenciesTool> Tool; + + bool ScanDependencies(std::string const& file, + std::string const& executablePath); + + bool GetFileDependencies(std::vector<std::string> const& names, + std::string const& executablePath, + std::string const& loaderPath, + std::vector<std::string> const& rpaths); + + bool ResolveDependency(std::string const& name, + std::string const& executablePath, + std::string const& loaderPath, + std::vector<std::string> const& rpaths, + std::string& path, bool& resolved); + + bool ResolveExecutablePathDependency(std::string const& name, + std::string const& executablePath, + std::string& path, bool& resolved); + + bool ResolveLoaderPathDependency(std::string const& name, + std::string const& loaderPath, + std::string& path, bool& resolved); + + bool ResolveRPathDependency(std::string const& name, + std::string const& executablePath, + std::string const& loaderPath, + std::vector<std::string> const& rpaths, + std::string& path, bool& resolved); +}; + +#endif // cmBinUtilsMacOSMachOLinker_h diff --git a/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx new file mode 100644 index 0000000..bab2382 --- /dev/null +++ b/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx @@ -0,0 +1,100 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h" + +#include "cmRuntimeDependencyArchive.h" +#include "cmUVProcessChain.h" + +#include <cmsys/RegularExpression.hxx> + +#include <sstream> + +cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool:: + cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool( + cmRuntimeDependencyArchive* archive) + : cmBinUtilsMacOSMachOGetRuntimeDependenciesTool(archive) +{ +} + +bool cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool::GetFileInfo( + std::string const& file, std::vector<std::string>& libs, + std::vector<std::string>& rpaths) +{ + std::vector<std::string> command; + if (!this->Archive->GetGetRuntimeDependenciesCommand("otool", command)) { + this->SetError("Could not find otool"); + return false; + } + command.emplace_back("-l"); + command.emplace_back(file); + + cmUVProcessChainBuilder builder; + builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT) + .AddCommand(command); + + auto process = builder.Start(); + if (!process.Valid()) { + std::ostringstream e; + e << "Failed to start otool process for:\n " << file; + this->SetError(e.str()); + return false; + } + + std::string line; + static const cmsys::RegularExpression rpathRegex("^ *cmd LC_RPATH$"); + static const cmsys::RegularExpression loadDylibRegex( + "^ *cmd LC_LOAD_DYLIB$"); + static const cmsys::RegularExpression pathRegex( + "^ *path (.*) \\(offset [0-9]+\\)$"); + static const cmsys::RegularExpression nameRegex( + "^ *name (.*) \\(offset [0-9]+\\)$"); + while (std::getline(*process.OutputStream(), line)) { + cmsys::RegularExpressionMatch cmdMatch; + if (rpathRegex.find(line.c_str(), cmdMatch)) { + if (!std::getline(*process.OutputStream(), line) || + !std::getline(*process.OutputStream(), line)) { + this->SetError("Invalid output from otool"); + return false; + } + + cmsys::RegularExpressionMatch pathMatch; + if (pathRegex.find(line.c_str(), pathMatch)) { + rpaths.push_back(pathMatch.match(1)); + } else { + this->SetError("Invalid output from otool"); + return false; + } + } else if (loadDylibRegex.find(line.c_str(), cmdMatch)) { + if (!std::getline(*process.OutputStream(), line) || + !std::getline(*process.OutputStream(), line)) { + this->SetError("Invalid output from otool"); + return false; + } + + cmsys::RegularExpressionMatch nameMatch; + if (nameRegex.find(line.c_str(), nameMatch)) { + libs.push_back(nameMatch.match(1)); + } else { + this->SetError("Invalid output from otool"); + return false; + } + } + } + + if (!process.Wait()) { + std::ostringstream e; + e << "Failed to wait on otool process for:\n " << file; + this->SetError(e.str()); + return false; + } + auto status = process.GetStatus(); + if (!status[0] || status[0]->ExitStatus != 0) { + std::ostringstream e; + e << "Failed to run otool on:\n " << file; + this->SetError(e.str()); + return false; + } + + return true; +} diff --git a/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h b/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h new file mode 100644 index 0000000..12bcbc1 --- /dev/null +++ b/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.h @@ -0,0 +1,25 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#ifndef cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool_h +#define cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool_h + +#include "cmBinUtilsMacOSMachOGetRuntimeDependenciesTool.h" + +#include <string> +#include <vector> + +class cmRuntimeDependencyArchive; + +class cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool + : public cmBinUtilsMacOSMachOGetRuntimeDependenciesTool +{ +public: + cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool( + cmRuntimeDependencyArchive* archive); + + bool GetFileInfo(std::string const& file, std::vector<std::string>& libs, + std::vector<std::string>& rpaths) override; +}; + +#endif // cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool_h diff --git a/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx new file mode 100644 index 0000000..2b35e30 --- /dev/null +++ b/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx @@ -0,0 +1,67 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h" +#include "cmRuntimeDependencyArchive.h" +#include "cmUVProcessChain.h" + +#include <cmsys/RegularExpression.hxx> + +#include <sstream> + +cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool:: + cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool( + cmRuntimeDependencyArchive* archive) + : cmBinUtilsWindowsPEGetRuntimeDependenciesTool(archive) +{ +} + +bool cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool::GetFileInfo( + const std::string& file, std::vector<std::string>& needed) +{ + cmUVProcessChainBuilder builder; + builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT); + + std::vector<std::string> command; + if (!this->Archive->GetGetRuntimeDependenciesCommand("dumpbin", command)) { + this->SetError("Could not find dumpbin"); + return false; + } + command.emplace_back("/dependents"); + command.push_back(file); + builder.AddCommand(command); + + auto process = builder.Start(); + if (!process.Valid()) { + std::ostringstream e; + e << "Failed to start dumpbin process for:\n " << file; + this->SetError(e.str()); + return false; + } + + std::string line; + static const cmsys::RegularExpression regex( + "^ ([^\n]*\\.[Dd][Ll][Ll])\r$"); + while (std::getline(*process.OutputStream(), line)) { + cmsys::RegularExpressionMatch match; + if (regex.find(line.c_str(), match)) { + needed.push_back(match.match(1)); + } + } + + if (!process.Wait()) { + std::ostringstream e; + e << "Failed to wait on dumpbin process for:\n " << file; + this->SetError(e.str()); + return false; + } + auto status = process.GetStatus(); + if (!status[0] || status[0]->ExitStatus != 0) { + std::ostringstream e; + e << "Failed to run dumpbin on:\n " << file; + this->SetError(e.str()); + return false; + } + + return true; +} diff --git a/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h b/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h new file mode 100644 index 0000000..4c17f8d --- /dev/null +++ b/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h @@ -0,0 +1,25 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#ifndef cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool_h +#define cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool_h + +#include "cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h" + +#include <string> +#include <vector> + +class cmRuntimeDependencyArchive; + +class cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool + : public cmBinUtilsWindowsPEGetRuntimeDependenciesTool +{ +public: + cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool( + cmRuntimeDependencyArchive* archive); + + bool GetFileInfo(const std::string& file, + std::vector<std::string>& needed) override; +}; + +#endif // cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool_h diff --git a/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.cxx new file mode 100644 index 0000000..f5a4431 --- /dev/null +++ b/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.cxx @@ -0,0 +1,18 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h" +#include "cmRuntimeDependencyArchive.h" + +cmBinUtilsWindowsPEGetRuntimeDependenciesTool:: + cmBinUtilsWindowsPEGetRuntimeDependenciesTool( + cmRuntimeDependencyArchive* archive) + : Archive(archive) +{ +} + +void cmBinUtilsWindowsPEGetRuntimeDependenciesTool::SetError( + const std::string& error) +{ + this->Archive->SetError(error); +} diff --git a/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h b/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h new file mode 100644 index 0000000..e9e402b --- /dev/null +++ b/Source/cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h @@ -0,0 +1,28 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#ifndef cmBinUtilsWindowsPEGetRuntimeDependenciesTool_h +#define cmBinUtilsWindowsPEGetRuntimeDependenciesTool_h + +#include <string> +#include <vector> + +class cmRuntimeDependencyArchive; + +class cmBinUtilsWindowsPEGetRuntimeDependenciesTool +{ +public: + cmBinUtilsWindowsPEGetRuntimeDependenciesTool( + cmRuntimeDependencyArchive* archive); + virtual ~cmBinUtilsWindowsPEGetRuntimeDependenciesTool() = default; + + virtual bool GetFileInfo(const std::string& file, + std::vector<std::string>& needed) = 0; + +protected: + cmRuntimeDependencyArchive* Archive; + + void SetError(const std::string& error); +}; + +#endif // cmBinUtilsWindowsPEGetRuntimeDependenciesTool_h diff --git a/Source/cmBinUtilsWindowsPELinker.cxx b/Source/cmBinUtilsWindowsPELinker.cxx new file mode 100644 index 0000000..5a9ad66 --- /dev/null +++ b/Source/cmBinUtilsWindowsPELinker.cxx @@ -0,0 +1,123 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmBinUtilsWindowsPELinker.h" + +#include "cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h" +#include "cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h" +#include "cmRuntimeDependencyArchive.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" + +#include <sstream> +#include <vector> + +#include "cm_memory.hxx" + +#ifdef _WIN32 +# include <windows.h> +#endif + +cmBinUtilsWindowsPELinker::cmBinUtilsWindowsPELinker( + cmRuntimeDependencyArchive* archive) + : cmBinUtilsLinker(archive) +{ +} + +bool cmBinUtilsWindowsPELinker::Prepare() +{ + std::string tool = this->Archive->GetGetRuntimeDependenciesTool(); + if (tool.empty()) { + std::vector<std::string> command; + if (this->Archive->GetGetRuntimeDependenciesCommand("dumpbin", command)) { + tool = "dumpbin"; + } else { + tool = "objdump"; + } + } + if (tool == "dumpbin") { + this->Tool = + cm::make_unique<cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool>( + this->Archive); + } else if (tool == "objdump") { + this->Tool = + cm::make_unique<cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool>( + this->Archive); + } else { + std::ostringstream e; + e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL: " << tool; + this->SetError(e.str()); + return false; + } + + return true; +} + +bool cmBinUtilsWindowsPELinker::ScanDependencies( + std::string const& file, cmStateEnums::TargetType /* unused */) +{ + std::vector<std::string> needed; + if (!this->Tool->GetFileInfo(file, needed)) { + return false; + } + for (auto& n : needed) { + n = cmSystemTools::LowerCase(n); + } + std::string origin = cmSystemTools::GetFilenamePath(file); + + for (auto const& lib : needed) { + if (!this->Archive->IsPreExcluded(lib)) { + std::string path; + bool resolved = false; + if (!this->ResolveDependency(lib, origin, path, resolved)) { + return false; + } + if (resolved) { + if (!this->Archive->IsPostExcluded(path)) { + bool unique; + this->Archive->AddResolvedPath(lib, path, unique); + if (unique && + !this->ScanDependencies(path, cmStateEnums::SHARED_LIBRARY)) { + return false; + } + } + } else { + this->Archive->AddUnresolvedPath(lib); + } + } + } + + return true; +} + +bool cmBinUtilsWindowsPELinker::ResolveDependency(std::string const& name, + std::string const& origin, + std::string& path, + bool& resolved) +{ + auto dirs = this->Archive->GetSearchDirectories(); + +#ifdef _WIN32 + char buf[MAX_PATH]; + unsigned int len; + if ((len = GetWindowsDirectoryA(buf, MAX_PATH)) > 0) { + dirs.insert(dirs.begin(), std::string(buf, len)); + } + if ((len = GetSystemDirectoryA(buf, MAX_PATH)) > 0) { + dirs.insert(dirs.begin(), std::string(buf, len)); + } +#endif + + dirs.insert(dirs.begin(), origin); + + for (auto const& searchPath : dirs) { + path = cmStrCat(searchPath, '/', name); + if (cmSystemTools::PathExists(path)) { + resolved = true; + return true; + } + } + + resolved = false; + return true; +} diff --git a/Source/cmBinUtilsWindowsPELinker.h b/Source/cmBinUtilsWindowsPELinker.h new file mode 100644 index 0000000..8d2bf4b --- /dev/null +++ b/Source/cmBinUtilsWindowsPELinker.h @@ -0,0 +1,33 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#ifndef cmBinUtilsWindowsPELinker_h +#define cmBinUtilsWindowsPELinker_h + +#include "cmBinUtilsLinker.h" +#include "cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h" +#include "cmStateTypes.h" + +#include <memory> +#include <string> + +class cmRuntimeDependencyArchive; + +class cmBinUtilsWindowsPELinker : public cmBinUtilsLinker +{ +public: + cmBinUtilsWindowsPELinker(cmRuntimeDependencyArchive* archive); + + bool Prepare() override; + + bool ScanDependencies(std::string const& file, + cmStateEnums::TargetType type) override; + +private: + std::unique_ptr<cmBinUtilsWindowsPEGetRuntimeDependenciesTool> Tool; + + bool ResolveDependency(std::string const& name, std::string const& origin, + std::string& path, bool& resolved); +}; + +#endif // cmBinUtilsWindowsPELinker_h diff --git a/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx new file mode 100644 index 0000000..1f27003 --- /dev/null +++ b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx @@ -0,0 +1,67 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h" +#include "cmRuntimeDependencyArchive.h" +#include "cmUVProcessChain.h" + +#include <cmsys/RegularExpression.hxx> + +#include <sstream> + +cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool:: + cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool( + cmRuntimeDependencyArchive* archive) + : cmBinUtilsWindowsPEGetRuntimeDependenciesTool(archive) +{ +} + +bool cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool::GetFileInfo( + const std::string& file, std::vector<std::string>& needed) +{ + cmUVProcessChainBuilder builder; + builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT); + + std::vector<std::string> command; + if (!this->Archive->GetGetRuntimeDependenciesCommand("objdump", command)) { + this->SetError("Could not find objdump"); + return false; + } + command.emplace_back("-p"); + command.push_back(file); + builder.AddCommand(command); + + auto process = builder.Start(); + if (!process.Valid()) { + std::ostringstream e; + e << "Failed to start objdump process for:\n " << file; + this->SetError(e.str()); + return false; + } + + std::string line; + static const cmsys::RegularExpression regex( + "^\t*DLL Name: ([^\n]*\\.[Dd][Ll][Ll])\r$"); + while (std::getline(*process.OutputStream(), line)) { + cmsys::RegularExpressionMatch match; + if (regex.find(line.c_str(), match)) { + needed.push_back(match.match(1)); + } + } + + if (!process.Wait()) { + std::ostringstream e; + e << "Failed to wait on objdump process for:\n " << file; + this->SetError(e.str()); + return false; + } + auto status = process.GetStatus(); + if (!status[0] || status[0]->ExitStatus != 0) { + std::ostringstream e; + e << "Failed to run objdump on:\n " << file; + this->SetError(e.str()); + return false; + } + + return true; +} diff --git a/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h new file mode 100644 index 0000000..1d1a5b0 --- /dev/null +++ b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h @@ -0,0 +1,25 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#ifndef cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool_h +#define cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool_h + +#include "cmBinUtilsWindowsPEGetRuntimeDependenciesTool.h" + +#include <string> +#include <vector> + +class cmRuntimeDependencyArchive; + +class cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool + : public cmBinUtilsWindowsPEGetRuntimeDependenciesTool +{ +public: + cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool( + cmRuntimeDependencyArchive* archive); + + bool GetFileInfo(const std::string& file, + std::vector<std::string>& needed) override; +}; + +#endif // cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool_h diff --git a/Source/cmBreakCommand.cxx b/Source/cmBreakCommand.cxx index d07898f..95db689 100644 --- a/Source/cmBreakCommand.cxx +++ b/Source/cmBreakCommand.cxx @@ -10,14 +10,14 @@ #include "cmPolicies.h" // cmBreakCommand -bool cmBreakCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) +bool cmBreakCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { - if (!this->Makefile->IsLoopBlock()) { + if (!status.GetMakefile().IsLoopBlock()) { bool issueMessage = true; std::ostringstream e; MessageType messageType = MessageType::AUTHOR_WARNING; - switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0055)) { + switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0055)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0055) << "\n"; break; @@ -34,7 +34,7 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const& args, if (issueMessage) { e << "A BREAK command was found outside of a proper " "FOREACH or WHILE loop scope."; - this->Makefile->IssueMessage(messageType, e.str()); + status.GetMakefile().IssueMessage(messageType, e.str()); if (messageType == MessageType::FATAL_ERROR) { return false; } @@ -47,7 +47,7 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const& args, bool issueMessage = true; std::ostringstream e; MessageType messageType = MessageType::AUTHOR_WARNING; - switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0055)) { + switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0055)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0055) << "\n"; break; @@ -63,7 +63,7 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const& args, if (issueMessage) { e << "The BREAK command does not accept any arguments."; - this->Makefile->IssueMessage(messageType, e.str()); + status.GetMakefile().IssueMessage(messageType, e.str()); if (messageType == MessageType::FATAL_ERROR) { return false; } diff --git a/Source/cmBreakCommand.h b/Source/cmBreakCommand.h index 3b18567..e6ce6fe 100644 --- a/Source/cmBreakCommand.h +++ b/Source/cmBreakCommand.h @@ -8,29 +8,14 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmBreakCommand +/** * \brief Break from an enclosing foreach or while loop * * cmBreakCommand returns from an enclosing foreach or while loop */ -class cmBreakCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmBreakCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmBreakCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx index 428a0b2..e9e1d49 100644 --- a/Source/cmBuildCommand.cxx +++ b/Source/cmBuildCommand.cxx @@ -92,7 +92,7 @@ bool cmBuildCommand::MainSignature(std::vector<std::string> const& args) this->Makefile->GetGlobalGenerator()->GenerateCMakeBuildCommand( target, configuration, "", this->Makefile->IgnoreErrorsCMP0061()); - this->Makefile->AddDefinition(variable, makecommand.c_str()); + this->Makefile->AddDefinition(variable, makecommand); return true; } diff --git a/Source/cmBuildCommand.h b/Source/cmBuildCommand.h index e0529a4..d373103 100644 --- a/Source/cmBuildCommand.h +++ b/Source/cmBuildCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -23,7 +25,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmBuildCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmBuildCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmBuildNameCommand.cxx b/Source/cmBuildNameCommand.cxx index ddff686..df94f1d 100644 --- a/Source/cmBuildNameCommand.cxx +++ b/Source/cmBuildNameCommand.cxx @@ -5,21 +5,20 @@ #include "cmsys/RegularExpression.hxx" #include <algorithm> +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmStateTypes.h" #include "cmSystemTools.h" -class cmExecutionStatus; - -// cmBuildNameCommand -bool cmBuildNameCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmBuildNameCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } - const char* cacheValue = this->Makefile->GetDefinition(args[0]); + cmMakefile& mf = status.GetMakefile(); + const char* cacheValue = mf.GetDefinition(args[0]); if (cacheValue) { // do we need to correct the value? cmsys::RegularExpression reg("[()/]"); @@ -28,14 +27,14 @@ bool cmBuildNameCommand::InitialPass(std::vector<std::string> const& args, std::replace(cv.begin(), cv.end(), '/', '_'); std::replace(cv.begin(), cv.end(), '(', '_'); std::replace(cv.begin(), cv.end(), ')', '_'); - this->Makefile->AddCacheDefinition(args[0], cv.c_str(), "Name of build.", - cmStateEnums::STRING); + mf.AddCacheDefinition(args[0], cv.c_str(), "Name of build.", + cmStateEnums::STRING); } return true; } std::string buildname = "WinNT"; - if (this->Makefile->GetDefinition("UNIX")) { + if (mf.GetDefinition("UNIX")) { buildname.clear(); cmSystemTools::RunSingleCommand("uname -a", &buildname, &buildname); if (!buildname.empty()) { @@ -47,14 +46,14 @@ bool cmBuildNameCommand::InitialPass(std::vector<std::string> const& args, } } std::string compiler = "${CMAKE_CXX_COMPILER}"; - this->Makefile->ExpandVariablesInString(compiler); + mf.ExpandVariablesInString(compiler); buildname += "-"; buildname += cmSystemTools::GetFilenameName(compiler); std::replace(buildname.begin(), buildname.end(), '/', '_'); std::replace(buildname.begin(), buildname.end(), '(', '_'); std::replace(buildname.begin(), buildname.end(), ')', '_'); - this->Makefile->AddCacheDefinition(args[0], buildname.c_str(), - "Name of build.", cmStateEnums::STRING); + mf.AddCacheDefinition(args[0], buildname.c_str(), "Name of build.", + cmStateEnums::STRING); return true; } diff --git a/Source/cmBuildNameCommand.h b/Source/cmBuildNameCommand.h index 4bb72d1..37a7268 100644 --- a/Source/cmBuildNameCommand.h +++ b/Source/cmBuildNameCommand.h @@ -8,16 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -class cmBuildNameCommand : public cmCommand -{ -public: - cmCommand* Clone() override { return new cmBuildNameCommand; } - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmBuildNameCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 54f08bb..974b984 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -2,8 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCMakeHostSystemInformationCommand.h" -#include <sstream> +#include <stddef.h> +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmsys/SystemInformation.hxx" @@ -16,16 +17,22 @@ # define HAVE_VS_SETUP_HELPER #endif -class cmExecutionStatus; +namespace { +bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info, + std::string const& key, std::string& value); +std::string ValueToString(size_t value); +std::string ValueToString(const char* value); +std::string ValueToString(std::string const& value); +} // cmCMakeHostSystemInformation -bool cmCMakeHostSystemInformationCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { size_t current_index = 0; if (args.size() < (current_index + 2) || args[current_index] != "RESULT") { - this->SetError("missing RESULT specification."); + status.SetError("missing RESULT specification."); return false; } @@ -33,7 +40,7 @@ bool cmCMakeHostSystemInformationCommand::InitialPass( current_index += 2; if (args.size() < (current_index + 2) || args[current_index] != "QUERY") { - this->SetError("missing QUERY specification"); + status.SetError("missing QUERY specification"); return false; } @@ -49,89 +56,91 @@ bool cmCMakeHostSystemInformationCommand::InitialPass( result_list += ";"; } std::string value; - if (!this->GetValue(info, key, value)) { + if (!GetValue(status, info, key, value)) { return false; } result_list += value; } - this->Makefile->AddDefinition(variable, result_list.c_str()); + status.GetMakefile().AddDefinition(variable, result_list); return true; } -bool cmCMakeHostSystemInformationCommand::GetValue( - cmsys::SystemInformation& info, std::string const& key, std::string& value) +namespace { + +bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info, + std::string const& key, std::string& value) { if (key == "NUMBER_OF_LOGICAL_CORES") { - value = this->ValueToString(info.GetNumberOfLogicalCPU()); + value = ValueToString(info.GetNumberOfLogicalCPU()); } else if (key == "NUMBER_OF_PHYSICAL_CORES") { - value = this->ValueToString(info.GetNumberOfPhysicalCPU()); + value = ValueToString(info.GetNumberOfPhysicalCPU()); } else if (key == "HOSTNAME") { - value = this->ValueToString(info.GetHostname()); + value = ValueToString(info.GetHostname()); } else if (key == "FQDN") { - value = this->ValueToString(info.GetFullyQualifiedDomainName()); + value = ValueToString(info.GetFullyQualifiedDomainName()); } else if (key == "TOTAL_VIRTUAL_MEMORY") { - value = this->ValueToString(info.GetTotalVirtualMemory()); + value = ValueToString(info.GetTotalVirtualMemory()); } else if (key == "AVAILABLE_VIRTUAL_MEMORY") { - value = this->ValueToString(info.GetAvailableVirtualMemory()); + value = ValueToString(info.GetAvailableVirtualMemory()); } else if (key == "TOTAL_PHYSICAL_MEMORY") { - value = this->ValueToString(info.GetTotalPhysicalMemory()); + value = ValueToString(info.GetTotalPhysicalMemory()); } else if (key == "AVAILABLE_PHYSICAL_MEMORY") { - value = this->ValueToString(info.GetAvailablePhysicalMemory()); + value = ValueToString(info.GetAvailablePhysicalMemory()); } else if (key == "IS_64BIT") { - value = this->ValueToString(info.Is64Bits()); + value = ValueToString(info.Is64Bits()); } else if (key == "HAS_FPU") { - value = this->ValueToString( + value = ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_FPU)); } else if (key == "HAS_MMX") { - value = this->ValueToString( + value = ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_MMX)); } else if (key == "HAS_MMX_PLUS") { - value = this->ValueToString(info.DoesCPUSupportFeature( + value = ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_MMX_PLUS)); } else if (key == "HAS_SSE") { - value = this->ValueToString( + value = ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE)); } else if (key == "HAS_SSE2") { - value = this->ValueToString( + value = ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE2)); } else if (key == "HAS_SSE_FP") { - value = this->ValueToString(info.DoesCPUSupportFeature( + value = ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_SSE_FP)); } else if (key == "HAS_SSE_MMX") { - value = this->ValueToString(info.DoesCPUSupportFeature( + value = ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_SSE_MMX)); } else if (key == "HAS_AMD_3DNOW") { - value = this->ValueToString(info.DoesCPUSupportFeature( + value = ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW)); } else if (key == "HAS_AMD_3DNOW_PLUS") { - value = this->ValueToString(info.DoesCPUSupportFeature( + value = ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW_PLUS)); } else if (key == "HAS_IA64") { - value = this->ValueToString( + value = ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_IA64)); } else if (key == "HAS_SERIAL_NUMBER") { - value = this->ValueToString(info.DoesCPUSupportFeature( + value = ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_SERIALNUMBER)); } else if (key == "PROCESSOR_NAME") { - value = this->ValueToString(info.GetExtendedProcessorName()); + value = ValueToString(info.GetExtendedProcessorName()); } else if (key == "PROCESSOR_DESCRIPTION") { value = info.GetCPUDescription(); } else if (key == "PROCESSOR_SERIAL_NUMBER") { - value = this->ValueToString(info.GetProcessorSerialNumber()); + value = ValueToString(info.GetProcessorSerialNumber()); } else if (key == "OS_NAME") { - value = this->ValueToString(info.GetOSName()); + value = ValueToString(info.GetOSName()); } else if (key == "OS_RELEASE") { - value = this->ValueToString(info.GetOSRelease()); + value = ValueToString(info.GetOSRelease()); } else if (key == "OS_VERSION") { - value = this->ValueToString(info.GetOSVersion()); + value = ValueToString(info.GetOSVersion()); } else if (key == "OS_PLATFORM") { - value = this->ValueToString(info.GetOSPlatform()); + value = ValueToString(info.GetOSPlatform()); #ifdef HAVE_VS_SETUP_HELPER } else if (key == "VS_15_DIR") { // If generating for the VS 15 IDE, use the same instance. - cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); + cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator(); if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 15 ")) { cmGlobalVisualStudioVersionedGenerator* vs15gen = static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); @@ -147,7 +156,7 @@ bool cmCMakeHostSystemInformationCommand::GetValue( } } else if (key == "VS_16_DIR") { // If generating for the VS 16 IDE, use the same instance. - cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); + cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator(); if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 16 ")) { cmGlobalVisualStudioVersionedGenerator* vs16gen = static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); @@ -164,30 +173,26 @@ bool cmCMakeHostSystemInformationCommand::GetValue( #endif } else { std::string e = "does not recognize <key> " + key; - this->SetError(e); + status.SetError(e); return false; } return true; } -std::string cmCMakeHostSystemInformationCommand::ValueToString( - size_t value) const +std::string ValueToString(size_t value) { - std::ostringstream tmp; - tmp << value; - return tmp.str(); + return std::to_string(value); } -std::string cmCMakeHostSystemInformationCommand::ValueToString( - const char* value) const +std::string ValueToString(const char* value) { std::string safe_string = value ? value : ""; return safe_string; } -std::string cmCMakeHostSystemInformationCommand::ValueToString( - std::string const& value) const +std::string ValueToString(std::string const& value) { return value; } +} diff --git a/Source/cmCMakeHostSystemInformationCommand.h b/Source/cmCMakeHostSystemInformationCommand.h index b871641..79e3f27 100644 --- a/Source/cmCMakeHostSystemInformationCommand.h +++ b/Source/cmCMakeHostSystemInformationCommand.h @@ -5,48 +5,18 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <stddef.h> #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -namespace cmsys { -class SystemInformation; -} // namespace cmsys -/** \class cmCMakeHostSystemInformationCommand +/** * \brief Query host system specific information * * cmCMakeHostSystemInformationCommand queries system information of * the system on which CMake runs. */ -class cmCMakeHostSystemInformationCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override - { - return new cmCMakeHostSystemInformationCommand; - } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - bool GetValue(cmsys::SystemInformation& info, std::string const& key, - std::string& value); - - std::string ValueToString(size_t value) const; - std::string ValueToString(const char* value) const; - std::string ValueToString(std::string const& value) const; -}; +bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmCMakeMinimumRequired.cxx b/Source/cmCMakeMinimumRequired.cxx index 4b4bca2..f93c266 100644 --- a/Source/cmCMakeMinimumRequired.cxx +++ b/Source/cmCMakeMinimumRequired.cxx @@ -5,26 +5,32 @@ #include <sstream> #include <stdio.h> +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmSystemTools.h" #include "cmVersion.h" -class cmExecutionStatus; +namespace { +bool EnforceUnknownArguments(std::string const& version_max, + std::vector<std::string> const& unknown_arguments, + cmExecutionStatus& status); +} // cmCMakeMinimumRequired -bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmCMakeMinimumRequired(std::vector<std::string> const& args, + cmExecutionStatus& status) { // Process arguments. std::string version_string; bool doing_version = false; + std::vector<std::string> unknown_arguments; for (std::string const& arg : args) { if (arg == "VERSION") { doing_version = true; } else if (arg == "FATAL_ERROR") { if (doing_version) { - this->SetError("called with no value for VERSION."); + status.SetError("called with no value for VERSION."); return false; } doing_version = false; @@ -32,17 +38,17 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args, doing_version = false; version_string = arg; } else { - this->UnknownArguments.push_back(arg); + unknown_arguments.push_back(arg); } } if (doing_version) { - this->SetError("called with no value for VERSION."); + status.SetError("called with no value for VERSION."); return false; } // Make sure there was a version to check. if (version_string.empty()) { - return this->EnforceUnknownArguments(std::string()); + return EnforceUnknownArguments(std::string(), unknown_arguments, status); } // Separate the <min> version and any trailing ...<max> component. @@ -56,13 +62,13 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args, std::ostringstream e; e << "VERSION \"" << version_string << R"(" does not have a version on both sides of "...".)"; - this->SetError(e.str()); + status.SetError(e.str()); return false; } // Save the required version string. - this->Makefile->AddDefinition("CMAKE_MINIMUM_REQUIRED_VERSION", - version_min.c_str()); + status.GetMakefile().AddDefinition("CMAKE_MINIMUM_REQUIRED_VERSION", + version_min); // Get the current version number. unsigned int current_major = cmVersion::GetMajorVersion(); @@ -80,7 +86,7 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args, &required_minor, &required_patch, &required_tweak) < 2) { std::ostringstream e; e << "could not parse VERSION \"" << version_min << "\"."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } @@ -96,32 +102,34 @@ bool cmCMakeMinimumRequired::InitialPass(std::vector<std::string> const& args, e << "CMake " << version_min << " or higher is required. You are running version " << cmVersion::GetCMakeVersion(); - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return true; } // The version is not from the future, so enforce unknown arguments. - if (!this->EnforceUnknownArguments(version_max)) { + if (!EnforceUnknownArguments(version_max, unknown_arguments, status)) { return false; } if (required_major < 2 || (required_major == 2 && required_minor < 4)) { - this->Makefile->IssueMessage( + status.GetMakefile().IssueMessage( MessageType::AUTHOR_WARNING, "Compatibility with CMake < 2.4 is not supported by CMake >= 3.0."); - this->Makefile->SetPolicyVersion("2.4", version_max); + status.GetMakefile().SetPolicyVersion("2.4", version_max); } else { - this->Makefile->SetPolicyVersion(version_min, version_max); + status.GetMakefile().SetPolicyVersion(version_min, version_max); } return true; } -bool cmCMakeMinimumRequired::EnforceUnknownArguments( - std::string const& version_max) +namespace { +bool EnforceUnknownArguments(std::string const& version_max, + std::vector<std::string> const& unknown_arguments, + cmExecutionStatus& status) { - if (this->UnknownArguments.empty()) { + if (unknown_arguments.empty()) { return true; } @@ -150,7 +158,8 @@ bool cmCMakeMinimumRequired::EnforceUnknownArguments( } std::ostringstream e; - e << "called with unknown argument \"" << this->UnknownArguments[0] << "\"."; - this->SetError(e.str()); + e << "called with unknown argument \"" << unknown_arguments[0] << "\"."; + status.SetError(e.str()); return false; } +} diff --git a/Source/cmCMakeMinimumRequired.h b/Source/cmCMakeMinimumRequired.h index f9b61e1..53f78f6 100644 --- a/Source/cmCMakeMinimumRequired.h +++ b/Source/cmCMakeMinimumRequired.h @@ -8,33 +8,14 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmCMakeMinimumRequired +/** * \brief cmake_minimum_required command * * cmCMakeMinimumRequired implements the cmake_minimum_required CMake command */ -class cmCMakeMinimumRequired : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmCMakeMinimumRequired; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - std::vector<std::string> UnknownArguments; - bool EnforceUnknownArguments(std::string const& version_max); -}; +bool cmCMakeMinimumRequired(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx index 8da5ef7..9b1aea9 100644 --- a/Source/cmCMakePolicyCommand.cxx +++ b/Source/cmCMakePolicyCommand.cxx @@ -4,88 +4,101 @@ #include <sstream> +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" #include "cmState.h" #include "cmStateTypes.h" -class cmExecutionStatus; +namespace { +bool HandleSetMode(std::vector<std::string> const& args, + cmExecutionStatus& status); +bool HandleGetMode(std::vector<std::string> const& args, + cmExecutionStatus& status); +bool HandleVersionMode(std::vector<std::string> const& args, + cmExecutionStatus& status); +bool HandleGetWarningMode(std::vector<std::string> const& args, + cmExecutionStatus& status); +} // cmCMakePolicyCommand -bool cmCMakePolicyCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmCMakePolicyCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("requires at least one argument."); + status.SetError("requires at least one argument."); return false; } if (args[0] == "SET") { - return this->HandleSetMode(args); + return HandleSetMode(args, status); } if (args[0] == "GET") { - return this->HandleGetMode(args); + return HandleGetMode(args, status); } if (args[0] == "PUSH") { if (args.size() > 1) { - this->SetError("PUSH may not be given additional arguments."); + status.SetError("PUSH may not be given additional arguments."); return false; } - this->Makefile->PushPolicy(); + status.GetMakefile().PushPolicy(); return true; } if (args[0] == "POP") { if (args.size() > 1) { - this->SetError("POP may not be given additional arguments."); + status.SetError("POP may not be given additional arguments."); return false; } - this->Makefile->PopPolicy(); + status.GetMakefile().PopPolicy(); return true; } if (args[0] == "VERSION") { - return this->HandleVersionMode(args); + return HandleVersionMode(args, status); } if (args[0] == "GET_WARNING") { - return this->HandleGetWarningMode(args); + return HandleGetWarningMode(args, status); } std::ostringstream e; e << "given unknown first argument \"" << args[0] << "\""; - this->SetError(e.str()); + status.SetError(e.str()); return false; } -bool cmCMakePolicyCommand::HandleSetMode(std::vector<std::string> const& args) +namespace { + +bool HandleSetMode(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 3) { - this->SetError("SET must be given exactly 2 additional arguments."); + status.SetError("SET must be given exactly 2 additional arguments."); return false; } - cmPolicies::PolicyStatus status; + cmPolicies::PolicyStatus policyStatus; if (args[2] == "OLD") { - status = cmPolicies::OLD; + policyStatus = cmPolicies::OLD; } else if (args[2] == "NEW") { - status = cmPolicies::NEW; + policyStatus = cmPolicies::NEW; } else { std::ostringstream e; e << "SET given unrecognized policy status \"" << args[2] << "\""; - this->SetError(e.str()); + status.SetError(e.str()); return false; } - if (!this->Makefile->SetPolicy(args[1].c_str(), status)) { - this->SetError("SET failed to set policy."); + if (!status.GetMakefile().SetPolicy(args[1].c_str(), policyStatus)) { + status.SetError("SET failed to set policy."); return false; } if (args[1] == "CMP0001" && - (status == cmPolicies::WARN || status == cmPolicies::OLD)) { - if (!(this->Makefile->GetState()->GetInitializedCacheValue( + (policyStatus == cmPolicies::WARN || policyStatus == cmPolicies::OLD)) { + if (!(status.GetMakefile().GetState()->GetInitializedCacheValue( "CMAKE_BACKWARDS_COMPATIBILITY"))) { // Set it to 2.4 because that is the last version where the // variable had meaning. - this->Makefile->AddCacheDefinition( + status.GetMakefile().AddCacheDefinition( "CMAKE_BACKWARDS_COMPATIBILITY", "2.4", "For backwards compatibility, what version of CMake " "commands and " @@ -96,14 +109,15 @@ bool cmCMakePolicyCommand::HandleSetMode(std::vector<std::string> const& args) return true; } -bool cmCMakePolicyCommand::HandleGetMode(std::vector<std::string> const& args) +bool HandleGetMode(std::vector<std::string> const& args, + cmExecutionStatus& status) { bool parent_scope = false; if (args.size() == 4 && args[3] == "PARENT_SCOPE") { // Undocumented PARENT_SCOPE option for use within CMake. parent_scope = true; } else if (args.size() != 3) { - this->SetError("GET must be given exactly 2 additional arguments."); + status.SetError("GET must be given exactly 2 additional arguments."); return false; } @@ -117,25 +131,25 @@ bool cmCMakePolicyCommand::HandleGetMode(std::vector<std::string> const& args) std::ostringstream e; e << "GET given policy \"" << id << "\" which is not known to this " << "version of CMake."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } // Lookup the policy setting. - cmPolicies::PolicyStatus status = - this->Makefile->GetPolicyStatus(pid, parent_scope); - switch (status) { + cmPolicies::PolicyStatus policyStatus = + status.GetMakefile().GetPolicyStatus(pid, parent_scope); + switch (policyStatus) { case cmPolicies::OLD: // Report that the policy is set to OLD. - this->Makefile->AddDefinition(var, "OLD"); + status.GetMakefile().AddDefinition(var, "OLD"); break; case cmPolicies::WARN: // Report that the policy is not set. - this->Makefile->AddDefinition(var, ""); + status.GetMakefile().AddDefinition(var, ""); break; case cmPolicies::NEW: // Report that the policy is set to NEW. - this->Makefile->AddDefinition(var, "NEW"); + status.GetMakefile().AddDefinition(var, "NEW"); break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: @@ -146,22 +160,22 @@ bool cmCMakePolicyCommand::HandleGetMode(std::vector<std::string> const& args) << "The call to cmake_policy(GET " << id << " ...) at which this " << "error appears requests the policy, and this version of CMake " << "requires that the policy be set to NEW before it is checked."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); } } return true; } -bool cmCMakePolicyCommand::HandleVersionMode( - std::vector<std::string> const& args) +bool HandleVersionMode(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() <= 1) { - this->SetError("VERSION not given an argument"); + status.SetError("VERSION not given an argument"); return false; } if (args.size() >= 3) { - this->SetError("VERSION given too many arguments"); + status.SetError("VERSION given too many arguments"); return false; } std::string const& version_string = args[1]; @@ -177,19 +191,19 @@ bool cmCMakePolicyCommand::HandleVersionMode( std::ostringstream e; e << "VERSION \"" << version_string << R"(" does not have a version on both sides of "...".)"; - this->SetError(e.str()); + status.SetError(e.str()); return false; } - this->Makefile->SetPolicyVersion(version_min, version_max); + status.GetMakefile().SetPolicyVersion(version_min, version_max); return true; } -bool cmCMakePolicyCommand::HandleGetWarningMode( - std::vector<std::string> const& args) +bool HandleGetWarningMode(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 3) { - this->SetError( + status.SetError( "GET_WARNING must be given exactly 2 additional arguments."); return false; } @@ -204,13 +218,13 @@ bool cmCMakePolicyCommand::HandleGetWarningMode( std::ostringstream e; e << "GET_WARNING given policy \"" << id << "\" which is not known to this version of CMake."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } // Lookup the policy warning. - this->Makefile->AddDefinition(var, - cmPolicies::GetPolicyWarning(pid).c_str()); + status.GetMakefile().AddDefinition(var, cmPolicies::GetPolicyWarning(pid)); return true; } +} diff --git a/Source/cmCMakePolicyCommand.h b/Source/cmCMakePolicyCommand.h index cca1406..ba9397d 100644 --- a/Source/cmCMakePolicyCommand.h +++ b/Source/cmCMakePolicyCommand.h @@ -8,36 +8,15 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmCMakePolicyCommand +/** * \brief Set how CMake should handle policies * * cmCMakePolicyCommand sets how CMake should deal with backwards * compatibility policies. */ -class cmCMakePolicyCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmCMakePolicyCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - bool HandleSetMode(std::vector<std::string> const& args); - bool HandleGetMode(std::vector<std::string> const& args); - bool HandleVersionMode(std::vector<std::string> const& args); - bool HandleGetWarningMode(std::vector<std::string> const& args); -}; +bool cmCMakePolicyCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index 255a8e6..f0c1845 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -65,8 +65,10 @@ unsigned int CCONV cmGetMinorVersion(void*) void CCONV cmAddDefinition(void* arg, const char* name, const char* value) { - cmMakefile* mf = static_cast<cmMakefile*>(arg); - mf->AddDefinition(name, value); + if (value) { + cmMakefile* mf = static_cast<cmMakefile*>(arg); + mf->AddDefinition(name, value); + } } /* Add a definition to this makefile and the global cmake cache. */ @@ -421,7 +423,7 @@ int CCONV cmExecuteCommand(void* arg, const char* name, int numArgs, // Assume all arguments are quoted. lff.Arguments.emplace_back(args[i], cmListFileArgument::Quoted, 0); } - cmExecutionStatus status; + cmExecutionStatus status(*mf); return mf->ExecuteCommand(lff, status); } @@ -606,7 +608,7 @@ int CCONV cmSourceFileGetPropertyAsBool(void* arg, const char* prop) if (cmSourceFile* rsf = sf->RealSourceFile) { return rsf->GetPropertyAsBool(prop) ? 1 : 0; } - return cmSystemTools::IsOn(cmSourceFileGetProperty(arg, prop)) ? 1 : 0; + return cmIsOn(cmSourceFileGetProperty(arg, prop)) ? 1 : 0; } void CCONV cmSourceFileSetProperty(void* arg, const char* prop, @@ -688,9 +690,7 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir, // Next, try the various source extensions for (std::string const& ext : sourceExts) { - hname = pathname; - hname += "."; - hname += ext; + hname = cmStrCat(pathname, '.', ext); if (cmSystemTools::FileExists(hname)) { sf->SourceExtension = ext; sf->FullPath = hname; @@ -700,9 +700,7 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir, // Finally, try the various header extensions for (std::string const& ext : headerExts) { - hname = pathname; - hname += "."; - hname += ext; + hname = cmStrCat(pathname, '.', ext); if (cmSystemTools::FileExists(hname)) { sf->SourceExtension = ext; sf->FullPath = hname; diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index d1226c3..14f0c0c 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -15,7 +15,6 @@ #include <ctype.h> #include <iostream> #include <map> -#include <memory> // IWYU pragma: keep #include <sstream> #include <stdio.h> #include <stdlib.h> @@ -30,6 +29,8 @@ # include <unistd.h> // IWYU pragma: keep #endif +#include "cm_memory.hxx" + #include "cmAlgorithms.h" #include "cmCTestBuildAndTestHandler.h" #include "cmCTestBuildHandler.h" @@ -51,6 +52,7 @@ #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVersion.h" #include "cmVersionConfig.h" @@ -153,7 +155,7 @@ struct cmCTest::Private bool TomorrowTag = false; int TestModel = cmCTest::EXPERIMENTAL; - std::string SpecificTrack; + std::string SpecificGroup; cmDuration TimeOut = cmDuration::zero(); @@ -321,12 +323,11 @@ cmCTest::cmCTest() { std::string envValue; if (cmSystemTools::GetEnv("CTEST_OUTPUT_ON_FAILURE", envValue)) { - this->Impl->OutputTestOutputOnTestFailure = - !cmSystemTools::IsOff(envValue); + this->Impl->OutputTestOutputOnTestFailure = !cmIsOff(envValue); } envValue.clear(); if (cmSystemTools::GetEnv("CTEST_PROGRESS_OUTPUT", envValue)) { - this->Impl->TestProgressOutput = !cmSystemTools::IsOff(envValue); + this->Impl->TestProgressOutput = !cmIsOff(envValue); } this->Impl->Parts[PartStart].SetName("Start"); @@ -507,10 +508,10 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) day != lctime->tm_mday) { tag.clear(); } - std::string track; - if (cmSystemTools::GetLineFromStream(tfin, track) && + std::string group; + if (cmSystemTools::GetLineFromStream(tfin, group) && !this->Impl->Parts[PartStart] && !command) { - this->Impl->SpecificTrack = track; + this->Impl->SpecificGroup = group; } std::string model; if (cmSystemTools::GetLineFromStream(tfin, model) && @@ -563,13 +564,13 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) } } } else { - std::string track; + std::string group; std::string modelStr; int model = cmCTest::UNKNOWN; if (tfin) { cmSystemTools::GetLineFromStream(tfin, tag); - cmSystemTools::GetLineFromStream(tfin, track); + cmSystemTools::GetLineFromStream(tfin, group); if (cmSystemTools::GetLineFromStream(tfin, modelStr)) { model = GetTestModelFromString(modelStr.c_str()); } @@ -604,15 +605,15 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) quiet); } - if (!this->Impl->SpecificTrack.empty() && - track != this->Impl->SpecificTrack) { + if (!this->Impl->SpecificGroup.empty() && + group != this->Impl->SpecificGroup) { cmCTestOptionalLog(this, WARNING, - "Track given in TAG does not match " - "track given in ctest_start()" + "Group given in TAG does not match " + "group given in ctest_start()" << std::endl, quiet); } else { - this->Impl->SpecificTrack = track; + this->Impl->SpecificGroup = group; } cmCTestOptionalLog(this, OUTPUT, @@ -640,12 +641,10 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command) cmMakefile* mf = command->GetMakefile(); std::string fname; - std::string src_dir_fname = src_dir; - src_dir_fname += "/CTestConfig.cmake"; + std::string src_dir_fname = cmStrCat(src_dir, "/CTestConfig.cmake"); cmSystemTools::ConvertToUnixSlashes(src_dir_fname); - std::string bld_dir_fname = bld_dir; - bld_dir_fname += "/CTestConfig.cmake"; + std::string bld_dir_fname = cmStrCat(bld_dir, "/CTestConfig.cmake"); cmSystemTools::ConvertToUnixSlashes(bld_dir_fname); if (cmSystemTools::FileExists(bld_dir_fname)) { @@ -661,8 +660,7 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command) command->ShouldBeQuiet()); bool readit = mf->ReadDependentFile(fname); if (!readit) { - std::string m = "Could not find include file: "; - m += fname; + std::string m = cmStrCat("Could not find include file: ", fname); command->SetError(m); return false; } @@ -752,7 +750,7 @@ bool cmCTest::UpdateCTestConfiguration() std::string const& testLoad = this->GetCTestConfiguration("TestLoad"); if (!testLoad.empty()) { unsigned long load; - if (cmSystemTools::StringToULong(testLoad.c_str(), &load)) { + if (cmStrToULong(testLoad, &load)) { this->SetTestLoad(load); } else { cmCTestLog(this, WARNING, @@ -761,7 +759,7 @@ bool cmCTest::UpdateCTestConfiguration() } if (this->Impl->ProduceXML) { this->Impl->CompressXMLFiles = - cmSystemTools::IsOn(this->GetCTestConfiguration("CompressSubmission")); + cmIsOn(this->GetCTestConfiguration("CompressSubmission")); } return true; } @@ -855,8 +853,7 @@ bool cmCTest::AddIfExists(Part part, const char* file) if (this->CTestFileExists(file)) { this->AddSubmitFile(part, file); } else { - std::string name = file; - name += ".gz"; + std::string name = cmStrCat(file, ".gz"); if (this->CTestFileExists(name)) { this->AddSubmitFile(part, file); } else { @@ -1020,8 +1017,8 @@ int cmCTest::ProcessSteps() std::string cmCTest::GetTestModelString() { - if (!this->Impl->SpecificTrack.empty()) { - return this->Impl->SpecificTrack; + if (!this->Impl->SpecificGroup.empty()) { + return this->Impl->SpecificGroup; } switch (this->Impl->TestModel) { case cmCTest::NIGHTLY: @@ -1098,9 +1095,10 @@ int cmCTest::RunMakeCommand(const std::string& command, std::string& output, cmProcessOutput processOutput(encoding); std::string strdata; cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, - " Each . represents " << tick_len << " bytes of output" - << std::endl - << " " << std::flush); + " Each . represents " << tick_len + << " bytes of output\n" + " " + << std::flush); while (cmsysProcess_WaitForData(cp, &data, &length, nullptr)) { processOutput.DecodeText(data, length, strdata); for (char& cc : strdata) { @@ -1115,8 +1113,7 @@ int cmCTest::RunMakeCommand(const std::string& command, std::string& output, if (tick % tick_line_len == 0 && tick > 0) { cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, " Size: " << int((double(output.size()) / 1024.0) + 1) - << "K" << std::endl - << " " << std::flush); + << "K\n " << std::flush); } } cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, @@ -1221,9 +1218,7 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output, timeout != cmCTest::MaxDuration() && timeout > cmDuration::zero()) { args.emplace_back("--test-timeout"); - std::ostringstream msg; - msg << cmDurationTo<unsigned int>(timeout); - args.push_back(msg.str()); + args.push_back(std::to_string(cmDurationTo<unsigned int>(timeout))); } args.emplace_back(i); } @@ -1319,23 +1314,19 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output, OutputTestErrors(tempOutput); } *retVal = cmsysProcess_GetExitException(cp); - std::string outerr = "\n*** Exception executing: "; - outerr += cmsysProcess_GetExceptionString(cp); + std::string outerr = cmStrCat("\n*** Exception executing: ", + cmsysProcess_GetExceptionString(cp)); if (output) { *output += outerr; } - cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, - outerr << std::endl - << std::flush); + cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl); } else if (result == cmsysProcess_State_Error) { - std::string outerr = "\n*** ERROR executing: "; - outerr += cmsysProcess_GetErrorString(cp); + std::string outerr = + cmStrCat("\n*** ERROR executing: ", cmsysProcess_GetErrorString(cp)); if (output) { *output += outerr; } - cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, - outerr << std::endl - << std::flush); + cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl); } cmsysProcess_Delete(cp); @@ -1455,8 +1446,7 @@ void cmCTest::AddSiteProperties(cmXMLWriter& xml) if (labels) { xml.StartElement("Labels"); std::string l = labels; - std::vector<std::string> args; - cmSystemTools::ExpandListArgument(l, args); + std::vector<std::string> args = cmExpandedList(l); for (std::string const& i : args) { xml.Element("Label", i); } @@ -1488,8 +1478,7 @@ std::vector<std::string> cmCTest::GetLabelsForSubprojects() { std::string labelsForSubprojects = this->GetCTestConfiguration("LabelsForSubprojects"); - std::vector<std::string> subprojects; - cmSystemTools::ExpandListArgument(labelsForSubprojects, subprojects); + std::vector<std::string> subprojects = cmExpandedList(labelsForSubprojects); // sort the array std::sort(subprojects.begin(), subprojects.end()); @@ -1856,7 +1845,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, } i++; long repeat = 1; - if (!cmSystemTools::StringToLong(args[i].c_str(), &repeat)) { + if (!cmStrToLong(args[i], &repeat)) { errormsg = "'--repeat-until-fail' given non-integer value '" + args[i] + "'"; return false; @@ -1870,7 +1859,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, if (this->CheckArgument(arg, "--test-load") && i < args.size() - 1) { i++; unsigned long load; - if (cmSystemTools::StringToULong(args[i].c_str(), &load)) { + if (cmStrToULong(args[i], &load)) { this->SetTestLoad(load); } else { cmCTestLog(this, WARNING, @@ -1911,9 +1900,15 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, this->Impl->Debug = true; this->Impl->ShowLineNumbers = true; } + if (this->CheckArgument(arg, "--group") && i < args.size() - 1) { + i++; + this->Impl->SpecificGroup = args[i]; + } + // This is an undocumented / deprecated option. + // "Track" has been renamed to "Group". if (this->CheckArgument(arg, "--track") && i < args.size() - 1) { i++; - this->Impl->SpecificTrack = args[i]; + this->Impl->SpecificGroup = args[i]; } if (this->CheckArgument(arg, "--show-line-numbers")) { this->Impl->ShowLineNumbers = true; @@ -1944,7 +1939,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, i < args.size() - 1) { i++; long outputSize; - if (cmSystemTools::StringToLong(args[i].c_str(), &outputSize)) { + if (cmStrToLong(args[i], &outputSize)) { this->Impl->TestHandler.SetTestOutputSizePassed(int(outputSize)); } else { cmCTestLog(this, WARNING, @@ -1956,7 +1951,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, i < args.size() - 1) { i++; long outputSize; - if (cmSystemTools::StringToLong(args[i].c_str(), &outputSize)) { + if (cmStrToLong(args[i], &outputSize)) { this->Impl->TestHandler.SetTestOutputSizeFailed(int(outputSize)); } else { cmCTestLog(this, WARNING, @@ -1967,7 +1962,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, if (this->CheckArgument(arg, "-N", "--show-only")) { this->Impl->ShowOnly = true; } - if (cmSystemTools::StringStartsWith(arg.c_str(), "--show-only=")) { + if (cmHasLiteralPrefix(arg, "--show-only=")) { this->Impl->ShowOnly = true; // Check if a specific format is requested. Defaults to human readable @@ -2003,7 +1998,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, if (this->CheckArgument(arg, "--interactive-debug-mode") && i < args.size() - 1) { i++; - this->Impl->InteractiveDebugMode = cmSystemTools::IsOn(args[i]); + this->Impl->InteractiveDebugMode = cmIsOn(args[i]); } if (this->CheckArgument(arg, "--submit-index") && i < args.size() - 1) { i++; @@ -2229,7 +2224,7 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output) // attempts are simply ignored since previous ctest versions ignore // this too. (As well as many other unknown command line args.) // - if (arg != "-D" && cmSystemTools::StringStartsWith(arg.c_str(), "-D")) { + if (arg != "-D" && cmHasLiteralPrefix(arg, "-D")) { std::string input = arg.substr(2); this->AddVariableDefinition(input); } @@ -2425,7 +2420,7 @@ int cmCTest::RunCMakeAndTest(std::string* output) cmCTestBuildAndTestHandler* handler = this->GetBuildAndTestHandler(); int retv = handler->ProcessHandler(); *output = handler->GetOutput(); -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP cmDynamicLoader::FlushCache(); #endif if (retv != 0) { @@ -2502,8 +2497,7 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf) "* Read custom CTest configuration directory: " << dir << std::endl); - std::string fname = dir; - fname += "/CTestCustom.cmake"; + std::string fname = cmStrCat(dir, "/CTestCustom.cmake"); cmCTestLog(this, DEBUG, "* Check for file: " << fname << std::endl); if (cmSystemTools::FileExists(fname)) { cmCTestLog(this, DEBUG, @@ -2523,8 +2517,7 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf) } } - std::string rexpr = dir; - rexpr += "/CTestCustom.ctest"; + std::string rexpr = cmStrCat(dir, "/CTestCustom.ctest"); cmCTestLog(this, DEBUG, "* Check for file: " << rexpr << std::endl); if (!found && cmSystemTools::FileExists(rexpr)) { cmsys::Glob gl; @@ -2567,7 +2560,7 @@ void cmCTest::PopulateCustomVector(cmMakefile* mf, const std::string& def, cmCTestLog(this, DEBUG, "PopulateCustomVector: " << def << std::endl); vec.clear(); - cmSystemTools::ExpandListArgument(dval, vec); + cmExpandList(dval, vec); for (std::string const& it : vec) { cmCTestLog(this, DEBUG, " -- " << it << std::endl); @@ -2676,8 +2669,7 @@ std::string cmCTest::GetSubmitURL() std::string site = this->GetCTestConfiguration("DropSite"); std::string location = this->GetCTestConfiguration("DropLocation"); - url = method.empty() ? "http" : method; - url += "://"; + url = cmStrCat(method.empty() ? "http" : method, "://"); if (!user.empty()) { url += user; if (!password.empty()) { @@ -2772,21 +2764,21 @@ std::vector<std::string>& cmCTest::GetInitialCommandLineArguments() return this->Impl->InitialCommandLineArguments; } -const char* cmCTest::GetSpecificTrack() +const char* cmCTest::GetSpecificGroup() { - if (this->Impl->SpecificTrack.empty()) { + if (this->Impl->SpecificGroup.empty()) { return nullptr; } - return this->Impl->SpecificTrack.c_str(); + return this->Impl->SpecificGroup.c_str(); } -void cmCTest::SetSpecificTrack(const char* track) +void cmCTest::SetSpecificGroup(const char* group) { - if (!track) { - this->Impl->SpecificTrack.clear(); + if (!group) { + this->Impl->SpecificGroup.clear(); return; } - this->Impl->SpecificTrack = track; + this->Impl->SpecificGroup = group; } void cmCTest::SetFailover(bool failover) @@ -3077,11 +3069,11 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg, } else { *this->Impl->OutputLogFile << cmCTestStringLogType[logType]; } - *this->Impl->OutputLogFile << "] " << std::endl << std::flush; + *this->Impl->OutputLogFile << "] " << std::endl; } *this->Impl->OutputLogFile << msg << std::flush; if (logType != this->Impl->OutputLogFileLastTag) { - *this->Impl->OutputLogFile << std::endl << std::flush; + *this->Impl->OutputLogFile << std::endl; this->Impl->OutputLogFileLastTag = logType; } } @@ -3194,7 +3186,7 @@ void cmCTest::OutputTestErrors(std::vector<char> const& process_output) if (!process_output.empty()) { test_outputs.append(process_output.data(), process_output.size()); } - cmCTestLog(this, HANDLER_OUTPUT, test_outputs << std::endl << std::flush); + cmCTestLog(this, HANDLER_OUTPUT, test_outputs << std::endl); } bool cmCTest::CompressString(std::string& str) diff --git a/Source/cmCTest.h b/Source/cmCTest.h index d300c33..7fe3455 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -10,7 +10,7 @@ #include <chrono> #include <map> -#include <memory> // IWYU pragma: keep +#include <memory> #include <sstream> #include <string> #include <time.h> @@ -404,9 +404,9 @@ public: std::vector<std::string>& GetInitialCommandLineArguments(); - /** Set the track to submit to */ - void SetSpecificTrack(const char* track); - const char* GetSpecificTrack(); + /** Set the group to submit to */ + void SetSpecificGroup(const char* group); + const char* GetSpecificGroup(); void SetFailover(bool failover); bool GetFailover() const; diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index 358f095..cf28cdb 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -14,6 +14,7 @@ #include "cmMessageType.h" #include "cmMessenger.h" #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVersion.h" @@ -25,9 +26,7 @@ cmCacheManager::cmCacheManager() void cmCacheManager::CleanCMakeFiles(const std::string& path) { - std::string glob = path; - glob += "/CMakeFiles"; - glob += "/*.cmake"; + std::string glob = cmStrCat(path, "/CMakeFiles/*.cmake"); cmsys::Glob globIt; globIt.FindFiles(glob); std::vector<std::string> files = globIt.GetFiles(); @@ -38,8 +37,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal, std::set<std::string>& excludes, std::set<std::string>& includes) { - std::string cacheFile = path; - cacheFile += "/CMakeCache.txt"; + std::string cacheFile = cmStrCat(path, "/CMakeCache.txt"); // clear the old cache, if we are reading in internal values if (internal) { this->Cache.clear(); @@ -104,12 +102,10 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal, // not visible in the gui if (!internal) { e.Type = cmStateEnums::INTERNAL; - helpString = "DO NOT EDIT, "; - helpString += entryKey; - helpString += " loaded from external file. " - "To change this value edit this file: "; - helpString += path; - helpString += "/CMakeCache.txt"; + helpString = cmStrCat("DO NOT EDIT, ", entryKey, + " loaded from external file. " + "To change this value edit this file: ", + path, "/CMakeCache.txt"); e.SetProperty("HELPSTRING", helpString.c_str()); } if (!this->ReadPropertyEntry(entryKey, e)) { @@ -214,14 +210,11 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i, { for (const char** p = cmCacheManager::PersistentProperties; *p; ++p) { if (const char* value = i.GetProperty(*p)) { - std::string helpstring = *p; - helpstring += " property for variable: "; - helpstring += i.GetName(); + std::string helpstring = + cmStrCat(*p, " property for variable: ", i.GetName()); cmCacheManager::OutputHelpString(os, helpstring); - std::string key = i.GetName(); - key += "-"; - key += *p; + std::string key = cmStrCat(i.GetName(), '-', *p); cmCacheManager::OutputKey(os, key); os << ":INTERNAL="; cmCacheManager::OutputValue(os, value); @@ -234,8 +227,7 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i, bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) { - std::string cacheFile = path; - cacheFile += "/CMakeCache.txt"; + std::string cacheFile = cmStrCat(path, "/CMakeCache.txt"); cmGeneratedFileStream fout(cacheFile); fout.SetCopyIfDifferent(true); if (!fout) { @@ -356,8 +348,7 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) } fout << "\n"; fout.Close(); - std::string checkCacheFile = path; - checkCacheFile += "/CMakeFiles"; + std::string checkCacheFile = cmStrCat(path, "/CMakeFiles"); cmSystemTools::MakeDirectory(checkCacheFile); checkCacheFile += "/cmake.check_cache"; cmsys::ofstream checkCache(checkCacheFile.c_str()); @@ -473,15 +464,14 @@ void cmCacheManager::OutputNewlineTruncationWarning(std::ostream& fout, { if (value.find('\n') != std::string::npos) { if (messenger) { - std::string message = "Value of "; - message += key; - message += " contained a newline; truncating"; + std::string message = + cmStrCat("Value of ", key, " contained a newline; truncating"); messenger->IssueMessage(MessageType::WARNING, message); } - std::string comment = "WARNING: Value of "; - comment += key; - comment += " contained a newline and was truncated. Original value:"; + std::string comment = + cmStrCat("WARNING: Value of ", key, + " contained a newline and was truncated. Original value:"); OutputWarningComment(fout, comment, true); OutputWarningComment(fout, value, false); @@ -551,8 +541,7 @@ void cmCacheManager::AddCacheEntry(const std::string& key, const char* value, // make sure we only use unix style paths if (type == cmStateEnums::FILEPATH || type == cmStateEnums::PATH) { if (e.Value.find(';') != std::string::npos) { - std::vector<std::string> paths; - cmSystemTools::ExpandListArgument(e.Value, paths); + std::vector<std::string> paths = cmExpandedList(e.Value); const char* sep = ""; e.Value = ""; for (std::string& i : paths) { @@ -615,12 +604,12 @@ void cmCacheManager::CacheIterator::SetValue(const char* value) bool cmCacheManager::CacheIterator::GetValueAsBool() const { - return cmSystemTools::IsOn(this->GetEntry().Value); + return cmIsOn(this->GetEntry().Value); } std::vector<std::string> cmCacheManager::CacheEntry::GetPropertyList() const { - return this->Properties.GetPropertyList(); + return this->Properties.GetKeys(); } const char* cmCacheManager::CacheEntry::GetProperty( @@ -695,7 +684,7 @@ bool cmCacheManager::CacheIterator::GetPropertyAsBool( const std::string& prop) const { if (const char* value = this->GetProperty(prop)) { - return cmSystemTools::IsOn(value); + return cmIsOn(value); } return false; } diff --git a/Source/cmCallVisualStudioMacro.cxx b/Source/cmCallVisualStudioMacro.cxx index f7a2244..9e152ff 100644 --- a/Source/cmCallVisualStudioMacro.cxx +++ b/Source/cmCallVisualStudioMacro.cxx @@ -4,6 +4,7 @@ #include <sstream> +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #if defined(_MSC_VER) @@ -328,8 +329,7 @@ HRESULT FindVisualStudioInstances(const std::string& slnFile, if (SUCCEEDED(hr)) { std::map<std::string, IUnknownPtr>::iterator it; for (it = mrot.begin(); it != mrot.end(); ++it) { - if (cmSystemTools::StringStartsWith(it->first.c_str(), - "!VisualStudio.DTE.")) { + if (cmHasLiteralPrefix(it->first, "!VisualStudio.DTE.")) { IDispatchPtr disp(it->second); if (disp != (IDispatch*)0) { std::string slnName; diff --git a/Source/cmCommand.cxx b/Source/cmCommand.cxx index d349c91..0c2734e 100644 --- a/Source/cmCommand.cxx +++ b/Source/cmCommand.cxx @@ -2,11 +2,19 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCommand.h" +#include <utility> + +#include "cmExecutionStatus.h" #include "cmMakefile.h" -class cmExecutionStatus; struct cmListFileArgument; +void cmCommand::SetExecutionStatus(cmExecutionStatus* status) +{ + this->Status = status; + this->Makefile = &status->GetMakefile(); +} + bool cmCommand::InvokeInitialPass(const std::vector<cmListFileArgument>& args, cmExecutionStatus& status) { @@ -19,15 +27,33 @@ bool cmCommand::InvokeInitialPass(const std::vector<cmListFileArgument>& args, return this->InitialPass(expandedArguments, status); } -const char* cmCommand::GetError() +void cmCommand::SetError(const std::string& e) { - if (this->Error.empty()) { - return "unknown error."; - } - return this->Error.c_str(); + this->Status->SetError(e); } -void cmCommand::SetError(const std::string& e) +cmLegacyCommandWrapper::cmLegacyCommandWrapper(std::unique_ptr<cmCommand> cmd) + : Command(std::move(cmd)) +{ +} + +cmLegacyCommandWrapper::cmLegacyCommandWrapper( + cmLegacyCommandWrapper const& other) + : Command(other.Command->Clone()) +{ +} + +cmLegacyCommandWrapper& cmLegacyCommandWrapper::operator=( + cmLegacyCommandWrapper const& other) +{ + this->Command = other.Command->Clone(); + return *this; +} + +bool cmLegacyCommandWrapper::operator()( + std::vector<cmListFileArgument> const& args, cmExecutionStatus& status) const { - this->Error = e; + auto cmd = this->Command->Clone(); + cmd->SetExecutionStatus(&status); + return cmd->InvokeInitialPass(args, status); } diff --git a/Source/cmCommand.h b/Source/cmCommand.h index 9ccd773..bcb178d 100644 --- a/Source/cmCommand.h +++ b/Source/cmCommand.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <memory> #include <string> #include <vector> @@ -41,16 +42,18 @@ public: /** * Specify the makefile. */ - void SetMakefile(cmMakefile* m) { this->Makefile = m; } cmMakefile* GetMakefile() { return this->Makefile; } + void SetExecutionStatus(cmExecutionStatus* s); + cmExecutionStatus* GetExecutionStatus() { return this->Status; }; + /** * This is called by the cmMakefile when the command is first * encountered in the CMakeLists.txt file. It expands the command's * arguments and then invokes the InitialPass. */ - virtual bool InvokeInitialPass(const std::vector<cmListFileArgument>& args, - cmExecutionStatus& status); + bool InvokeInitialPass(const std::vector<cmListFileArgument>& args, + cmExecutionStatus& status); /** * This is called when the command is first encountered in @@ -60,27 +63,9 @@ public: cmExecutionStatus&) = 0; /** - * This is called at the end after all the information - * specified by the command is accumulated. Most commands do - * not implement this method. At this point, reading and - * writing to the cache can be done. - */ - virtual void FinalPass() {} - - /** - * Does this command have a final pass? Query after InitialPass. - */ - virtual bool HasFinalPass() const { return false; } - - /** * This is a virtual constructor for the command. */ - virtual cmCommand* Clone() = 0; - - /** - * Return the last error string. - */ - const char* GetError(); + virtual std::unique_ptr<cmCommand> Clone() = 0; /** * Set the error message @@ -91,7 +76,25 @@ protected: cmMakefile* Makefile = nullptr; private: - std::string Error; + cmExecutionStatus* Status = nullptr; +}; + +class cmLegacyCommandWrapper +{ +public: + explicit cmLegacyCommandWrapper(std::unique_ptr<cmCommand> cmd); + + cmLegacyCommandWrapper(cmLegacyCommandWrapper const& other); + cmLegacyCommandWrapper& operator=(cmLegacyCommandWrapper const& other); + + cmLegacyCommandWrapper(cmLegacyCommandWrapper&&) = default; + cmLegacyCommandWrapper& operator=(cmLegacyCommandWrapper&&) = default; + + bool operator()(std::vector<cmListFileArgument> const& args, + cmExecutionStatus& status) const; + +private: + std::unique_ptr<cmCommand> Command; }; #endif diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx index ca29967..b368b3a 100644 --- a/Source/cmCommandArgumentParserHelper.cxx +++ b/Source/cmCommandArgumentParserHelper.cxx @@ -5,6 +5,7 @@ #include "cmCommandArgumentLexer.h" #include "cmMakefile.h" #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include <iostream> @@ -58,7 +59,7 @@ const char* cmCommandArgumentParserHelper::ExpandSpecialVariable( std::string str; if (cmSystemTools::GetEnv(var, str)) { if (this->EscapeQuotes) { - return this->AddString(cmSystemTools::EscapeQuotes(str)); + return this->AddString(cmEscapeQuotes(str)); } return this->AddString(str); } @@ -68,7 +69,7 @@ const char* cmCommandArgumentParserHelper::ExpandSpecialVariable( if (const std::string* c = this->Makefile->GetState()->GetInitializedCacheValue(var)) { if (this->EscapeQuotes) { - return this->AddString(cmSystemTools::EscapeQuotes(*c)); + return this->AddString(cmEscapeQuotes(*c)); } return this->AddString(*c); } @@ -87,9 +88,7 @@ const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var) return nullptr; } if (this->FileLine >= 0 && strcmp(var, "CMAKE_CURRENT_LIST_LINE") == 0) { - std::ostringstream ostr; - ostr << this->FileLine; - return this->AddString(ostr.str()); + return this->AddString(std::to_string(this->FileLine)); } const char* value = this->Makefile->GetDefinition(var); if (!value) { @@ -99,7 +98,7 @@ const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var) } } if (this->EscapeQuotes && value) { - return this->AddString(cmSystemTools::EscapeQuotes(value)); + return this->AddString(cmEscapeQuotes(value)); } return this->AddString(value ? value : ""); } @@ -123,9 +122,7 @@ const char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var) // - this->ReplaceAtSyntax is false // - this->ReplaceAtSyntax is true, but this->RemoveEmpty is false, // and the variable was not defined - std::string ref = "@"; - ref += var; - ref += "@"; + std::string ref = cmStrCat('@', var, '@'); return this->AddString(ref); } diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 63c5397..ead16d2 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -1,5 +1,8 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cm_memory.hxx" + #include "cmCommands.h" #include "cmPolicies.h" #include "cmState.h" @@ -17,6 +20,7 @@ #include "cmBuildCommand.h" #include "cmCMakeMinimumRequired.h" #include "cmCMakePolicyCommand.h" +#include "cmCommand.h" #include "cmConfigureFileCommand.h" #include "cmContinueCommand.h" #include "cmCreateTestSourceList.h" @@ -80,7 +84,7 @@ #include "cmUnsetCommand.h" #include "cmWhileCommand.h" -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) # include "cmAddCompileOptionsCommand.h" # include "cmAddLinkOptionsCommand.h" # include "cmAuxSourceDirectoryCommand.h" @@ -112,52 +116,51 @@ void GetScriptingCommands(cmState* state) { - state->AddBuiltinCommand("break", new cmBreakCommand); - state->AddBuiltinCommand("cmake_minimum_required", - new cmCMakeMinimumRequired); - state->AddBuiltinCommand("cmake_policy", new cmCMakePolicyCommand); - state->AddBuiltinCommand("configure_file", new cmConfigureFileCommand); - state->AddBuiltinCommand("continue", new cmContinueCommand); - state->AddBuiltinCommand("exec_program", new cmExecProgramCommand); - state->AddBuiltinCommand("execute_process", new cmExecuteProcessCommand); - state->AddBuiltinCommand("file", new cmFileCommand); - state->AddBuiltinCommand("find_file", new cmFindFileCommand); - state->AddBuiltinCommand("find_library", new cmFindLibraryCommand); - state->AddBuiltinCommand("find_package", new cmFindPackageCommand); - state->AddBuiltinCommand("find_path", new cmFindPathCommand); - state->AddBuiltinCommand("find_program", new cmFindProgramCommand); - state->AddBuiltinCommand("foreach", new cmForEachCommand); - state->AddBuiltinCommand("function", new cmFunctionCommand); - state->AddBuiltinCommand("get_cmake_property", - new cmGetCMakePropertyCommand); + state->AddBuiltinCommand("break", cmBreakCommand); + state->AddBuiltinCommand("cmake_minimum_required", cmCMakeMinimumRequired); + state->AddBuiltinCommand("cmake_policy", cmCMakePolicyCommand); + state->AddBuiltinCommand("configure_file", cmConfigureFileCommand); + state->AddBuiltinCommand("continue", cmContinueCommand); + state->AddBuiltinCommand("exec_program", cmExecProgramCommand); + state->AddBuiltinCommand("execute_process", cmExecuteProcessCommand); + state->AddBuiltinCommand("file", cmFileCommand); + state->AddBuiltinCommand("find_file", cm::make_unique<cmFindFileCommand>()); + state->AddBuiltinCommand("find_library", + cm::make_unique<cmFindLibraryCommand>()); + state->AddBuiltinCommand("find_package", + cm::make_unique<cmFindPackageCommand>()); + state->AddBuiltinCommand("find_path", cm::make_unique<cmFindPathCommand>()); + state->AddBuiltinCommand("find_program", + cm::make_unique<cmFindProgramCommand>()); + state->AddBuiltinCommand("foreach", cmForEachCommand); + state->AddBuiltinCommand("function", cmFunctionCommand); + state->AddBuiltinCommand("get_cmake_property", cmGetCMakePropertyCommand); state->AddBuiltinCommand("get_directory_property", - new cmGetDirectoryPropertyCommand); + cmGetDirectoryPropertyCommand); state->AddBuiltinCommand("get_filename_component", - new cmGetFilenameComponentCommand); - state->AddBuiltinCommand("get_property", new cmGetPropertyCommand); - state->AddBuiltinCommand("if", new cmIfCommand); - state->AddBuiltinCommand("include", new cmIncludeCommand); - state->AddBuiltinCommand("include_guard", new cmIncludeGuardCommand); - state->AddBuiltinCommand("list", new cmListCommand); - state->AddBuiltinCommand("macro", new cmMacroCommand); - state->AddBuiltinCommand("make_directory", new cmMakeDirectoryCommand); - state->AddBuiltinCommand("mark_as_advanced", new cmMarkAsAdvancedCommand); - state->AddBuiltinCommand("math", new cmMathCommand); - state->AddBuiltinCommand("message", new cmMessageCommand); - state->AddBuiltinCommand("option", new cmOptionCommand); - state->AddBuiltinCommand("cmake_parse_arguments", - new cmParseArgumentsCommand); - state->AddBuiltinCommand("return", new cmReturnCommand); - state->AddBuiltinCommand("separate_arguments", - new cmSeparateArgumentsCommand); - state->AddBuiltinCommand("set", new cmSetCommand); + cmGetFilenameComponentCommand); + state->AddBuiltinCommand("get_property", cmGetPropertyCommand); + state->AddBuiltinCommand("if", cmIfCommand); + state->AddBuiltinCommand("include", cmIncludeCommand); + state->AddBuiltinCommand("include_guard", cmIncludeGuardCommand); + state->AddBuiltinCommand("list", cmListCommand); + state->AddBuiltinCommand("macro", cmMacroCommand); + state->AddBuiltinCommand("make_directory", cmMakeDirectoryCommand); + state->AddBuiltinCommand("mark_as_advanced", cmMarkAsAdvancedCommand); + state->AddBuiltinCommand("math", cmMathCommand); + state->AddBuiltinCommand("message", cmMessageCommand); + state->AddBuiltinCommand("option", cmOptionCommand); + state->AddBuiltinCommand("cmake_parse_arguments", cmParseArgumentsCommand); + state->AddBuiltinCommand("return", cmReturnCommand); + state->AddBuiltinCommand("separate_arguments", cmSeparateArgumentsCommand); + state->AddBuiltinCommand("set", cmSetCommand); state->AddBuiltinCommand("set_directory_properties", - new cmSetDirectoryPropertiesCommand); - state->AddBuiltinCommand("set_property", new cmSetPropertyCommand); - state->AddBuiltinCommand("site_name", new cmSiteNameCommand); - state->AddBuiltinCommand("string", new cmStringCommand); - state->AddBuiltinCommand("unset", new cmUnsetCommand); - state->AddBuiltinCommand("while", new cmWhileCommand); + cmSetDirectoryPropertiesCommand); + state->AddBuiltinCommand("set_property", cmSetPropertyCommand); + state->AddBuiltinCommand("site_name", cmSiteNameCommand); + state->AddBuiltinCommand("string", cmStringCommand); + state->AddBuiltinCommand("unset", cmUnsetCommand); + state->AddBuiltinCommand("while", cmWhileCommand); state->AddUnexpectedCommand( "else", @@ -194,18 +197,19 @@ void GetScriptingCommands(cmState* state) "WHILE ENDWHILE structure. Or its arguments did not " "match the opening WHILE command."); -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) state->AddBuiltinCommand("cmake_host_system_information", - new cmCMakeHostSystemInformationCommand); - state->AddBuiltinCommand("remove", new cmRemoveCommand); - state->AddBuiltinCommand("variable_watch", new cmVariableWatchCommand); - state->AddBuiltinCommand("write_file", new cmWriteFileCommand); + cmCMakeHostSystemInformationCommand); + state->AddBuiltinCommand("remove", cmRemoveCommand); + state->AddBuiltinCommand("variable_watch", cmVariableWatchCommand); + state->AddBuiltinCommand("write_file", cmWriteFileCommand); state->AddDisallowedCommand( - "build_name", new cmBuildNameCommand, cmPolicies::CMP0036, + "build_name", cmBuildNameCommand, cmPolicies::CMP0036, "The build_name command should not be called; see CMP0036."); state->AddDisallowedCommand( - "use_mangled_mesa", new cmUseMangledMesaCommand, cmPolicies::CMP0030, + "use_mangled_mesa", cm::make_unique<cmUseMangledMesaCommand>(), + cmPolicies::CMP0030, "The use_mangled_mesa command should not be called; see CMP0030."); #endif @@ -213,101 +217,122 @@ void GetScriptingCommands(cmState* state) void GetProjectCommands(cmState* state) { - state->AddBuiltinCommand("add_custom_command", - new cmAddCustomCommandCommand); - state->AddBuiltinCommand("add_custom_target", new cmAddCustomTargetCommand); - state->AddBuiltinCommand("add_definitions", new cmAddDefinitionsCommand); - state->AddBuiltinCommand("add_dependencies", new cmAddDependenciesCommand); - state->AddBuiltinCommand("add_executable", new cmAddExecutableCommand); - state->AddBuiltinCommand("add_library", new cmAddLibraryCommand); - state->AddBuiltinCommand("add_subdirectory", new cmAddSubDirectoryCommand); - state->AddBuiltinCommand("add_test", new cmAddTestCommand); - state->AddBuiltinCommand("build_command", new cmBuildCommand); + state->AddBuiltinCommand("add_custom_command", cmAddCustomCommandCommand); + state->AddBuiltinCommand("add_custom_target", cmAddCustomTargetCommand); + state->AddBuiltinCommand("add_definitions", cmAddDefinitionsCommand); + state->AddBuiltinCommand("add_dependencies", cmAddDependenciesCommand); + state->AddBuiltinCommand("add_executable", cmAddExecutableCommand); + state->AddBuiltinCommand("add_library", cmAddLibraryCommand); + state->AddBuiltinCommand("add_subdirectory", cmAddSubDirectoryCommand); + state->AddBuiltinCommand("add_test", cmAddTestCommand); + state->AddBuiltinCommand("build_command", cm::make_unique<cmBuildCommand>()); state->AddBuiltinCommand("create_test_sourcelist", - new cmCreateTestSourceList); - state->AddBuiltinCommand("define_property", new cmDefinePropertyCommand); - state->AddBuiltinCommand("enable_language", new cmEnableLanguageCommand); - state->AddBuiltinCommand("enable_testing", new cmEnableTestingCommand); + cm::make_unique<cmCreateTestSourceList>()); + state->AddBuiltinCommand("define_property", + cm::make_unique<cmDefinePropertyCommand>()); + state->AddBuiltinCommand("enable_language", + cm::make_unique<cmEnableLanguageCommand>()); + state->AddBuiltinCommand("enable_testing", cmEnableTestingCommand); state->AddBuiltinCommand("get_source_file_property", - new cmGetSourceFilePropertyCommand); + cm::make_unique<cmGetSourceFilePropertyCommand>()); state->AddBuiltinCommand("get_target_property", - new cmGetTargetPropertyCommand); - state->AddBuiltinCommand("get_test_property", new cmGetTestPropertyCommand); + cm::make_unique<cmGetTargetPropertyCommand>()); + state->AddBuiltinCommand("get_test_property", + cm::make_unique<cmGetTestPropertyCommand>()); state->AddBuiltinCommand("include_directories", - new cmIncludeDirectoryCommand); - state->AddBuiltinCommand("include_regular_expression", - new cmIncludeRegularExpressionCommand); - state->AddBuiltinCommand("install", new cmInstallCommand); - state->AddBuiltinCommand("install_files", new cmInstallFilesCommand); - state->AddBuiltinCommand("install_targets", new cmInstallTargetsCommand); - state->AddBuiltinCommand("link_directories", new cmLinkDirectoriesCommand); - state->AddBuiltinCommand("project", new cmProjectCommand); - state->AddBuiltinCommand("set_source_files_properties", - new cmSetSourceFilesPropertiesCommand); + cm::make_unique<cmIncludeDirectoryCommand>()); + state->AddBuiltinCommand( + "include_regular_expression", + cm::make_unique<cmIncludeRegularExpressionCommand>()); + state->AddBuiltinCommand("install", cm::make_unique<cmInstallCommand>()); + state->AddBuiltinCommand("install_files", + cm::make_unique<cmInstallFilesCommand>()); + state->AddBuiltinCommand("install_targets", + cm::make_unique<cmInstallTargetsCommand>()); + state->AddBuiltinCommand("link_directories", + cm::make_unique<cmLinkDirectoriesCommand>()); + state->AddBuiltinCommand("project", cm::make_unique<cmProjectCommand>()); + state->AddBuiltinCommand( + "set_source_files_properties", + cm::make_unique<cmSetSourceFilesPropertiesCommand>()); state->AddBuiltinCommand("set_target_properties", - new cmSetTargetPropertiesCommand); + cm::make_unique<cmSetTargetPropertiesCommand>()); state->AddBuiltinCommand("set_tests_properties", - new cmSetTestsPropertiesCommand); - state->AddBuiltinCommand("subdirs", new cmSubdirCommand); - state->AddBuiltinCommand("target_compile_definitions", - new cmTargetCompileDefinitionsCommand); + cm::make_unique<cmSetTestsPropertiesCommand>()); + state->AddBuiltinCommand("subdirs", cm::make_unique<cmSubdirCommand>()); + state->AddBuiltinCommand( + "target_compile_definitions", + cm::make_unique<cmTargetCompileDefinitionsCommand>()); state->AddBuiltinCommand("target_compile_features", - new cmTargetCompileFeaturesCommand); + cm::make_unique<cmTargetCompileFeaturesCommand>()); state->AddBuiltinCommand("target_compile_options", - new cmTargetCompileOptionsCommand); - state->AddBuiltinCommand("target_include_directories", - new cmTargetIncludeDirectoriesCommand); + cm::make_unique<cmTargetCompileOptionsCommand>()); + state->AddBuiltinCommand( + "target_include_directories", + cm::make_unique<cmTargetIncludeDirectoriesCommand>()); state->AddBuiltinCommand("target_link_libraries", - new cmTargetLinkLibrariesCommand); - state->AddBuiltinCommand("target_sources", new cmTargetSourcesCommand); - state->AddBuiltinCommand("try_compile", new cmTryCompileCommand); - state->AddBuiltinCommand("try_run", new cmTryRunCommand); + cm::make_unique<cmTargetLinkLibrariesCommand>()); + state->AddBuiltinCommand("target_sources", + cm::make_unique<cmTargetSourcesCommand>()); + state->AddBuiltinCommand("try_compile", + cm::make_unique<cmTryCompileCommand>()); + state->AddBuiltinCommand("try_run", cm::make_unique<cmTryRunCommand>()); -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) state->AddBuiltinCommand("add_compile_definitions", - new cmAddCompileDefinitionsCommand); - state->AddBuiltinCommand("add_compile_options", - new cmAddCompileOptionsCommand); + cmAddCompileDefinitionsCommand); + state->AddBuiltinCommand("add_compile_options", cmAddCompileOptionsCommand); state->AddBuiltinCommand("aux_source_directory", - new cmAuxSourceDirectoryCommand); - state->AddBuiltinCommand("export", new cmExportCommand); - state->AddBuiltinCommand("fltk_wrap_ui", new cmFLTKWrapUICommand); - state->AddBuiltinCommand("include_external_msproject", - new cmIncludeExternalMSProjectCommand); - state->AddBuiltinCommand("install_programs", new cmInstallProgramsCommand); - state->AddBuiltinCommand("add_link_options", new cmAddLinkOptionsCommand); - state->AddBuiltinCommand("link_libraries", new cmLinkLibrariesCommand); + cmAuxSourceDirectoryCommand); + state->AddBuiltinCommand("export", cm::make_unique<cmExportCommand>()); + state->AddBuiltinCommand("fltk_wrap_ui", + cm::make_unique<cmFLTKWrapUICommand>()); + state->AddBuiltinCommand( + "include_external_msproject", + cm::make_unique<cmIncludeExternalMSProjectCommand>()); + state->AddBuiltinCommand("install_programs", + cm::make_unique<cmInstallProgramsCommand>()); + state->AddBuiltinCommand("add_link_options", cmAddLinkOptionsCommand); + state->AddBuiltinCommand("link_libraries", + cm::make_unique<cmLinkLibrariesCommand>()); state->AddBuiltinCommand("target_link_options", - new cmTargetLinkOptionsCommand); + cm::make_unique<cmTargetLinkOptionsCommand>()); state->AddBuiltinCommand("target_link_directories", - new cmTargetLinkDirectoriesCommand); - state->AddBuiltinCommand("load_cache", new cmLoadCacheCommand); - state->AddBuiltinCommand("qt_wrap_cpp", new cmQTWrapCPPCommand); - state->AddBuiltinCommand("qt_wrap_ui", new cmQTWrapUICommand); + cm::make_unique<cmTargetLinkDirectoriesCommand>()); + state->AddBuiltinCommand("load_cache", + cm::make_unique<cmLoadCacheCommand>()); + state->AddBuiltinCommand("qt_wrap_cpp", + cm::make_unique<cmQTWrapCPPCommand>()); + state->AddBuiltinCommand("qt_wrap_ui", cm::make_unique<cmQTWrapUICommand>()); state->AddBuiltinCommand("remove_definitions", - new cmRemoveDefinitionsCommand); - state->AddBuiltinCommand("source_group", new cmSourceGroupCommand); + cm::make_unique<cmRemoveDefinitionsCommand>()); + state->AddBuiltinCommand("source_group", + cm::make_unique<cmSourceGroupCommand>()); state->AddDisallowedCommand( - "export_library_dependencies", new cmExportLibraryDependenciesCommand, - cmPolicies::CMP0033, + "export_library_dependencies", + cm::make_unique<cmExportLibraryDependenciesCommand>(), cmPolicies::CMP0033, "The export_library_dependencies command should not be called; " "see CMP0033."); state->AddDisallowedCommand( - "load_command", new cmLoadCommandCommand, cmPolicies::CMP0031, + "load_command", cm::make_unique<cmLoadCommandCommand>(), + cmPolicies::CMP0031, "The load_command command should not be called; see CMP0031."); state->AddDisallowedCommand( - "output_required_files", new cmOutputRequiredFilesCommand, + "output_required_files", cm::make_unique<cmOutputRequiredFilesCommand>(), cmPolicies::CMP0032, "The output_required_files command should not be called; see CMP0032."); state->AddDisallowedCommand( - "subdir_depends", new cmSubdirDependsCommand, cmPolicies::CMP0029, + "subdir_depends", cm::make_unique<cmSubdirDependsCommand>(), + cmPolicies::CMP0029, "The subdir_depends command should not be called; see CMP0029."); state->AddDisallowedCommand( - "utility_source", new cmUtilitySourceCommand, cmPolicies::CMP0034, + "utility_source", cm::make_unique<cmUtilitySourceCommand>(), + cmPolicies::CMP0034, "The utility_source command should not be called; see CMP0034."); state->AddDisallowedCommand( - "variable_requires", new cmVariableRequiresCommand, cmPolicies::CMP0035, + "variable_requires", cm::make_unique<cmVariableRequiresCommand>(), + cmPolicies::CMP0035, "The variable_requires command should not be called; see CMP0035."); #endif } diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 66250f3..49db505 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -6,7 +6,6 @@ #include <sstream> #include <utility> -#include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" #include "cmGeneratorTarget.h" #include "cmGlobalCommonGenerator.h" @@ -17,6 +16,7 @@ #include "cmOutputConverter.h" #include "cmSourceFile.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt) : GeneratorTarget(gt) @@ -59,10 +59,11 @@ void cmCommonTargetGenerator::AddModuleDefinitionFlag( // Append the flag and value. Use ConvertToLinkReference to help // vs6's "cl -link" pass it to the linker. - std::string flag = defFileFlag; - flag += this->LocalCommonGenerator->ConvertToOutputFormat( - linkLineComputer->ConvertToLinkReference(mdi->DefFile), - cmOutputConverter::SHELL); + std::string flag = + cmStrCat(defFileFlag, + this->LocalCommonGenerator->ConvertToOutputFormat( + linkLineComputer->ConvertToLinkReference(mdi->DefFile), + cmOutputConverter::SHELL)); this->LocalCommonGenerator->AppendFlags(flags, flag); } @@ -155,9 +156,8 @@ std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories() && linkee->GetType() != cmStateEnums::INTERFACE_LIBRARY && emitted.insert(linkee).second) { cmLocalGenerator* lg = linkee->GetLocalGenerator(); - std::string di = lg->GetCurrentBinaryDirectory(); - di += "/"; - di += lg->GetTargetDirectory(linkee); + std::string di = cmStrCat(lg->GetCurrentBinaryDirectory(), '/', + lg->GetTargetDirectory(linkee)); dirs.push_back(std::move(di)); } } @@ -210,11 +210,7 @@ void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags, const char* name, bool so) { // Lookup the flag to specify the version. - std::string fvar = "CMAKE_"; - fvar += lang; - fvar += "_OSX_"; - fvar += name; - fvar += "_VERSION_FLAG"; + std::string fvar = cmStrCat("CMAKE_", lang, "_OSX_", name, "_VERSION_FLAG"); const char* flag = this->Makefile->GetDefinition(fvar); // Skip if no such flag. diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 186deb6..a39425c 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -11,7 +11,7 @@ #include "cmMakefile.h" #include "cmRange.h" #include "cmStateTypes.h" -#include "cmSystemTools.h" +#include "cmStringAlgorithms.h" #include "cmTarget.h" #include "cmake.h" @@ -23,6 +23,8 @@ #include <string.h> #include <utility> +#include "cm_memory.hxx" + /* This file computes an ordered list of link items to use when linking a @@ -202,7 +204,6 @@ cmComputeLinkDepends::cmComputeLinkDepends(const cmGeneratorTarget* target, cmComputeLinkDepends::~cmComputeLinkDepends() { cmDeleteAll(this->InferredDependSets); - delete this->CCG; } void cmComputeLinkDepends::SetOldLinkDirMode(bool b) @@ -318,8 +319,7 @@ int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item) this->BFSQueue.push(qe); } else { // Look for an old-style <item>_LIB_DEPENDS variable. - std::string var = entry.Item; - var += "_LIB_DEPENDS"; + std::string var = cmStrCat(entry.Item, "_LIB_DEPENDS"); if (const char* val = this->Makefile->GetDefinition(var)) { // The item dependencies are known. Follow them. BFSEntry qe = { index, val }; @@ -436,8 +436,7 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index, // This is called to add the dependencies named by // <item>_LIB_DEPENDS. The variable contains a semicolon-separated // list. The list contains link-type;item pairs and just items. - std::vector<std::string> deplist; - cmSystemTools::ExpandListArgument(value, deplist); + std::vector<std::string> deplist = cmExpandedList(value); // Look for entries meant for this configuration. std::vector<cmLinkItem> actual_libs; @@ -460,8 +459,7 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index, // the export_library_dependencies command from CMake 2.4 and // lower. if (!haveLLT) { - std::string var = d; - var += "_LINK_TYPE"; + std::string var = cmStrCat(d, "_LINK_TYPE"); if (const char* val = this->Makefile->GetDefinition(var)) { if (strcmp(val, "debug") == 0) { llt = DEBUG_LibraryType; @@ -632,7 +630,8 @@ void cmComputeLinkDepends::OrderLinkEntires() // the same order in which the items were originally discovered in // the BFS. This should preserve the original order when no // constraints disallow it. - this->CCG = new cmComputeComponentGraph(this->EntryConstraintGraph); + this->CCG = + cm::make_unique<cmComputeComponentGraph>(this->EntryConstraintGraph); // The component graph is guaranteed to be acyclic. Start a DFS // from every entry to compute a topological order for the diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index dfaaf8b..839c27a 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -10,6 +10,7 @@ #include "cmTargetLinkLibraryType.h" #include <map> +#include <memory> #include <queue> #include <set> #include <string> @@ -137,7 +138,7 @@ private: std::set<int> Entries; }; std::map<int, PendingComponent> PendingComponents; - cmComputeComponentGraph* CCG; + std::unique_ptr<cmComputeComponentGraph> CCG; std::vector<int> FinalLinkOrder; void DisplayComponents(); void VisitComponent(unsigned int c); diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 44d8615..880d5c0 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -14,6 +14,7 @@ #include "cmPolicies.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmake.h" @@ -268,10 +269,6 @@ cmComputeLinkInformation::cmComputeLinkInformation( return; } - // Check whether we should use an import library for linking a target. - this->UseImportLibrary = - this->Makefile->IsDefinitionSet("CMAKE_IMPORT_LIBRARY_SUFFIX"); - // Check whether we should skip dependencies on shared library files. this->LinkDependsNoShared = this->Target->GetPropertyAsBool("LINK_DEPENDS_NO_SHARED"); @@ -280,17 +277,21 @@ cmComputeLinkInformation::cmComputeLinkInformation( // to use when creating a plugin (module) that obtains symbols from // the program that will load it. this->LoaderFlag = nullptr; - if (!this->UseImportLibrary && + if (!this->Target->IsDLLPlatform() && this->Target->GetType() == cmStateEnums::MODULE_LIBRARY) { - std::string loader_flag_var = "CMAKE_SHARED_MODULE_LOADER_"; - loader_flag_var += this->LinkLanguage; - loader_flag_var += "_FLAG"; + std::string loader_flag_var = + cmStrCat("CMAKE_SHARED_MODULE_LOADER_", this->LinkLanguage, "_FLAG"); this->LoaderFlag = this->Makefile->GetDefinition(loader_flag_var); } // Get options needed to link libraries. - this->LibLinkFlag = - this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FLAG"); + if (const char* flag = this->Makefile->GetDefinition( + "CMAKE_" + this->LinkLanguage + "_LINK_LIBRARY_FLAG")) { + this->LibLinkFlag = flag; + } else { + this->LibLinkFlag = + this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FLAG"); + } this->LibLinkFileFlag = this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FILE_FLAG"); this->LibLinkSuffix = @@ -302,11 +303,8 @@ cmComputeLinkInformation::cmComputeLinkInformation( const char* tType = ((this->Target->GetType() == cmStateEnums::EXECUTABLE) ? "EXECUTABLE" : "SHARED_LIBRARY"); - std::string rtVar = "CMAKE_"; - rtVar += tType; - rtVar += "_RUNTIME_"; - rtVar += this->LinkLanguage; - rtVar += "_FLAG"; + std::string rtVar = + cmStrCat("CMAKE_", tType, "_RUNTIME_", this->LinkLanguage, "_FLAG"); std::string rtSepVar = rtVar + "_SEP"; this->RuntimeFlag = this->Makefile->GetSafeDefinition(rtVar); this->RuntimeSep = this->Makefile->GetSafeDefinition(rtSepVar); @@ -316,19 +314,15 @@ cmComputeLinkInformation::cmComputeLinkInformation( this->RuntimeUseChrpath = this->Target->IsChrpathUsed(config); // Get options needed to help find dependent libraries. - std::string rlVar = "CMAKE_"; - rlVar += tType; - rlVar += "_RPATH_LINK_"; - rlVar += this->LinkLanguage; - rlVar += "_FLAG"; + std::string rlVar = + cmStrCat("CMAKE_", tType, "_RPATH_LINK_", this->LinkLanguage, "_FLAG"); this->RPathLinkFlag = this->Makefile->GetSafeDefinition(rlVar); } // Check if we need to include the runtime search path at link time. { - std::string var = "CMAKE_SHARED_LIBRARY_LINK_"; - var += this->LinkLanguage; - var += "_WITH_RUNTIME_PATH"; + std::string var = cmStrCat("CMAKE_SHARED_LIBRARY_LINK_", + this->LinkLanguage, "_WITH_RUNTIME_PATH"); this->LinkWithRuntimePath = this->Makefile->IsOn(var); } @@ -479,7 +473,7 @@ bool cmComputeLinkInformation::Compute() // Restore the target link type so the correct system runtime // libraries are found. const char* lss = this->Target->GetProperty("LINK_SEARCH_END_STATIC"); - if (cmSystemTools::IsOn(lss)) { + if (cmIsOn(lss)) { this->SetCurrentLinkType(LinkStatic); } else { this->SetCurrentLinkType(this->StartLinkType); @@ -493,9 +487,7 @@ bool cmComputeLinkInformation::Compute() std::set<cmGeneratorTarget const*> const& wrongItems = cld.GetOldWrongConfigItems(); for (cmGeneratorTarget const* tgt : wrongItems) { - bool implib = (this->UseImportLibrary && - (tgt->GetType() == cmStateEnums::SHARED_LIBRARY)); - cmStateEnums::ArtifactType artifact = implib + cmStateEnums::ArtifactType artifact = tgt->HasImportLibrary(this->Config) ? cmStateEnums::ImportLibraryArtifact : cmStateEnums::RuntimeBinaryArtifact; this->OldLinkDirItems.push_back( @@ -547,14 +539,11 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang) { // Add libraries for this language that are not implied by the // linker language. - std::string libVar = "CMAKE_"; - libVar += lang; - libVar += "_IMPLICIT_LINK_LIBRARIES"; + std::string libVar = cmStrCat("CMAKE_", lang, "_IMPLICIT_LINK_LIBRARIES"); if (const char* libs = this->Makefile->GetDefinition(libVar)) { - std::vector<std::string> libsVec; - cmSystemTools::ExpandListArgument(libs, libsVec); + std::vector<std::string> libsVec = cmExpandedList(libs); for (std::string const& i : libsVec) { - if (this->ImplicitLinkLibs.find(i) == this->ImplicitLinkLibs.end()) { + if (!cmContains(this->ImplicitLinkLibs, i)) { this->AddItem(i, nullptr); } } @@ -562,12 +551,9 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang) // Add linker search paths for this language that are not // implied by the linker language. - std::string dirVar = "CMAKE_"; - dirVar += lang; - dirVar += "_IMPLICIT_LINK_DIRECTORIES"; + std::string dirVar = cmStrCat("CMAKE_", lang, "_IMPLICIT_LINK_DIRECTORIES"); if (const char* dirs = this->Makefile->GetDefinition(dirVar)) { - std::vector<std::string> dirsVec; - cmSystemTools::ExpandListArgument(dirs, dirsVec); + std::vector<std::string> dirsVec = cmExpandedList(dirs); this->OrderLinkerSearchPath->AddLanguageDirectories(dirsVec); } } @@ -578,7 +564,7 @@ void cmComputeLinkInformation::AddItem(std::string const& item, // Compute the proper name to use to link this library. const std::string& config = this->Config; bool impexe = (tgt && tgt->IsExecutableWithExports()); - if (impexe && !this->UseImportLibrary && !this->LoaderFlag) { + if (impexe && !tgt->HasImportLibrary(config) && !this->LoaderFlag) { // Skip linking to executables on platforms with no import // libraries or loader flags. return; @@ -592,7 +578,7 @@ void cmComputeLinkInformation::AddItem(std::string const& item, // platform. Add it now. std::string linkItem; linkItem = this->LoaderFlag; - cmStateEnums::ArtifactType artifact = this->UseImportLibrary + cmStateEnums::ArtifactType artifact = tgt->HasImportLibrary(config) ? cmStateEnums::ImportLibraryArtifact : cmStateEnums::RuntimeBinaryArtifact; @@ -616,15 +602,21 @@ void cmComputeLinkInformation::AddItem(std::string const& item, // Its object-files should already have been extracted for linking. } else { // Decide whether to use an import library. - bool implib = - (this->UseImportLibrary && - (impexe || tgt->GetType() == cmStateEnums::SHARED_LIBRARY)); - cmStateEnums::ArtifactType artifact = implib + cmStateEnums::ArtifactType artifact = tgt->HasImportLibrary(config) ? cmStateEnums::ImportLibraryArtifact : cmStateEnums::RuntimeBinaryArtifact; // Pass the full path to the target file. std::string lib = tgt->GetFullPath(config, artifact, true); + if (tgt->Target->IsAIX() && cmHasLiteralSuffix(lib, "-NOTFOUND") && + artifact == cmStateEnums::ImportLibraryArtifact) { + // This is an imported executable on AIX that has ENABLE_EXPORTS + // but not IMPORTED_IMPLIB. CMake used to produce and accept such + // imported executables on AIX before we taught it to use linker + // import files. For compatibility, simply skip linking to this + // executable as we did before. It works with runtime linking. + return; + } if (!this->LinkDependsNoShared || tgt->GetType() != cmStateEnums::SHARED_LIBRARY) { this->Depends.push_back(lib); @@ -694,7 +686,7 @@ void cmComputeLinkInformation::AddSharedDepItem(std::string const& item, // linked will be able to find it. std::string lib; if (tgt) { - cmStateEnums::ArtifactType artifact = this->UseImportLibrary + cmStateEnums::ArtifactType artifact = tgt->HasImportLibrary(this->Config) ? cmStateEnums::ImportLibraryArtifact : cmStateEnums::RuntimeBinaryArtifact; lib = tgt->GetFullPath(this->Config, artifact); @@ -754,19 +746,15 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo() break; } if (target_type_str) { - std::string static_link_type_flag_var = "CMAKE_"; - static_link_type_flag_var += target_type_str; - static_link_type_flag_var += "_LINK_STATIC_"; - static_link_type_flag_var += this->LinkLanguage; - static_link_type_flag_var += "_FLAGS"; + std::string static_link_type_flag_var = + cmStrCat("CMAKE_", target_type_str, "_LINK_STATIC_", this->LinkLanguage, + "_FLAGS"); static_link_type_flag = this->Makefile->GetDefinition(static_link_type_flag_var); - std::string shared_link_type_flag_var = "CMAKE_"; - shared_link_type_flag_var += target_type_str; - shared_link_type_flag_var += "_LINK_DYNAMIC_"; - shared_link_type_flag_var += this->LinkLanguage; - shared_link_type_flag_var += "_FLAGS"; + std::string shared_link_type_flag_var = + cmStrCat("CMAKE_", target_type_str, "_LINK_DYNAMIC_", this->LinkLanguage, + "_FLAGS"); shared_link_type_flag = this->Makefile->GetDefinition(shared_link_type_flag_var); } @@ -782,7 +770,7 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo() // Lookup the starting link type from the target (linked statically?). const char* lss = this->Target->GetProperty("LINK_SEARCH_START_STATIC"); - this->StartLinkType = cmSystemTools::IsOn(lss) ? LinkStatic : LinkShared; + this->StartLinkType = cmIsOn(lss) ? LinkStatic : LinkShared; this->CurrentLinkType = this->StartLinkType; } @@ -805,16 +793,14 @@ void cmComputeLinkInformation::ComputeItemParserInfo() LinkUnknown); if (const char* linkSuffixes = mf->GetDefinition("CMAKE_EXTRA_LINK_EXTENSIONS")) { - std::vector<std::string> linkSuffixVec; - cmSystemTools::ExpandListArgument(linkSuffixes, linkSuffixVec); + std::vector<std::string> linkSuffixVec = cmExpandedList(linkSuffixes); for (std::string const& i : linkSuffixVec) { this->AddLinkExtension(i.c_str(), LinkUnknown); } } if (const char* sharedSuffixes = mf->GetDefinition("CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES")) { - std::vector<std::string> sharedSuffixVec; - cmSystemTools::ExpandListArgument(sharedSuffixes, sharedSuffixVec); + std::vector<std::string> sharedSuffixVec = cmExpandedList(sharedSuffixes); for (std::string const& i : sharedSuffixVec) { this->AddLinkExtension(i.c_str(), LinkShared); } @@ -842,8 +828,7 @@ void cmComputeLinkInformation::ComputeItemParserInfo() reg += "([^/:]*)"; // Create a regex to match any library name. - std::string reg_any = reg; - reg_any += libext; + std::string reg_any = cmStrCat(reg, libext); #ifdef CM_COMPUTE_LINK_INFO_DEBUG fprintf(stderr, "any regex [%s]\n", reg_any.c_str()); #endif @@ -851,9 +836,8 @@ void cmComputeLinkInformation::ComputeItemParserInfo() // Create a regex to match static library names. if (!this->StaticLinkExtensions.empty()) { - std::string reg_static = reg; - reg_static += - this->CreateExtensionRegex(this->StaticLinkExtensions, LinkStatic); + std::string reg_static = cmStrCat( + reg, this->CreateExtensionRegex(this->StaticLinkExtensions, LinkStatic)); #ifdef CM_COMPUTE_LINK_INFO_DEBUG fprintf(stderr, "static regex [%s]\n", reg_static.c_str()); #endif @@ -990,16 +974,11 @@ void cmComputeLinkInformation::AddTargetItem(std::string const& item, return; } - // If this platform wants a flag before the full path, add it. - if (!this->LibLinkFileFlag.empty()) { - this->Items.emplace_back(this->LibLinkFileFlag, false); - } - // For compatibility with CMake 2.4 include the item's directory in // the linker search path. if (this->OldLinkDirMode && !target->IsFrameworkOnApple() && - this->OldLinkDirMask.find(cmSystemTools::GetFilenamePath(item)) == - this->OldLinkDirMask.end()) { + !cmContains(this->OldLinkDirMask, + cmSystemTools::GetFilenamePath(item))) { this->OldLinkDirItems.push_back(item); } @@ -1052,16 +1031,11 @@ void cmComputeLinkInformation::AddFullItem(std::string const& item) // For compatibility with CMake 2.4 include the item's directory in // the linker search path. if (this->OldLinkDirMode && - this->OldLinkDirMask.find(cmSystemTools::GetFilenamePath(item)) == - this->OldLinkDirMask.end()) { + !cmContains(this->OldLinkDirMask, + cmSystemTools::GetFilenamePath(item))) { this->OldLinkDirItems.push_back(item); } - // If this platform wants a flag before the full path, add it. - if (!this->LibLinkFileFlag.empty()) { - this->Items.emplace_back(this->LibLinkFileFlag, false); - } - // Now add the full path to the library. this->Items.emplace_back(item, true); } @@ -1077,7 +1051,7 @@ bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item) // Check if this item is in an implicit link directory. std::string dir = cmSystemTools::GetFilenamePath(item); - if (this->ImplicitLinkDirs.find(dir) == this->ImplicitLinkDirs.end()) { + if (!cmContains(this->ImplicitLinkDirs, dir)) { // Only libraries in implicit link directories are converted to // pathless items. return false; @@ -1219,9 +1193,7 @@ void cmComputeLinkInformation::AddUserItem(std::string const& item, } // Create an option to ask the linker to search for the library. - std::string out = this->LibLinkFlag; - out += lib; - out += this->LibLinkSuffix; + std::string out = cmStrCat(this->LibLinkFlag, lib, this->LibLinkSuffix); this->Items.emplace_back(out, false); // Here we could try to find the library the linker will find and @@ -1243,12 +1215,7 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item) std::string fw_path = this->SplitFramework.match(1); std::string fw = this->SplitFramework.match(2); - std::string full_fw = fw_path; - full_fw += "/"; - full_fw += fw; - full_fw += ".framework"; - full_fw += "/"; - full_fw += fw; + std::string full_fw = cmStrCat(fw_path, '/', fw, ".framework/", fw); // Add the directory portion to the framework search path. this->AddFrameworkPath(fw_path); @@ -1293,16 +1260,15 @@ void cmComputeLinkInformation::ComputeFrameworkInfo() // Get platform-wide implicit directories. if (const char* implicitLinks = this->Makefile->GetDefinition( "CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES")) { - cmSystemTools::ExpandListArgument(implicitLinks, implicitDirVec); + cmExpandList(implicitLinks, implicitDirVec); } // Get language-specific implicit directories. - std::string implicitDirVar = "CMAKE_"; - implicitDirVar += this->LinkLanguage; - implicitDirVar += "_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES"; + std::string implicitDirVar = cmStrCat( + "CMAKE_", this->LinkLanguage, "_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES"); if (const char* implicitDirs = this->Makefile->GetDefinition(implicitDirVar)) { - cmSystemTools::ExpandListArgument(implicitDirs, implicitDirVec); + cmExpandList(implicitDirs, implicitDirVec); } this->FrameworkPathsEmmitted.insert(implicitDirVec.begin(), @@ -1372,8 +1338,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item, switch (this->Target->GetPolicyStatusCMP0008()) { case cmPolicies::WARN: { // Print the warning at most once for this item. - std::string wid = "CMP0008-WARNING-GIVEN-"; - wid += item; + std::string wid = cmStrCat("CMP0008-WARNING-GIVEN-", item); if (!this->CMakeInstance->GetState()->GetGlobalPropertyAsBool(wid)) { this->CMakeInstance->GetState()->SetGlobalProperty(wid, "1"); std::ostringstream w; @@ -1521,7 +1486,7 @@ void cmComputeLinkInformation::LoadImplicitLinkInfo() // Get platform-wide implicit directories. if (const char* implicitLinks = (this->Makefile->GetDefinition( "CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES"))) { - cmSystemTools::ExpandListArgument(implicitLinks, implicitDirVec); + cmExpandList(implicitLinks, implicitDirVec); } // Append library architecture to all implicit platform directories @@ -1534,12 +1499,11 @@ void cmComputeLinkInformation::LoadImplicitLinkInfo() } // Get language-specific implicit directories. - std::string implicitDirVar = "CMAKE_"; - implicitDirVar += this->LinkLanguage; - implicitDirVar += "_IMPLICIT_LINK_DIRECTORIES"; + std::string implicitDirVar = + cmStrCat("CMAKE_", this->LinkLanguage, "_IMPLICIT_LINK_DIRECTORIES"); if (const char* implicitDirs = this->Makefile->GetDefinition(implicitDirVar)) { - cmSystemTools::ExpandListArgument(implicitDirs, implicitDirVec); + cmExpandList(implicitDirs, implicitDirVec); } // Store implicit link directories. @@ -1547,12 +1511,11 @@ void cmComputeLinkInformation::LoadImplicitLinkInfo() // Get language-specific implicit libraries. std::vector<std::string> implicitLibVec; - std::string implicitLibVar = "CMAKE_"; - implicitLibVar += this->LinkLanguage; - implicitLibVar += "_IMPLICIT_LINK_LIBRARIES"; + std::string implicitLibVar = + cmStrCat("CMAKE_", this->LinkLanguage, "_IMPLICIT_LINK_LIBRARIES"); if (const char* implicitLibs = this->Makefile->GetDefinition(implicitLibVar)) { - cmSystemTools::ExpandListArgument(implicitLibs, implicitLibVec); + cmExpandList(implicitLibs, implicitLibVec); } // Store implicit link libraries. @@ -1567,7 +1530,7 @@ void cmComputeLinkInformation::LoadImplicitLinkInfo() // Get platform specific rpath link directories if (const char* rpathDirs = (this->Makefile->GetDefinition("CMAKE_PLATFORM_RUNTIME_PATH"))) { - cmSystemTools::ExpandListArgument(rpathDirs, this->RuntimeLinkDirs); + cmExpandList(rpathDirs, this->RuntimeLinkDirs); } } @@ -1673,8 +1636,7 @@ static void cmCLI_ExpandListUnique(const char* str, std::vector<std::string>& out, std::set<std::string>& emitted) { - std::vector<std::string> tmp; - cmSystemTools::ExpandListArgument(str, tmp); + std::vector<std::string> tmp = cmExpandedList(str); for (std::string const& i : tmp) { if (emitted.insert(i).second) { out.push_back(i); @@ -1695,7 +1657,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, (for_install || this->Target->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")); bool use_install_rpath = - (outputRuntime && this->Target->HaveInstallTreeRPATH() && + (outputRuntime && this->Target->HaveInstallTreeRPATH(this->Config) && linking_for_install); bool use_build_rpath = (outputRuntime && this->Target->HaveBuildTreeRPATH(this->Config) && @@ -1715,15 +1677,17 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, // Construct the RPATH. std::set<std::string> emitted; if (use_install_rpath) { - const char* install_rpath = this->Target->GetProperty("INSTALL_RPATH"); - cmCLI_ExpandListUnique(install_rpath, runtimeDirs, emitted); + std::string install_rpath; + this->Target->GetInstallRPATH(this->Config, install_rpath); + cmCLI_ExpandListUnique(install_rpath.c_str(), runtimeDirs, emitted); } if (use_build_rpath) { // Add directories explicitly specified by user - if (const char* build_rpath = this->Target->GetProperty("BUILD_RPATH")) { + std::string build_rpath; + if (this->Target->GetBuildRPATH(this->Config, build_rpath)) { // This will not resolve entries to use $ORIGIN, the user is expected to // do that if necessary. - cmCLI_ExpandListUnique(build_rpath, runtimeDirs, emitted); + cmCLI_ExpandListUnique(build_rpath.c_str(), runtimeDirs, emitted); } } if (use_build_rpath || use_link_rpath) { @@ -1751,9 +1715,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, d = d.substr(rootPath.size()); } else if (stagePath && *stagePath && d.find(stagePath) == 0) { std::string suffix = d.substr(strlen(stagePath)); - d = installPrefix; - d += "/"; - d += suffix; + d = cmStrCat(installPrefix, '/', suffix); cmSystemTools::ConvertToUnixSlashes(d); } else if (use_relative_build_rpath) { // If expansion of the $ORIGIN token is supported and permitted per @@ -1762,7 +1724,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, cmSystemTools::IsSubDirectory(d, topBinaryDir)) { d = cmSystemTools::RelativePath(targetOutputDir, d); if (!d.empty()) { - d = originToken + "/" + d; + d = cmStrCat(originToken, "/", d); } else { d = originToken; } @@ -1784,9 +1746,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, d = d.substr(rootPath.size()); } else if (stagePath && *stagePath && d.find(stagePath) == 0) { std::string suffix = d.substr(strlen(stagePath)); - d = installPrefix; - d += "/"; - d += suffix; + d = cmStrCat(installPrefix, '/', suffix); cmSystemTools::ConvertToUnixSlashes(d); } if (emitted.insert(d).second) { diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 863639c..784d3fa 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -56,6 +56,11 @@ public: std::string GetChrpathString() const; std::set<cmGeneratorTarget const*> const& GetSharedLibrariesLinked() const; + std::string const& GetLibLinkFileFlag() const + { + return this->LibLinkFileFlag; + } + std::string const& GetRPathLinkFlag() const { return this->RPathLinkFlag; } std::string GetRPathLinkString() const; @@ -179,7 +184,6 @@ private: bool OldLinkDirMode; bool OpenBSD; bool LinkDependsNoShared; - bool UseImportLibrary; bool RuntimeUseChrpath; bool NoSONameUsesPath; bool LinkWithRuntimePath; diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index e7e91c1..21df278 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -3,7 +3,7 @@ #include "cmConditionEvaluator.h" #include "cmsys/RegularExpression.hxx" -#include <algorithm> +#include <functional> #include <sstream> #include <stdio.h> #include <stdlib.h> @@ -14,10 +14,10 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" -class cmCommand; class cmTest; static std::string const keyAND = "AND"; @@ -219,10 +219,10 @@ bool cmConditionEvaluator::GetBooleanValue( } // Check named constants. - if (cmSystemTools::IsOn(arg.c_str())) { + if (cmIsOn(arg.GetValue())) { return true; } - if (cmSystemTools::IsOff(arg.c_str())) { + if (cmIsOff(arg.GetValue())) { return false; } @@ -238,7 +238,7 @@ bool cmConditionEvaluator::GetBooleanValue( // Check definition. const char* def = this->GetDefinitionIfUnquoted(arg); - return !cmSystemTools::IsOff(def); + return !cmIsOff(def); } //========================================================================= @@ -255,14 +255,14 @@ bool cmConditionEvaluator::GetBooleanValueOld( return true; } const char* def = this->GetDefinitionIfUnquoted(arg); - return !cmSystemTools::IsOff(def); + return !cmIsOff(def); } // Old GetVariableOrNumber behavior. const char* def = this->GetDefinitionIfUnquoted(arg); if (!def && atoi(arg.c_str())) { def = arg.c_str(); } - return !cmSystemTools::IsOff(def); + return !cmIsOff(def); } //========================================================================= @@ -452,7 +452,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&, } // does a command exist if (this->IsKeyword(keyCOMMAND, *arg) && argP1 != newArgs.end()) { - cmCommand* command = + cmState::Command command = this->Makefile.GetState()->GetCommand(argP1->c_str()); this->HandlePredicate(command != nullptr, reducible, arg, newArgs, argP1, argP2); @@ -668,10 +668,9 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList& newArgs, def2 = this->Makefile.GetDefinition(argP2->GetValue()); if (def2) { - std::vector<std::string> list; - cmSystemTools::ExpandListArgument(def2, list, true); + std::vector<std::string> list = cmExpandedList(def2, true); - result = std::find(list.begin(), list.end(), def) != list.end(); + result = cmContains(list, def); } this->HandleBinaryOp(result, reducible, arg, newArgs, argP1, argP2); diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in index 19b1cd4..4de1c5d 100644 --- a/Source/cmConfigure.cmake.h.in +++ b/Source/cmConfigure.cmake.h.in @@ -26,4 +26,8 @@ #define CM_FALLTHROUGH cmsys_FALLTHROUGH +#if defined(_WIN32) && !defined(NOMINMAX) +# define NOMINMAX +#endif + #endif diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx index 0917d11..7e37f32 100644 --- a/Source/cmConfigureFileCommand.cxx +++ b/Source/cmConfigureFileCommand.cxx @@ -4,76 +4,78 @@ #include <sstream> +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmNewLineStyle.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmExecutionStatus; - // cmConfigureFileCommand -bool cmConfigureFileCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmConfigureFileCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 2) { - this->SetError("called with incorrect number of arguments, expected 2"); + status.SetError("called with incorrect number of arguments, expected 2"); return false; } std::string const& inFile = args[0]; - this->InputFile = cmSystemTools::CollapseFullPath( - inFile, this->Makefile->GetCurrentSourceDirectory()); + const std::string inputFile = cmSystemTools::CollapseFullPath( + inFile, status.GetMakefile().GetCurrentSourceDirectory()); // If the input location is a directory, error out. - if (cmSystemTools::FileIsDirectory(this->InputFile)) { + if (cmSystemTools::FileIsDirectory(inputFile)) { std::ostringstream e; /* clang-format off */ e << "input location\n" - << " " << this->InputFile << "\n" + << " " << inputFile << "\n" << "is a directory but a file was expected."; /* clang-format on */ - this->SetError(e.str()); + status.SetError(e.str()); return false; } std::string const& outFile = args[1]; - this->OutputFile = cmSystemTools::CollapseFullPath( - outFile, this->Makefile->GetCurrentBinaryDirectory()); + std::string outputFile = cmSystemTools::CollapseFullPath( + outFile, status.GetMakefile().GetCurrentBinaryDirectory()); // If the output location is already a directory put the file in it. - if (cmSystemTools::FileIsDirectory(this->OutputFile)) { - this->OutputFile += "/"; - this->OutputFile += cmSystemTools::GetFilenameName(inFile); + if (cmSystemTools::FileIsDirectory(outputFile)) { + outputFile += "/"; + outputFile += cmSystemTools::GetFilenameName(inFile); } - if (!this->Makefile->CanIWriteThisFile(this->OutputFile)) { - std::string e = "attempted to configure a file: " + this->OutputFile + + if (!status.GetMakefile().CanIWriteThisFile(outputFile)) { + std::string e = "attempted to configure a file: " + outputFile + " into a source directory."; - this->SetError(e); + status.SetError(e); cmSystemTools::SetFatalErrorOccured(); return false; } std::string errorMessage; - if (!this->NewLineStyle.ReadFromArguments(args, errorMessage)) { - this->SetError(errorMessage); + cmNewLineStyle newLineStyle; + if (!newLineStyle.ReadFromArguments(args, errorMessage)) { + status.SetError(errorMessage); return false; } - this->CopyOnly = false; - this->EscapeQuotes = false; + bool copyOnly = false; + bool escapeQuotes = false; std::string unknown_args; - this->AtOnly = false; + bool atOnly = false; for (unsigned int i = 2; i < args.size(); ++i) { if (args[i] == "COPYONLY") { - this->CopyOnly = true; - if (this->NewLineStyle.IsValid()) { - this->SetError("COPYONLY could not be used in combination " - "with NEWLINE_STYLE"); + copyOnly = true; + if (newLineStyle.IsValid()) { + status.SetError("COPYONLY could not be used in combination " + "with NEWLINE_STYLE"); return false; } } else if (args[i] == "ESCAPE_QUOTES") { - this->EscapeQuotes = true; + escapeQuotes = true; } else if (args[i] == "@ONLY") { - this->AtOnly = true; + atOnly = true; } else if (args[i] == "IMMEDIATE") { /* Ignore legacy option. */ } else if (args[i] == "NEWLINE_STYLE" || args[i] == "LF" || @@ -87,22 +89,16 @@ bool cmConfigureFileCommand::InitialPass(std::vector<std::string> const& args, } } if (!unknown_args.empty()) { - std::string msg = "configure_file called with unknown argument(s):\n"; - msg += unknown_args; - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, msg); + std::string msg = cmStrCat( + "configure_file called with unknown argument(s):\n", unknown_args); + status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, msg); } - if (!this->ConfigureFile()) { - this->SetError("Problem configuring file"); + if (!status.GetMakefile().ConfigureFile( + inputFile, outputFile, copyOnly, atOnly, escapeQuotes, newLineStyle)) { + status.SetError("Problem configuring file"); return false; } return true; } - -int cmConfigureFileCommand::ConfigureFile() -{ - return this->Makefile->ConfigureFile(this->InputFile, this->OutputFile, - this->CopyOnly, this->AtOnly, - this->EscapeQuotes, this->NewLineStyle); -} diff --git a/Source/cmConfigureFileCommand.h b/Source/cmConfigureFileCommand.h index 5603c50..c7f95b8 100644 --- a/Source/cmConfigureFileCommand.h +++ b/Source/cmConfigureFileCommand.h @@ -8,33 +8,8 @@ #include <string> #include <vector> -#include "cmCommand.h" -#include "cmNewLineStyle.h" - class cmExecutionStatus; -class cmConfigureFileCommand : public cmCommand -{ -public: - cmCommand* Clone() override { return new cmConfigureFileCommand; } - - /** - * This is called when the command is first encountered in - * the input file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - int ConfigureFile(); - - cmNewLineStyle NewLineStyle; - - std::string InputFile; - std::string OutputFile; - bool CopyOnly = false; - bool EscapeQuotes = false; - bool AtOnly = false; -}; - +bool cmConfigureFileCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmContinueCommand.cxx b/Source/cmContinueCommand.cxx index 48f1f41..bb63dff 100644 --- a/Source/cmContinueCommand.cxx +++ b/Source/cmContinueCommand.cxx @@ -8,13 +8,14 @@ #include "cmSystemTools.h" // cmContinueCommand -bool cmContinueCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) +bool cmContinueCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { - if (!this->Makefile->IsLoopBlock()) { - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, - "A CONTINUE command was found outside of a " - "proper FOREACH or WHILE loop scope."); + if (!status.GetMakefile().IsLoopBlock()) { + status.GetMakefile().IssueMessage( + MessageType::FATAL_ERROR, + "A CONTINUE command was found outside of a " + "proper FOREACH or WHILE loop scope."); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -22,9 +23,10 @@ bool cmContinueCommand::InitialPass(std::vector<std::string> const& args, status.SetContinueInvoked(); if (!args.empty()) { - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, - "The CONTINUE command does not accept any " - "arguments."); + status.GetMakefile().IssueMessage( + MessageType::FATAL_ERROR, + "The CONTINUE command does not accept any " + "arguments."); cmSystemTools::SetFatalErrorOccured(); return true; } diff --git a/Source/cmContinueCommand.h b/Source/cmContinueCommand.h index d383d1d..ff903aa 100644 --- a/Source/cmContinueCommand.h +++ b/Source/cmContinueCommand.h @@ -8,29 +8,14 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmContinueCommand +/** * \brief Continue from an enclosing foreach or while loop * * cmContinueCommand returns from an enclosing foreach or while loop */ -class cmContinueCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmContinueCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmContinueCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index f12ef0b..3687056 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -9,7 +9,6 @@ #include <string.h> #include <utility> -#include "cmAlgorithms.h" #include "cmExportTryCompileFileGenerator.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" @@ -17,6 +16,7 @@ #include "cmOutputConverter.h" #include "cmPolicies.h" #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmVersion.h" @@ -234,11 +234,11 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } else if (doing == DoingCMakeFlags) { cmakeFlags.push_back(argv[i]); } else if (doing == DoingCompileDefinitions) { - cmSystemTools::ExpandListArgument(argv[i], compileDefs); + cmExpandList(argv[i], compileDefs); } else if (doing == DoingLinkOptions) { linkOptions.push_back(argv[i]); } else if (doing == DoingLinkLibraries) { - libsToLink += "\"" + cmSystemTools::TrimWhitespace(argv[i]) + "\" "; + libsToLink += "\"" + cmTrimWhitespace(argv[i]) + "\" "; if (cmTarget* tgt = this->Makefile->FindTargetToUse(argv[i])) { switch (tgt->GetType()) { case cmStateEnums::SHARED_LIBRARY: @@ -411,8 +411,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, // compute the binary dir when TRY_COMPILE is called with a src file // signature if (this->SrcFileSignature) { - this->BinaryDirectory += "/CMakeFiles"; - this->BinaryDirectory += "/CMakeTmp"; + this->BinaryDirectory += "/CMakeFiles/CMakeTmp"; } else { // only valid for srcfile signatures if (!compileDefs.empty()) { @@ -514,7 +513,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, for (std::string const& li : testLangs) { projectLangs += " " + li; std::string rulesOverrideBase = "CMAKE_USER_MAKE_RULES_OVERRIDE"; - std::string rulesOverrideLang = rulesOverrideBase + "_" + li; + std::string rulesOverrideLang = cmStrCat(rulesOverrideBase, "_", li); if (const char* rulesOverridePath = this->Makefile->GetDefinition(rulesOverrideLang)) { fprintf(fout, "set(%s \"%s\")\n", rulesOverrideLang.c_str(), @@ -574,7 +573,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, std::string const cfg = !tcConfig.empty() ? cmSystemTools::UpperCase(tcConfig) : cfgDefault; for (std::string const& li : testLangs) { - std::string const langFlagsCfg = "CMAKE_" + li + "_FLAGS_" + cfg; + std::string const langFlagsCfg = + cmStrCat("CMAKE_", li, "_FLAGS_", cfg); const char* flagsCfg = this->Makefile->GetDefinition(langFlagsCfg); fprintf(fout, "set(%s %s)\n", langFlagsCfg.c_str(), cmOutputConverter::EscapeForCMake(flagsCfg ? flagsCfg : "") @@ -674,8 +674,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, if (const char* varListStr = this->Makefile->GetDefinition( kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES)) { - std::vector<std::string> varList; - cmSystemTools::ExpandListArgument(varListStr, varList); + std::vector<std::string> varList = cmExpandedList(varListStr); vars.insert(varList.begin(), varList.end()); } @@ -932,7 +931,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, cmStateEnums::INTERNAL); if (!outputVariable.empty()) { - this->Makefile->AddDefinition(outputVariable, output.c_str()); + this->Makefile->AddDefinition(outputVariable, output); } if (this->SrcFileSignature) { @@ -961,8 +960,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } if (!copyFileError.empty()) { - this->Makefile->AddDefinition(copyFileError, - copyFileErrorMessage.c_str()); + this->Makefile->AddDefinition(copyFileError, copyFileErrorMessage); } } return res; @@ -1046,16 +1044,14 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName, this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION"); // if a config was specified try that first if (config && config[0]) { - std::string tmp = "/"; - tmp += config; + std::string tmp = cmStrCat('/', config); searchDirs.push_back(std::move(tmp)); } searchDirs.emplace_back("/Debug"); #if defined(__APPLE__) std::string app = "/" + targetName + ".app"; if (config && config[0]) { - std::string tmp = "/"; - tmp += config + app; + std::string tmp = cmStrCat('/', config, app); searchDirs.push_back(std::move(tmp)); } std::string tmp = "/Debug" + app; @@ -1065,9 +1061,7 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName, searchDirs.emplace_back("/Development"); for (std::string const& sdir : searchDirs) { - std::string command = this->BinaryDirectory; - command += sdir; - command += tmpOutputFile; + std::string command = cmStrCat(this->BinaryDirectory, sdir, tmpOutputFile); if (cmSystemTools::FileExists(command)) { this->OutputFile = cmSystemTools::CollapseFullPath(command); return; diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx index b78493f..4a1825f 100644 --- a/Source/cmCreateTestSourceList.cxx +++ b/Source/cmCreateTestSourceList.cxx @@ -6,6 +6,7 @@ #include "cmMakefile.h" #include "cmSourceFile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmExecutionStatus; @@ -31,17 +32,14 @@ bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args, this->SetError("incorrect arguments to EXTRA_INCLUDE"); return false; } - extraInclude = "#include \""; - extraInclude += *i; - extraInclude += "\"\n"; + extraInclude = cmStrCat("#include \"", *i, "\"\n"); } else if (*i == "FUNCTION") { ++i; if (i == args.end()) { this->SetError("incorrect arguments to FUNCTION"); return false; } - function = *i; - function += "(&ac, &av);\n"; + function = cmStrCat(*i, "(&ac, &av);\n"); } else { tests.push_back(*i); } @@ -60,9 +58,8 @@ bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args, "You must specify a file extension for the test driver file."); return false; } - std::string driver = this->Makefile->GetCurrentBinaryDirectory(); - driver += "/"; - driver += *i; + std::string driver = + cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', *i); ++i; std::string configFile = cmSystemTools::GetCMakeRoot(); @@ -125,16 +122,15 @@ bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args, } if (!extraInclude.empty()) { this->Makefile->AddDefinition("CMAKE_TESTDRIVER_EXTRA_INCLUDES", - extraInclude.c_str()); + extraInclude); } if (!function.empty()) { - this->Makefile->AddDefinition("CMAKE_TESTDRIVER_ARGVC_FUNCTION", - function.c_str()); + this->Makefile->AddDefinition("CMAKE_TESTDRIVER_ARGVC_FUNCTION", function); } this->Makefile->AddDefinition("CMAKE_FORWARD_DECLARE_TESTS", - forwardDeclareCode.c_str()); + forwardDeclareCode); this->Makefile->AddDefinition("CMAKE_FUNCTION_TABLE_ENTIRES", - functionMapCode.c_str()); + functionMapCode); bool res = true; if (!this->Makefile->ConfigureFile(configFile, driver, false, true, false)) { res = false; @@ -154,6 +150,6 @@ bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args, sourceListValue += *i; } - this->Makefile->AddDefinition(sourceList, sourceListValue.c_str()); + this->Makefile->AddDefinition(sourceList, sourceListValue); return res; } diff --git a/Source/cmCreateTestSourceList.h b/Source/cmCreateTestSourceList.h index 005b32c..5aa6af4 100644 --- a/Source/cmCreateTestSourceList.h +++ b/Source/cmCreateTestSourceList.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -23,7 +25,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmCreateTestSourceList; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmCreateTestSourceList>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmCryptoHash.cxx b/Source/cmCryptoHash.cxx index d914eb1..f9f9581 100644 --- a/Source/cmCryptoHash.cxx +++ b/Source/cmCryptoHash.cxx @@ -2,13 +2,11 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCryptoHash.h" -#include "cmAlgorithms.h" #include "cm_kwiml.h" #include "cm_rhash.h" #include "cmsys/FStream.hxx" -#include <string.h> -#include <memory> // IWYU pragma: keep +#include "cm_memory.hxx" static unsigned int const cmCryptoHashAlgoToId[] = { /* clang-format needs this comment to break after the opening brace */ @@ -46,36 +44,36 @@ cmCryptoHash::~cmCryptoHash() rhash_free(this->CTX); } -std::unique_ptr<cmCryptoHash> cmCryptoHash::New(const char* algo) +std::unique_ptr<cmCryptoHash> cmCryptoHash::New(cm::string_view algo) { - if (strcmp(algo, "MD5") == 0) { + if (algo == "MD5") { return cm::make_unique<cmCryptoHash>(AlgoMD5); } - if (strcmp(algo, "SHA1") == 0) { + if (algo == "SHA1") { return cm::make_unique<cmCryptoHash>(AlgoSHA1); } - if (strcmp(algo, "SHA224") == 0) { + if (algo == "SHA224") { return cm::make_unique<cmCryptoHash>(AlgoSHA224); } - if (strcmp(algo, "SHA256") == 0) { + if (algo == "SHA256") { return cm::make_unique<cmCryptoHash>(AlgoSHA256); } - if (strcmp(algo, "SHA384") == 0) { + if (algo == "SHA384") { return cm::make_unique<cmCryptoHash>(AlgoSHA384); } - if (strcmp(algo, "SHA512") == 0) { + if (algo == "SHA512") { return cm::make_unique<cmCryptoHash>(AlgoSHA512); } - if (strcmp(algo, "SHA3_224") == 0) { + if (algo == "SHA3_224") { return cm::make_unique<cmCryptoHash>(AlgoSHA3_224); } - if (strcmp(algo, "SHA3_256") == 0) { + if (algo == "SHA3_256") { return cm::make_unique<cmCryptoHash>(AlgoSHA3_256); } - if (strcmp(algo, "SHA3_384") == 0) { + if (algo == "SHA3_384") { return cm::make_unique<cmCryptoHash>(AlgoSHA3_384); } - if (strcmp(algo, "SHA3_512") == 0) { + if (algo == "SHA3_512") { return cm::make_unique<cmCryptoHash>(AlgoSHA3_512); } return std::unique_ptr<cmCryptoHash>(nullptr); @@ -106,6 +104,7 @@ std::string cmCryptoHash::ByteHashToString( '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; std::string res; + res.reserve(hash.size() * 2); for (unsigned char v : hash) { res.push_back(hex[v >> 4]); res.push_back(hex[v & 0xF]); @@ -113,12 +112,10 @@ std::string cmCryptoHash::ByteHashToString( return res; } -std::vector<unsigned char> cmCryptoHash::ByteHashString( - const std::string& input) +std::vector<unsigned char> cmCryptoHash::ByteHashString(cm::string_view input) { this->Initialize(); - this->Append(reinterpret_cast<unsigned char const*>(input.c_str()), - static_cast<int>(input.size())); + this->Append(input); return this->Finalize(); } @@ -156,7 +153,7 @@ std::vector<unsigned char> cmCryptoHash::ByteHashFile(const std::string& file) return std::vector<unsigned char>(); } -std::string cmCryptoHash::HashString(const std::string& input) +std::string cmCryptoHash::HashString(cm::string_view input) { return ByteHashToString(this->ByteHashString(input)); } @@ -176,9 +173,9 @@ void cmCryptoHash::Append(void const* buf, size_t sz) rhash_update(this->CTX, buf, sz); } -void cmCryptoHash::Append(std::string const& str) +void cmCryptoHash::Append(cm::string_view input) { - this->Append(str.c_str(), str.size()); + rhash_update(this->CTX, input.data(), input.size()); } std::vector<unsigned char> cmCryptoHash::Finalize() diff --git a/Source/cmCryptoHash.h b/Source/cmCryptoHash.h index b712f09..681f5cc 100644 --- a/Source/cmCryptoHash.h +++ b/Source/cmCryptoHash.h @@ -5,7 +5,9 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <memory> // IWYU pragma: keep +#include "cm_string_view.hxx" + +#include <memory> #include <stddef.h> #include <string> #include <vector> @@ -42,7 +44,7 @@ public: /// SHA3_224, SHA3_256, SHA3_384, SHA3_512 /// @return A valid auto pointer if algo is supported or /// an invalid/NULL pointer otherwise - static std::unique_ptr<cmCryptoHash> New(const char* algo); + static std::unique_ptr<cmCryptoHash> New(cm::string_view algo); /// @brief Converts a hex character to its binary value (4 bits) /// @arg input Hex character [0-9a-fA-F]. @@ -55,7 +57,7 @@ public: /// @brief Calculates a binary hash from string input data /// @return Binary hash vector - std::vector<unsigned char> ByteHashString(const std::string& input); + std::vector<unsigned char> ByteHashString(cm::string_view input); /// @brief Calculates a binary hash from file content /// @see ByteHashString() @@ -65,7 +67,7 @@ public: /// @brief Calculates a hash string from string input data /// @return Sequence of hex characters pairs for each byte of the binary hash - std::string HashString(const std::string& input); + std::string HashString(cm::string_view input); /// @brief Calculates a hash string from file content /// @see HashString() @@ -75,7 +77,7 @@ public: void Initialize(); void Append(void const*, size_t); - void Append(std::string const& str); + void Append(cm::string_view input); std::vector<unsigned char> Finalize(); std::string FinalizeHex(); diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx index 0004f66..233790e 100644 --- a/Source/cmCurl.cxx +++ b/Source/cmCurl.cxx @@ -7,6 +7,7 @@ # define CMAKE_FIND_CAFILE # include "cmSystemTools.h" #endif +#include "cmStringAlgorithms.h" // curl versions before 7.21.5 did not provide this error code #if defined(LIBCURL_VERSION_NUM) && LIBCURL_VERSION_NUM < 0x071505 @@ -72,8 +73,8 @@ std::string cmCurlSetNETRCOption(::CURL* curl, const std::string& netrc_level, } else if (netrc_level == "IGNORED") { curl_netrc_level = CURL_NETRC_IGNORED; } else { - e = "NETRC accepts OPTIONAL, IGNORED or REQUIRED but got: "; - e += netrc_level; + e = cmStrCat("NETRC accepts OPTIONAL, IGNORED or REQUIRED but got: ", + netrc_level); return e; } } diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index fe228ff..82cc037 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -10,9 +10,10 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" -#include <memory> // IWYU pragma: keep +#include <memory> #include <stddef.h> #include <utility> @@ -35,7 +36,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc, this->GE->Parse(clarg); std::string parsed_arg = cge->Evaluate(this->LG, this->Config); if (this->CC.GetCommandExpandLists()) { - cmAppend(argv, cmSystemTools::ExpandedListArgument(parsed_arg)); + cmAppend(argv, cmExpandedList(parsed_arg)); } else { argv.push_back(std::move(parsed_arg)); } @@ -54,8 +55,8 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc, std::vector<std::string> depends = this->CC.GetDepends(); for (std::string const& d : depends) { std::unique_ptr<cmCompiledGeneratorExpression> cge = this->GE->Parse(d); - std::vector<std::string> result = cmSystemTools::ExpandedListArgument( - cge->Evaluate(this->LG, this->Config)); + std::vector<std::string> result = + cmExpandedList(cge->Evaluate(this->LG, this->Config)); for (std::string& it : result) { if (cmSystemTools::FileIsFullPath(it)) { it = cmSystemTools::CollapseFullPath(it); @@ -108,8 +109,7 @@ void cmCustomCommandGenerator::FillEmulatorsWithArguments() continue; } - cmSystemTools::ExpandListArgument(emulator_property, - this->EmulatorsWithArguments[c]); + cmExpandList(emulator_property, this->EmulatorsWithArguments[c]); } } } @@ -169,9 +169,7 @@ std::string escapeForShellOldStyle(const std::string& str) std::string temp = str; if (temp.find(" ") != std::string::npos && temp.find("\"") == std::string::npos) { - result = "\""; - result += str; - result += "\""; + result = cmStrCat('"', str, '"'); return result; } return str; diff --git a/Source/cmDefinePropertyCommand.h b/Source/cmDefinePropertyCommand.h index a9c1856..36f97df 100644 --- a/Source/cmDefinePropertyCommand.h +++ b/Source/cmDefinePropertyCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -15,7 +17,10 @@ class cmExecutionStatus; class cmDefinePropertyCommand : public cmCommand { public: - cmCommand* Clone() override { return new cmDefinePropertyCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmDefinePropertyCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx index 5fafaf9..e688890 100644 --- a/Source/cmDefinitions.cxx +++ b/Source/cmDefinitions.cxx @@ -2,8 +2,11 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmDefinitions.h" +#include "cm_string_view.hxx" + #include <assert.h> -#include <set> +#include <functional> +#include <unordered_set> #include <utility> cmDefinitions::Def cmDefinitions::NoDef; @@ -13,10 +16,12 @@ cmDefinitions::Def const& cmDefinitions::GetInternal(const std::string& key, StackIter end, bool raise) { assert(begin != end); - MapType::iterator i = begin->Map.find(key); - if (i != begin->Map.end()) { - i->second.Used = true; - return i->second; + { + auto it = begin->Map.find(cm::String::borrow(key)); + if (it != begin->Map.end()) { + it->second.Used = true; + return it->second; + } } StackIter it = begin; ++it; @@ -27,14 +32,14 @@ cmDefinitions::Def const& cmDefinitions::GetInternal(const std::string& key, if (!raise) { return def; } - return begin->Map.insert(MapType::value_type(key, def)).first->second; + return begin->Map.emplace(key, def).first->second; } const std::string* cmDefinitions::Get(const std::string& key, StackIter begin, StackIter end) { Def const& def = cmDefinitions::GetInternal(key, begin, end, false); - return def.Exists ? &def : nullptr; + return def.Value ? def.Value.str_if_stable() : nullptr; } void cmDefinitions::Raise(const std::string& key, StackIter begin, @@ -47,47 +52,27 @@ bool cmDefinitions::HasKey(const std::string& key, StackIter begin, StackIter end) { for (StackIter it = begin; it != end; ++it) { - MapType::const_iterator i = it->Map.find(key); - if (i != it->Map.end()) { + if (it->Map.find(cm::String::borrow(key)) != it->Map.end()) { return true; } } return false; } -void cmDefinitions::Set(const std::string& key, const char* value) -{ - Def def(value); - this->Map[key] = def; -} - -std::vector<std::string> cmDefinitions::UnusedKeys() const -{ - std::vector<std::string> keys; - keys.reserve(this->Map.size()); - // Consider local definitions. - for (auto const& mi : this->Map) { - if (!mi.second.Used) { - keys.push_back(mi.first); - } - } - return keys; -} - cmDefinitions cmDefinitions::MakeClosure(StackIter begin, StackIter end) { cmDefinitions closure; - std::set<std::string> undefined; + std::unordered_set<cm::string_view> undefined; for (StackIter it = begin; it != end; ++it) { // Consider local definitions. for (auto const& mi : it->Map) { // Use this key if it is not already set or unset. if (closure.Map.find(mi.first) == closure.Map.end() && - undefined.find(mi.first) == undefined.end()) { - if (mi.second.Exists) { + undefined.find(mi.first.view()) == undefined.end()) { + if (mi.second.Value) { closure.Map.insert(mi); } else { - undefined.insert(mi.first); + undefined.emplace(mi.first.view()); } } } @@ -98,18 +83,41 @@ cmDefinitions cmDefinitions::MakeClosure(StackIter begin, StackIter end) std::vector<std::string> cmDefinitions::ClosureKeys(StackIter begin, StackIter end) { - std::set<std::string> bound; std::vector<std::string> defined; + std::unordered_set<cm::string_view> bound; for (StackIter it = begin; it != end; ++it) { defined.reserve(defined.size() + it->Map.size()); for (auto const& mi : it->Map) { // Use this key if it is not already set or unset. - if (bound.insert(mi.first).second && mi.second.Exists) { - defined.push_back(mi.first); + if (bound.emplace(mi.first.view()).second && mi.second.Value) { + defined.push_back(*mi.first.str_if_stable()); } } } return defined; } + +void cmDefinitions::Set(const std::string& key, cm::string_view value) +{ + this->Map[key] = Def(value); +} + +void cmDefinitions::Unset(const std::string& key) +{ + this->Map[key] = Def(); +} + +std::vector<std::string> cmDefinitions::UnusedKeys() const +{ + std::vector<std::string> keys; + keys.reserve(this->Map.size()); + // Consider local definitions. + for (auto const& mi : this->Map) { + if (!mi.second.Used) { + keys.push_back(*mi.first.str_if_stable()); + } + } + return keys; +} diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h index 6c252be..b4d6419 100644 --- a/Source/cmDefinitions.h +++ b/Source/cmDefinitions.h @@ -5,12 +5,16 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include "cm_string_view.hxx" + +#include "cmLinkedTree.h" +#include "cmString.hxx" + +#include <functional> #include <string> #include <unordered_map> #include <vector> -#include "cmLinkedTree.h" - /** \class cmDefinitions * \brief Store a scope of variable definitions for CMake language. * @@ -23,6 +27,8 @@ class cmDefinitions typedef cmLinkedTree<cmDefinitions>::iterator StackIter; public: + // -- Static member functions + static const std::string* Get(const std::string& key, StackIter begin, StackIter end); @@ -30,41 +36,37 @@ public: static bool HasKey(const std::string& key, StackIter begin, StackIter end); - /** Set (or unset if null) a value associated with a key. */ - void Set(const std::string& key, const char* value); - - std::vector<std::string> UnusedKeys() const; - static std::vector<std::string> ClosureKeys(StackIter begin, StackIter end); static cmDefinitions MakeClosure(StackIter begin, StackIter end); + // -- Member functions + + /** Set a value associated with a key. */ + void Set(const std::string& key, cm::string_view value); + + /** Unset a definition. */ + void Unset(const std::string& key); + + /** List of unused keys. */ + std::vector<std::string> UnusedKeys() const; + private: - // String with existence boolean. - struct Def : public std::string + /** String with existence boolean. */ + struct Def { - private: - typedef std::string std_string; - public: Def() = default; - Def(const char* v) - : std_string(v ? v : "") - , Exists(v ? true : false) - { - } - Def(const std_string& v) - : std_string(v) - , Exists(true) + Def(cm::string_view value) + : Value(value) { } - bool Exists = false; + cm::String Value; bool Used = false; }; static Def NoDef; - typedef std::unordered_map<std::string, Def> MapType; - MapType Map; + std::unordered_map<cm::String, Def> Map; static Def const& GetInternal(const std::string& key, StackIter begin, StackIter end, bool raise); diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index ed76dbf..06a442b 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -7,6 +7,7 @@ #include "cmGeneratedFileStream.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmsys/FStream.hxx" @@ -30,7 +31,7 @@ bool cmDepends::Write(std::ostream& makeDepends, std::ostream& internalDepends) { std::string const srcLang = "CMAKE_DEPENDS_CHECK_" + this->Language; cmMakefile* mf = this->LocalGenerator->GetMakefile(); - cmSystemTools::ExpandListArgument(mf->GetSafeDefinition(srcLang), pairs); + cmExpandList(mf->GetSafeDefinition(srcLang), pairs); } for (std::vector<std::string>::iterator si = pairs.begin(); si != pairs.end();) { @@ -235,21 +236,18 @@ void cmDepends::SetIncludePathFromLanguage(const std::string& lang) { // Look for the new per "TARGET_" variant first: const char* includePath = nullptr; - std::string includePathVar = "CMAKE_"; - includePathVar += lang; - includePathVar += "_TARGET_INCLUDE_PATH"; + std::string includePathVar = + cmStrCat("CMAKE_", lang, "_TARGET_INCLUDE_PATH"); cmMakefile* mf = this->LocalGenerator->GetMakefile(); includePath = mf->GetDefinition(includePathVar); if (includePath) { - cmSystemTools::ExpandListArgument(includePath, this->IncludePath); + cmExpandList(includePath, this->IncludePath); } else { // Fallback to the old directory level variable if no per-target var: - includePathVar = "CMAKE_"; - includePathVar += lang; - includePathVar += "_INCLUDE_PATH"; + includePathVar = cmStrCat("CMAKE_", lang, "_INCLUDE_PATH"); includePath = mf->GetDefinition(includePathVar); if (includePath) { - cmSystemTools::ExpandListArgument(includePath, this->IncludePath); + cmExpandList(includePath, this->IncludePath); } } } diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index dc49c18..0f9f166 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -9,6 +9,7 @@ #include "cmFileTime.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #define INCLUDE_REGEX_LINE \ @@ -35,15 +36,12 @@ cmDependsC::cmDependsC(cmLocalGenerator* lg, const std::string& targetDir, std::string scanRegex = "^.*$"; std::string complainRegex = "^$"; { - std::string scanRegexVar = "CMAKE_"; - scanRegexVar += lang; - scanRegexVar += "_INCLUDE_REGEX_SCAN"; + std::string scanRegexVar = cmStrCat("CMAKE_", lang, "_INCLUDE_REGEX_SCAN"); if (const char* sr = mf->GetDefinition(scanRegexVar)) { scanRegex = sr; } - std::string complainRegexVar = "CMAKE_"; - complainRegexVar += lang; - complainRegexVar += "_INCLUDE_REGEX_COMPLAIN"; + std::string complainRegexVar = + cmStrCat("CMAKE_", lang, "_INCLUDE_REGEX_COMPLAIN"); if (const char* cr = mf->GetDefinition(complainRegexVar)) { complainRegex = cr; } @@ -53,17 +51,15 @@ cmDependsC::cmDependsC(cmLocalGenerator* lg, const std::string& targetDir, this->IncludeRegexScan.compile(scanRegex); this->IncludeRegexComplain.compile(complainRegex); this->IncludeRegexLineString = INCLUDE_REGEX_LINE_MARKER INCLUDE_REGEX_LINE; - this->IncludeRegexScanString = INCLUDE_REGEX_SCAN_MARKER; - this->IncludeRegexScanString += scanRegex; - this->IncludeRegexComplainString = INCLUDE_REGEX_COMPLAIN_MARKER; - this->IncludeRegexComplainString += complainRegex; + this->IncludeRegexScanString = + cmStrCat(INCLUDE_REGEX_SCAN_MARKER, scanRegex); + this->IncludeRegexComplainString = + cmStrCat(INCLUDE_REGEX_COMPLAIN_MARKER, complainRegex); this->SetupTransforms(); - this->CacheFileName = this->TargetDirectory; - this->CacheFileName += "/"; - this->CacheFileName += lang; - this->CacheFileName += ".includecache"; + this->CacheFileName = + cmStrCat(this->TargetDirectory, '/', lang, ".includecache"); this->ReadCacheFile(); } @@ -391,7 +387,7 @@ void cmDependsC::SetupTransforms() std::vector<std::string> transformRules; cmMakefile* mf = this->LocalGenerator->GetMakefile(); if (const char* xform = mf->GetDefinition("CMAKE_INCLUDE_TRANSFORMS")) { - cmSystemTools::ExpandListArgument(xform, transformRules, true); + cmExpandList(xform, transformRules, true); } for (std::string const& tr : transformRules) { this->ParseTransform(tr); diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index 178e18b..6c77db9 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -9,7 +9,6 @@ #include <stdlib.h> #include <utility> -#include "cmAlgorithms.h" #include "cmFortranParser.h" /* Interface to parser object. */ #include "cmGeneratedFileStream.h" #include "cmLocalGenerator.h" @@ -17,6 +16,7 @@ #include "cmOutputConverter.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" // TODO: Test compiler for the case of the mod file. Some always @@ -82,7 +82,7 @@ cmDependsFortran::cmDependsFortran(cmLocalGenerator* lg) cmMakefile* mf = this->LocalGenerator->GetMakefile(); if (const char* c_defines = mf->GetDefinition("CMAKE_TARGET_DEFINITIONS_Fortran")) { - cmSystemTools::ExpandListArgument(c_defines, definitions); + cmExpandList(c_defines, definitions); } // translate i.e. FOO=BAR to FOO and add it to the list of defined @@ -180,8 +180,7 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, } // Store the list of modules provided by this target. - std::string fiName = this->TargetDirectory; - fiName += "/fortran.internal"; + std::string fiName = cmStrCat(this->TargetDirectory, "/fortran.internal"); cmGeneratedFileStream fiStream(fiName); fiStream << "# The fortran modules provided by this target.\n"; fiStream << "provides\n"; @@ -192,23 +191,18 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, // Create a script to clean the modules. if (!provides.empty()) { - std::string fcName = this->TargetDirectory; - fcName += "/cmake_clean_Fortran.cmake"; + std::string fcName = + cmStrCat(this->TargetDirectory, "/cmake_clean_Fortran.cmake"); cmGeneratedFileStream fcStream(fcName); fcStream << "# Remove fortran modules provided by this target.\n"; fcStream << "FILE(REMOVE"; std::string currentBinDir = this->LocalGenerator->GetCurrentBinaryDirectory(); for (std::string const& i : provides) { - std::string mod_upper = mod_dir; - mod_upper += "/"; - std::string mod_lower = mod_dir; - mod_lower += "/"; + std::string mod_upper = cmStrCat(mod_dir, '/'); + std::string mod_lower = cmStrCat(mod_dir, '/'); cmFortranModuleAppendUpperLower(i, mod_upper, mod_lower); - std::string stamp = stamp_dir; - stamp += "/"; - stamp += i; - stamp += ".stamp"; + std::string stamp = cmStrCat(stamp_dir, '/', i, ".stamp"); fcStream << "\n"; fcStream << " \"" << this->MaybeConvertToRelativePath(currentBinDir, mod_lower) @@ -254,7 +248,7 @@ void cmDependsFortran::LocateModules() std::vector<std::string> infoFiles; if (const char* infoFilesValue = mf->GetDefinition("CMAKE_TARGET_LINKED_INFO_FILES")) { - cmSystemTools::ExpandListArgument(infoFilesValue, infoFiles); + cmExpandList(infoFilesValue, infoFiles); } for (std::string const& i : infoFiles) { std::string targetDir = cmSystemTools::GetFilenamePath(i); @@ -315,10 +309,7 @@ void cmDependsFortran::ConsiderModule(const std::string& name, if (required != this->Internal->TargetRequires.end() && required->second.empty()) { // The module is provided by a CMake target. It will have a stamp file. - std::string stampFile = stampDir; - stampFile += "/"; - stampFile += name; - stampFile += ".stamp"; + std::string stampFile = cmStrCat(stampDir, '/', name, ".stamp"); required->second = stampFile; } } @@ -392,16 +383,11 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, // Always use lower case for the mod stamp file name. The // cmake_copy_f90_mod will call back to this class, which will // try various cases for the real mod file name. - std::string modFile = mod_dir; - modFile += "/"; - modFile += i; + std::string modFile = cmStrCat(mod_dir, '/', i); modFile = this->LocalGenerator->ConvertToOutputFormat( this->MaybeConvertToRelativePath(binDir, modFile), cmOutputConverter::SHELL); - std::string stampFile = stamp_dir; - stampFile += "/"; - stampFile += i; - stampFile += ".stamp"; + std::string stampFile = cmStrCat(stamp_dir, '/', i, ".stamp"); stampFile = this->MaybeConvertToRelativePath(binDir, stampFile); std::string const stampFileForShell = this->LocalGenerator->ConvertToOutputFormat(stampFile, @@ -435,8 +421,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, // Make sure the module timestamp rule is evaluated by the time // the target finishes building. - std::string driver = this->TargetDirectory; - driver += "/build"; + std::string driver = cmStrCat(this->TargetDirectory, "/build"); driver = cmSystemTools::ConvertToOutputPath( this->MaybeConvertToRelativePath(binDir, driver)); makeDepends << driver << ": " << obj_m << ".provides.build\n"; @@ -456,18 +441,14 @@ bool cmDependsFortran::FindModule(std::string const& name, std::string& module) std::string fullName; for (std::string const& ip : this->IncludePath) { // Try the lower-case name. - fullName = ip; - fullName += "/"; - fullName += mod_lower; + fullName = cmStrCat(ip, '/', mod_lower); if (cmSystemTools::FileExists(fullName, true)) { module = fullName; return true; } // Try the upper-case name. - fullName = ip; - fullName += "/"; - fullName += mod_upper; + fullName = cmStrCat(ip, '/', mod_upper); if (cmSystemTools::FileExists(fullName, true)) { module = fullName; return true; diff --git a/Source/cmDisallowedCommand.cxx b/Source/cmDisallowedCommand.cxx index 418d98c..aa1f90b 100644 --- a/Source/cmDisallowedCommand.cxx +++ b/Source/cmDisallowedCommand.cxx @@ -24,8 +24,6 @@ bool cmDisallowedCommand::InitialPass(std::vector<std::string> const& args, return true; } - this->Command->SetMakefile(this->GetMakefile()); - bool const ret = this->Command->InitialPass(args, status); - this->SetError(this->Command->GetError()); - return ret; + this->Command->SetExecutionStatus(this->GetExecutionStatus()); + return this->Command->InitialPass(args, status); } diff --git a/Source/cmDisallowedCommand.h b/Source/cmDisallowedCommand.h index d85c00f..e07f255 100644 --- a/Source/cmDisallowedCommand.h +++ b/Source/cmDisallowedCommand.h @@ -6,8 +6,11 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <string> +#include <utility> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" #include "cmPolicies.h" @@ -16,31 +19,27 @@ class cmExecutionStatus; class cmDisallowedCommand : public cmCommand { public: - cmDisallowedCommand(cmCommand* command, cmPolicies::PolicyID policy, - const char* message) - : Command(command) + cmDisallowedCommand(std::unique_ptr<cmCommand> command, + cmPolicies::PolicyID policy, const char* message) + : Command(std::move(command)) , Policy(policy) , Message(message) { } - ~cmDisallowedCommand() override { delete this->Command; } + ~cmDisallowedCommand() override = default; - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - return new cmDisallowedCommand(this->Command->Clone(), this->Policy, - this->Message); + return cm::make_unique<cmDisallowedCommand>(this->Command->Clone(), + this->Policy, this->Message); } bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; - void FinalPass() override { this->Command->FinalPass(); } - - bool HasFinalPass() const override { return this->Command->HasFinalPass(); } - private: - cmCommand* Command; + std::unique_ptr<cmCommand> Command; cmPolicies::PolicyID Policy; const char* Message; }; diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index 2226463..096016d 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -4,9 +4,10 @@ #include "cmAlgorithms.h" #include "cm_kwiml.h" +#include "cm_memory.hxx" #include "cmsys/FStream.hxx" #include <map> -#include <memory> // IWYU pragma: keep +#include <memory> #include <sstream> #include <stddef.h> #include <utility> @@ -109,10 +110,10 @@ public: }; // Construct and take ownership of the file stream object. - cmELFInternal(cmELF* external, std::unique_ptr<cmsys::ifstream>& fin, + cmELFInternal(cmELF* external, std::unique_ptr<std::istream> fin, ByteOrderType order) : External(external) - , Stream(*fin.release()) + , Stream(std::move(fin)) , ByteOrder(order) , ELFType(cmELF::FileTypeInvalid) { @@ -132,7 +133,7 @@ public: } // Destruct and delete the file stream object. - virtual ~cmELFInternal() { delete &this->Stream; } + virtual ~cmELFInternal() = default; // Forward to the per-class implementation. virtual unsigned int GetNumberOfSections() const = 0; @@ -171,7 +172,7 @@ protected: cmELF* External; // The stream from which to read. - std::istream& Stream; + std::unique_ptr<std::istream> Stream; // The byte order of the ELF file. ByteOrderType ByteOrder; @@ -233,7 +234,7 @@ public: typedef typename Types::tagtype tagtype; // Construct with a stream and byte swap indicator. - cmELFInternalImpl(cmELF* external, std::unique_ptr<cmsys::ifstream>& fin, + cmELFInternalImpl(cmELF* external, std::unique_ptr<std::istream> fin, ByteOrderType order); // Return the number of sections as specified by the ELF header. @@ -352,7 +353,7 @@ private: bool Read(ELF_Ehdr& x) { // Read the header from the file. - if (!this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x))) { + if (!this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x))) { return false; } @@ -382,26 +383,26 @@ private: } bool Read(ELF_Shdr& x) { - if (this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) && + if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) && this->NeedSwap) { ByteSwap(x); } - return !this->Stream.fail(); + return !this->Stream->fail(); } bool Read(ELF_Dyn& x) { - if (this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) && + if (this->Stream->read(reinterpret_cast<char*>(&x), sizeof(x)) && this->NeedSwap) { ByteSwap(x); } - return !this->Stream.fail(); + return !this->Stream->fail(); } bool LoadSectionHeader(ELF_Half i) { // Read the section header from the file. - this->Stream.seekg(this->ELFHeader.e_shoff + - this->ELFHeader.e_shentsize * i); + this->Stream->seekg(this->ELFHeader.e_shoff + + this->ELFHeader.e_shentsize * i); if (!this->Read(this->SectionHeaders[i])) { return false; } @@ -426,9 +427,10 @@ private: }; template <class Types> -cmELFInternalImpl<Types>::cmELFInternalImpl( - cmELF* external, std::unique_ptr<cmsys::ifstream>& fin, ByteOrderType order) - : cmELFInternal(external, fin, order) +cmELFInternalImpl<Types>::cmELFInternalImpl(cmELF* external, + std::unique_ptr<std::istream> fin, + ByteOrderType order) + : cmELFInternal(external, std::move(fin), order) { // Read the main header. if (!this->Read(this->ELFHeader)) { @@ -510,7 +512,7 @@ bool cmELFInternalImpl<Types>::LoadDynamicSection() // Read each entry. for (int j = 0; j < n; ++j) { // Seek to the beginning of the section entry. - this->Stream.seekg(sec.sh_offset + sec.sh_entsize * j); + this->Stream->seekg(sec.sh_offset + sec.sh_entsize * j); ELF_Dyn& dyn = this->DynamicSectionEntries[j]; // Try reading the entry. @@ -630,7 +632,7 @@ cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString( unsigned long first = static_cast<unsigned long>(dyn.d_un.d_val); unsigned long last = first; unsigned long end = static_cast<unsigned long>(strtab.sh_size); - this->Stream.seekg(strtab.sh_offset + first); + this->Stream->seekg(strtab.sh_offset + first); // Read the string. It may be followed by more than one NULL // terminator. Count the total size of the region allocated to @@ -639,7 +641,7 @@ cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString( // assumption. bool terminated = false; char c; - while (last != end && this->Stream.get(c) && !(terminated && c)) { + while (last != end && this->Stream->get(c) && !(terminated && c)) { ++last; if (c) { se.Value += c; @@ -649,7 +651,7 @@ cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString( } // Make sure the whole value was read. - if (!this->Stream) { + if (!(*this->Stream)) { this->SetErrorMessage("Dynamic section specifies unreadable RPATH."); se.Value = ""; return nullptr; @@ -679,10 +681,9 @@ const long cmELF::TagMipsRldMapRel = 0; #endif cmELF::cmELF(const char* fname) - : Internal(nullptr) { // Try to open the file. - std::unique_ptr<cmsys::ifstream> fin(new cmsys::ifstream(fname)); + auto fin = cm::make_unique<cmsys::ifstream>(fname); // Quit now if the file could not be opened. if (!fin || !*fin) { @@ -725,12 +726,14 @@ cmELF::cmELF(const char* fname) // parser implementation. if (ident[EI_CLASS] == ELFCLASS32) { // 32-bit ELF - this->Internal = new cmELFInternalImpl<cmELFTypes32>(this, fin, order); + this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes32>>( + this, std::move(fin), order); } #ifndef _SCO_DS else if (ident[EI_CLASS] == ELFCLASS64) { // 64-bit ELF - this->Internal = new cmELFInternalImpl<cmELFTypes64>(this, fin, order); + this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes64>>( + this, std::move(fin), order); } #endif else { @@ -739,10 +742,7 @@ cmELF::cmELF(const char* fname) } } -cmELF::~cmELF() -{ - delete this->Internal; -} +cmELF::~cmELF() = default; bool cmELF::Valid() const { diff --git a/Source/cmELF.h b/Source/cmELF.h index 987f0c3..afef654 100644 --- a/Source/cmELF.h +++ b/Source/cmELF.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> +#include <memory> #include <string> #include <utility> #include <vector> @@ -108,7 +109,7 @@ public: private: friend class cmELFInternal; bool Valid() const; - cmELFInternal* Internal; + std::unique_ptr<cmELFInternal> Internal; std::string ErrorMessage; }; diff --git a/Source/cmEnableLanguageCommand.h b/Source/cmEnableLanguageCommand.h index 97645a9..dc43e34 100644 --- a/Source/cmEnableLanguageCommand.h +++ b/Source/cmEnableLanguageCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -26,7 +28,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmEnableLanguageCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmEnableLanguageCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmEnableTestingCommand.cxx b/Source/cmEnableTestingCommand.cxx index 6a64450..89212c8 100644 --- a/Source/cmEnableTestingCommand.cxx +++ b/Source/cmEnableTestingCommand.cxx @@ -2,15 +2,12 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmEnableTestingCommand.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" -class cmExecutionStatus; - -// we do this in the final pass so that we now the subdirs have all -// been defined -bool cmEnableTestingCommand::InitialPass(std::vector<std::string> const&, - cmExecutionStatus&) +bool cmEnableTestingCommand(std::vector<std::string> const&, + cmExecutionStatus& status) { - this->Makefile->AddDefinition("CMAKE_TESTING_ENABLED", "1"); + status.GetMakefile().AddDefinition("CMAKE_TESTING_ENABLED", "1"); return true; } diff --git a/Source/cmEnableTestingCommand.h b/Source/cmEnableTestingCommand.h index 88a17b9..e4593f2 100644 --- a/Source/cmEnableTestingCommand.h +++ b/Source/cmEnableTestingCommand.h @@ -8,11 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmEnableTestingCommand +/** * \brief Enable testing for this directory and below. * * Produce the output testfile. This produces a file in the build directory @@ -25,20 +23,7 @@ class cmExecutionStatus; * Note that CTest expects to find this file in the build directory root; * therefore, this command should be in the source directory root too. */ -class cmEnableTestingCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmEnableTestingCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const&, - cmExecutionStatus&) override; -}; +bool cmEnableTestingCommand(std::vector<std::string> const&, + cmExecutionStatus&); #endif diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx index 4b559e7..7f41640 100644 --- a/Source/cmExecProgramCommand.cxx +++ b/Source/cmExecProgramCommand.cxx @@ -5,18 +5,26 @@ #include "cmsys/Process.h" #include <stdio.h> +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmProcessOutput.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmExecutionStatus; +typedef cmProcessOutput::Encoding Encoding; + +namespace { +bool RunCommand(std::string command, std::string& output, int& retVal, + const char* directory = nullptr, bool verbose = true, + Encoding encoding = cmProcessOutput::Auto); +} // cmExecProgramCommand -bool cmExecProgramCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmExecProgramCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } std::string arguments; @@ -34,7 +42,7 @@ bool cmExecProgramCommand::InitialPass(std::vector<std::string> const& args, haveoutput_variable = true; } else if (haveoutput_variable) { if (!output_variable.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } output_variable = arg; @@ -47,7 +55,7 @@ bool cmExecProgramCommand::InitialPass(std::vector<std::string> const& args, havereturn_variable = true; } else if (havereturn_variable) { if (!return_variable.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } return_variable = arg; @@ -67,9 +75,8 @@ bool cmExecProgramCommand::InitialPass(std::vector<std::string> const& args, std::string command; if (!arguments.empty()) { - command = cmSystemTools::ConvertToRunCommandPath(args[0]); - command += " "; - command += arguments; + command = cmStrCat(cmSystemTools::ConvertToRunCommandPath(args[0]), ' ', + arguments); } else { command = args[0]; } @@ -82,11 +89,9 @@ bool cmExecProgramCommand::InitialPass(std::vector<std::string> const& args, bool result = true; if (args.size() - count == 2) { cmSystemTools::MakeDirectory(args[1]); - result = cmExecProgramCommand::RunCommand(command, output, retVal, - args[1].c_str(), verbose); + result = RunCommand(command, output, retVal, args[1].c_str(), verbose); } else { - result = cmExecProgramCommand::RunCommand(command, output, retVal, nullptr, - verbose); + result = RunCommand(command, output, retVal, nullptr, verbose); } if (!result) { retVal = -1; @@ -103,21 +108,21 @@ bool cmExecProgramCommand::InitialPass(std::vector<std::string> const& args, } std::string coutput = std::string(output, first, last - first + 1); - this->Makefile->AddDefinition(output_variable, coutput.c_str()); + status.GetMakefile().AddDefinition(output_variable, coutput); } if (!return_variable.empty()) { char buffer[100]; sprintf(buffer, "%d", retVal); - this->Makefile->AddDefinition(return_variable, buffer); + status.GetMakefile().AddDefinition(return_variable, buffer); } return true; } -bool cmExecProgramCommand::RunCommand(std::string command, std::string& output, - int& retVal, const char* dir, - bool verbose, Encoding encoding) +namespace { +bool RunCommand(std::string command, std::string& output, int& retVal, + const char* dir, bool verbose, Encoding encoding) { if (cmSystemTools::GetRunCommandOutput()) { verbose = false; @@ -187,10 +192,7 @@ bool cmExecProgramCommand::RunCommand(std::string command, std::string& output, #else std::string commandInDir; if (dir) { - commandInDir = "cd \""; - commandInDir += dir; - commandInDir += "\" && "; - commandInDir += command; + commandInDir = cmStrCat("cd \"", dir, "\" && ", command); } else { commandInDir = command; } @@ -284,3 +286,4 @@ bool cmExecProgramCommand::RunCommand(std::string command, std::string& output, return true; } +} diff --git a/Source/cmExecProgramCommand.h b/Source/cmExecProgramCommand.h index ae0fa9b..7c751e1 100644 --- a/Source/cmExecProgramCommand.h +++ b/Source/cmExecProgramCommand.h @@ -8,38 +8,16 @@ #include <string> #include <vector> -#include "cmCommand.h" -#include "cmProcessOutput.h" - class cmExecutionStatus; -/** \class cmExecProgramCommand +/** * \brief Command that adds a target to the build system. * * cmExecProgramCommand adds an extra target to the build system. * This is useful when you would like to add special * targets like "install,", "clean," and so on. */ -class cmExecProgramCommand : public cmCommand -{ -public: - typedef cmProcessOutput::Encoding Encoding; - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmExecProgramCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - static bool RunCommand(std::string command, std::string& output, int& retVal, - const char* directory = nullptr, bool verbose = true, - Encoding encoding = cmProcessOutput::Auto); -}; +bool cmExecProgramCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index 494afbb..acf2a83 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -4,21 +4,25 @@ #include "cm_static_string_view.hxx" #include "cmsys/Process.h" + #include <algorithm> #include <ctype.h> /* isspace */ #include <iostream> +#include <memory> #include <stdio.h> +#include <vector> #include "cmAlgorithms.h" #include "cmArgumentParser.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmProcessOutput.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmExecutionStatus; - -static bool cmExecuteProcessCommandIsWhitespace(char c) +namespace { +bool cmExecuteProcessCommandIsWhitespace(char c) { return (isspace(static_cast<int>(c)) || c == '\n' || c == '\r'); } @@ -27,13 +31,14 @@ void cmExecuteProcessCommandFixText(std::vector<char>& output, bool strip_trailing_whitespace); void cmExecuteProcessCommandAppend(std::vector<char>& output, const char* data, int length); +} // cmExecuteProcessCommand -bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmExecuteProcessCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } @@ -84,31 +89,31 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, parser.Parse(args, &unparsedArguments, &keywordsMissingValue); if (!keywordsMissingValue.empty()) { - this->SetError(" called with no value for " + - keywordsMissingValue.front() + "."); + status.SetError(" called with no value for " + + keywordsMissingValue.front() + "."); return false; } if (!unparsedArguments.empty()) { - this->SetError(" given unknown argument \"" + unparsedArguments.front() + - "\"."); + status.SetError(" given unknown argument \"" + unparsedArguments.front() + + "\"."); return false; } - if (!this->Makefile->CanIWriteThisFile(arguments.OutputFile)) { - this->SetError("attempted to output into a file: " + arguments.OutputFile + - " into a source directory."); + if (!status.GetMakefile().CanIWriteThisFile(arguments.OutputFile)) { + status.SetError("attempted to output into a file: " + + arguments.OutputFile + " into a source directory."); cmSystemTools::SetFatalErrorOccured(); return false; } // Check for commands given. if (arguments.Commands.empty()) { - this->SetError(" called with no COMMAND argument."); + status.SetError(" called with no COMMAND argument."); return false; } for (std::vector<std::string> const& cmd : arguments.Commands) { if (cmd.empty()) { - this->SetError(" given COMMAND argument with no value."); + status.SetError(" given COMMAND argument with no value."); return false; } } @@ -117,7 +122,7 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, double timeout = -1; if (!arguments.Timeout.empty()) { if (sscanf(arguments.Timeout.c_str(), "%lg", &timeout) != 1) { - this->SetError(" called with TIMEOUT value that could not be parsed."); + status.SetError(" called with TIMEOUT value that could not be parsed."); return false; } } @@ -177,8 +182,8 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, bool echo_stdout = false; bool echo_stderr = false; bool echo_output_from_variable = true; - std::string echo_output = - this->Makefile->GetSafeDefinition("CMAKE_EXECUTE_PROCESS_COMMAND_ECHO"); + std::string echo_output = status.GetMakefile().GetSafeDefinition( + "CMAKE_EXECUTE_PROCESS_COMMAND_ECHO"); if (!arguments.CommandEcho.empty()) { echo_output_from_variable = false; echo_output = arguments.CommandEcho; @@ -201,7 +206,7 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, if (!echo_output_from_variable) { error += " for COMMAND_ECHO."; } - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, error); + status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, error); return true; } } @@ -275,11 +280,13 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, // Store the output obtained. if (!arguments.OutputVariable.empty() && !tempOutput.empty()) { - this->Makefile->AddDefinition(arguments.OutputVariable, tempOutput.data()); + status.GetMakefile().AddDefinition(arguments.OutputVariable, + tempOutput.data()); } if (!merge_output && !arguments.ErrorVariable.empty() && !tempError.empty()) { - this->Makefile->AddDefinition(arguments.ErrorVariable, tempError.data()); + status.GetMakefile().AddDefinition(arguments.ErrorVariable, + tempError.data()); } // Store the result of running the process. @@ -289,19 +296,19 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, int v = cmsysProcess_GetExitValue(cp); char buf[16]; sprintf(buf, "%d", v); - this->Makefile->AddDefinition(arguments.ResultVariable, buf); + status.GetMakefile().AddDefinition(arguments.ResultVariable, buf); } break; case cmsysProcess_State_Exception: - this->Makefile->AddDefinition(arguments.ResultVariable, - cmsysProcess_GetExceptionString(cp)); + status.GetMakefile().AddDefinition( + arguments.ResultVariable, cmsysProcess_GetExceptionString(cp)); break; case cmsysProcess_State_Error: - this->Makefile->AddDefinition(arguments.ResultVariable, - cmsysProcess_GetErrorString(cp)); + status.GetMakefile().AddDefinition(arguments.ResultVariable, + cmsysProcess_GetErrorString(cp)); break; case cmsysProcess_State_Expired: - this->Makefile->AddDefinition(arguments.ResultVariable, - "Process terminated due to timeout"); + status.GetMakefile().AddDefinition( + arguments.ResultVariable, "Process terminated due to timeout"); break; } } @@ -329,20 +336,20 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, break; } } - this->Makefile->AddDefinition(arguments.ResultsVariable, - cmJoin(res, ";").c_str()); + status.GetMakefile().AddDefinition(arguments.ResultsVariable, + cmJoin(res, ";")); } break; case cmsysProcess_State_Exception: - this->Makefile->AddDefinition(arguments.ResultsVariable, - cmsysProcess_GetExceptionString(cp)); + status.GetMakefile().AddDefinition( + arguments.ResultsVariable, cmsysProcess_GetExceptionString(cp)); break; case cmsysProcess_State_Error: - this->Makefile->AddDefinition(arguments.ResultsVariable, - cmsysProcess_GetErrorString(cp)); + status.GetMakefile().AddDefinition(arguments.ResultsVariable, + cmsysProcess_GetErrorString(cp)); break; case cmsysProcess_State_Expired: - this->Makefile->AddDefinition(arguments.ResultsVariable, - "Process terminated due to timeout"); + status.GetMakefile().AddDefinition( + arguments.ResultsVariable, "Process terminated due to timeout"); break; } } @@ -350,6 +357,7 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, return true; } +namespace { void cmExecuteProcessCommandFixText(std::vector<char>& output, bool strip_trailing_whitespace) { @@ -395,3 +403,4 @@ void cmExecuteProcessCommandAppend(std::vector<char>& output, const char* data, #endif cmAppend(output, data, data + length); } +} diff --git a/Source/cmExecuteProcessCommand.h b/Source/cmExecuteProcessCommand.h index b415deb..9c4b600 100644 --- a/Source/cmExecuteProcessCommand.h +++ b/Source/cmExecuteProcessCommand.h @@ -8,30 +8,15 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmExecuteProcessCommand +/** * \brief Command that adds a target to the build system. * * cmExecuteProcessCommand is a CMake language interface to the KWSys * Process Execution implementation. */ -class cmExecuteProcessCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmExecuteProcessCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmExecuteProcessCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmExecutionStatus.h b/Source/cmExecutionStatus.h index 56199dd..654922c 100644 --- a/Source/cmExecutionStatus.h +++ b/Source/cmExecutionStatus.h @@ -3,6 +3,11 @@ #ifndef cmExecutionStatus_h #define cmExecutionStatus_h +#include <cmConfigure.h> // IWYU pragma: keep +#include <string> + +class cmMakefile; + /** \class cmExecutionStatus * \brief Superclass for all command status classes * @@ -11,14 +16,17 @@ class cmExecutionStatus { public: - void Clear() + cmExecutionStatus(cmMakefile& makefile) + : Makefile(makefile) + , Error("unknown error.") { - this->ReturnInvoked = false; - this->BreakInvoked = false; - this->ContinueInvoked = false; - this->NestedError = false; } + cmMakefile& GetMakefile() { return this->Makefile; } + + void SetError(std::string const& e) { this->Error = e; } + std::string const& GetError() const { return this->Error; } + void SetReturnInvoked() { this->ReturnInvoked = true; } bool GetReturnInvoked() const { return this->ReturnInvoked; } @@ -32,6 +40,8 @@ public: bool GetNestedError() const { return this->NestedError; } private: + cmMakefile& Makefile; + std::string Error; bool ReturnInvoked = false; bool BreakInvoked = false; bool ContinueInvoked = false; diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx index ced27c9..561e830 100644 --- a/Source/cmExportBuildAndroidMKGenerator.cxx +++ b/Source/cmExportBuildAndroidMKGenerator.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExportBuildAndroidMKGenerator.h" -#include <algorithm> -#include <memory> // IWYU pragma: keep #include <sstream> #include <utility> @@ -14,6 +12,7 @@ #include "cmMessageType.h" #include "cmPolicies.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -42,8 +41,7 @@ void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode( std::ostream& os, cmGeneratorTarget const* target, cmStateEnums::TargetType /*targetType*/) { - std::string targetName = this->Namespace; - targetName += target->GetExportName(); + std::string targetName = cmStrCat(this->Namespace, target->GetExportName()); os << "include $(CLEAR_VARS)\n"; os << "LOCAL_MODULE := "; os << targetName << "\n"; @@ -145,8 +143,7 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties( } } else if (property.first == "INTERFACE_INCLUDE_DIRECTORIES") { std::string includes = property.second; - std::vector<std::string> includeList; - cmSystemTools::ExpandListArgument(includes, includeList); + std::vector<std::string> includeList = cmExpandedList(includes); os << "LOCAL_EXPORT_C_INCLUDES := "; std::string end; for (std::string const& i : includeList) { @@ -156,8 +153,8 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties( os << "\n"; } else if (property.first == "INTERFACE_LINK_OPTIONS") { os << "LOCAL_EXPORT_LDFLAGS := "; - std::vector<std::string> linkFlagsList; - cmSystemTools::ExpandListArgument(property.second, linkFlagsList); + std::vector<std::string> linkFlagsList = + cmExpandedList(property.second); os << cmJoin(linkFlagsList, " ") << "\n"; } else { os << "# " << property.first << " " << (property.second) << "\n"; @@ -168,8 +165,7 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties( // Tell the NDK build system if prebuilt static libraries use C++. if (target->GetType() == cmStateEnums::STATIC_LIBRARY) { cmLinkImplementation const* li = target->GetLinkImplementation(config); - if (std::find(li->Languages.begin(), li->Languages.end(), "CXX") != - li->Languages.end()) { + if (cmContains(li->Languages, "CXX")) { os << "LOCAL_HAS_CPP := true\n"; } } diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 012355b..8a1a305 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExportBuildFileGenerator.h" -#include "cmAlgorithms.h" #include "cmExportSet.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" @@ -12,12 +11,11 @@ #include "cmMessageType.h" #include "cmPolicies.h" #include "cmStateTypes.h" -#include "cmSystemTools.h" +#include "cmStringAlgorithms.h" #include "cmTarget.h" #include "cmTargetExport.h" #include "cmake.h" -#include <algorithm> #include <map> #include <set> #include <sstream> @@ -45,6 +43,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) std::string expectedTargets; std::string sep; std::vector<std::string> targets; + bool generatedInterfaceRequired = false; this->GetTargets(targets); for (std::string const& tei : targets) { cmGeneratorTarget* te = this->LG->FindGeneratorTargetToUse(tei); @@ -60,11 +59,13 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) this->LG->GetMakefile()->GetBacktrace()); return false; } - if (this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY) { - this->GenerateRequiredCMakeVersion(os, "3.0.0"); - } + generatedInterfaceRequired |= + this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY; } + if (generatedInterfaceRequired) { + this->GenerateRequiredCMakeVersion(os, "3.0.0"); + } this->GenerateExpectedTargetsCode(os, expectedTargets); } @@ -201,8 +202,7 @@ void cmExportBuildFileGenerator::SetImportLocationProperty( cmMakefile* mf = target->Makefile; if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) { - std::string prop = "IMPORTED_OBJECTS"; - prop += suffix; + std::string prop = cmStrCat("IMPORTED_OBJECTS", suffix); // Compute all the object files inside this target and setup // IMPORTED_OBJECTS as a list of object files @@ -220,8 +220,7 @@ void cmExportBuildFileGenerator::SetImportLocationProperty( } else { // Add the main target file. { - std::string prop = "IMPORTED_LOCATION"; - prop += suffix; + std::string prop = cmStrCat("IMPORTED_LOCATION", suffix); std::string value; if (target->IsAppBundleOnApple()) { value = @@ -234,14 +233,14 @@ void cmExportBuildFileGenerator::SetImportLocationProperty( } // Add the import library for windows DLLs. - if (target->HasImportLibrary(config) && - mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) { - std::string prop = "IMPORTED_IMPLIB"; - prop += suffix; + if (target->HasImportLibrary(config)) { + std::string prop = cmStrCat("IMPORTED_IMPLIB", suffix); std::string value = target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact); - target->GetImplibGNUtoMS(config, value, value, - "${CMAKE_IMPORT_LIBRARY_SUFFIX}"); + if (mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) { + target->GetImplibGNUtoMS(config, value, value, + "${CMAKE_IMPORT_LIBRARY_SUFFIX}"); + } properties[prop] = value; } } @@ -256,11 +255,11 @@ void cmExportBuildFileGenerator::HandleMissingTarget( const std::string name = dependee->GetName(); cmGlobalGenerator* gg = dependee->GetLocalGenerator()->GetGlobalGenerator(); - std::vector<std::string> namespaces = this->FindNamespaces(gg, name); + auto exportInfo = this->FindBuildExportInfo(gg, name); + std::vector<std::string> const& exportFiles = exportInfo.first; - int targetOccurrences = static_cast<int>(namespaces.size()); - if (targetOccurrences == 1) { - std::string missingTarget = namespaces[0]; + if (exportFiles.size() == 1) { + std::string missingTarget = exportInfo.second; missingTarget += dependee->GetExportName(); link_libs += missingTarget; @@ -269,7 +268,7 @@ void cmExportBuildFileGenerator::HandleMissingTarget( } // We are not appending, so all exported targets should be // known here. This is probably user-error. - this->ComplainAboutMissingTarget(depender, dependee, targetOccurrences); + this->ComplainAboutMissingTarget(depender, dependee, exportFiles); } // Assume the target will be exported by another command. // Append it with the export namespace. @@ -289,10 +288,12 @@ void cmExportBuildFileGenerator::GetTargets( targets = this->Targets; } -std::vector<std::string> cmExportBuildFileGenerator::FindNamespaces( - cmGlobalGenerator* gg, const std::string& name) +std::pair<std::vector<std::string>, std::string> +cmExportBuildFileGenerator::FindBuildExportInfo(cmGlobalGenerator* gg, + const std::string& name) { - std::vector<std::string> namespaces; + std::vector<std::string> exportFiles; + std::string ns; std::map<std::string, cmExportBuildFileGenerator*>& exportSets = gg->GetBuildExportSets(); @@ -301,32 +302,32 @@ std::vector<std::string> cmExportBuildFileGenerator::FindNamespaces( const cmExportBuildFileGenerator* exportSet = exp.second; std::vector<std::string> targets; exportSet->GetTargets(targets); - if (std::find(targets.begin(), targets.end(), name) != targets.end()) { - namespaces.push_back(exportSet->GetNamespace()); + if (cmContains(targets, name)) { + exportFiles.push_back(exp.first); + ns = exportSet->GetNamespace(); } } - return namespaces; + return std::make_pair(exportFiles, ns); } void cmExportBuildFileGenerator::ComplainAboutMissingTarget( - cmGeneratorTarget* depender, cmGeneratorTarget* dependee, int occurrences) + cmGeneratorTarget* depender, cmGeneratorTarget* dependee, + std::vector<std::string> const& exportFiles) { - if (cmSystemTools::GetErrorOccuredFlag()) { - return; - } - std::ostringstream e; e << "export called with target \"" << depender->GetName() << "\" which requires target \"" << dependee->GetName() << "\" "; - if (occurrences == 0) { - e << "that is not in the export set.\n"; + if (exportFiles.empty()) { + e << "that is not in any export set."; } else { - e << "that is not in this export set, but " << occurrences - << " times in others.\n"; + e << "that is not in this export set, but in multiple other export sets: " + << cmJoin(exportFiles, ", ") << ".\n"; + e << "An exported target cannot depend upon another target which is " + "exported multiple times. Consider consolidating the exports of the " + "\"" + << dependee->GetName() << "\" target to a single export."; } - e << "If the required target is not easy to reference in this call, " - << "consider using the APPEND option with multiple separate calls."; this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( MessageType::FATAL_ERROR, e.str(), diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 0a1e755..e5b6597 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -11,6 +11,7 @@ #include <iosfwd> #include <string> +#include <utility> #include <vector> class cmExportSet; @@ -64,7 +65,7 @@ protected: void ComplainAboutMissingTarget(cmGeneratorTarget* depender, cmGeneratorTarget* dependee, - int occurrences); + std::vector<std::string> const& namespaces); /** Fill in properties indicating built file locations. */ void SetImportLocationProperty(const std::string& config, @@ -75,8 +76,8 @@ protected: std::string InstallNameDir(cmGeneratorTarget* target, const std::string& config) override; - std::vector<std::string> FindNamespaces(cmGlobalGenerator* gg, - const std::string& name); + std::pair<std::vector<std::string>, std::string> FindBuildExportInfo( + cmGlobalGenerator* gg, const std::string& name); std::vector<std::string> Targets; cmExportSet* ExportSet; diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index a849aa2..4046f91 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -5,11 +5,11 @@ #include "cm_static_string_view.hxx" #include "cmsys/RegularExpression.hxx" -#include <algorithm> #include <map> #include <sstream> #include <utility> +#include "cmAlgorithms.h" #include "cmArgumentParser.h" #include "cmExportBuildAndroidMKGenerator.h" #include "cmExportBuildFileGenerator.h" @@ -133,9 +133,7 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args, } ExportSet = it->second; } else if (!arguments.Targets.empty() || - std::find(keywordsMissingValue.begin(), - keywordsMissingValue.end(), - "TARGETS") != keywordsMissingValue.end()) { + cmContains(keywordsMissingValue, "TARGETS")) { for (std::string const& currentTarget : arguments.Targets) { if (this->Makefile->IsAlias(currentTarget)) { std::ostringstream e; @@ -301,8 +299,7 @@ void cmExportCommand::StorePackageRegistryWin(std::string const& package, const char* content, const char* hash) { - std::string key = "Software\\Kitware\\CMake\\Packages\\"; - key += package; + std::string key = cmStrCat("Software\\Kitware\\CMake\\Packages\\", package); HKEY hKey; LONG err = RegCreateKeyExW(HKEY_CURRENT_USER, cmsys::Encoding::ToWide(key).c_str(), 0, @@ -336,9 +333,7 @@ void cmExportCommand::StorePackageRegistryDir(std::string const& package, B_OK) { return; } - std::string fname = dir; - fname += "/cmake/packages/"; - fname += package; + std::string fname = cmStrCat(dir, "/cmake/packages/", package); # else std::string fname; if (!cmSystemTools::GetEnv("HOME", fname)) { diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h index 99f9932..50463af 100644 --- a/Source/cmExportCommand.h +++ b/Source/cmExportCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -18,7 +20,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmExportCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmExportCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index a12e0c4..70f98bf 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExportFileGenerator.h" -#include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" @@ -12,20 +11,21 @@ #include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" -#include "cmProperty.h" #include "cmPropertyMap.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetExport.h" #include "cmsys/FStream.hxx" #include <assert.h> -#include <memory> // IWYU pragma: keep #include <sstream> #include <string.h> #include <utility> +#include "cm_memory.hxx" + static std::string cmExportFileGeneratorEscape(std::string const& str) { // Escape a property value for writing into a .cmake file. @@ -499,8 +499,7 @@ void getPropertyContents(cmGeneratorTarget const* tgt, const std::string& prop, if (!p) { return; } - std::vector<std::string> content; - cmSystemTools::ExpandListArgument(p, content); + std::vector<std::string> content = cmExpandedList(p); ifaceProperties.insert(content.begin(), content.end()); } @@ -584,8 +583,8 @@ void cmExportFileGenerator::GenerateInterfaceProperties( const ImportPropertyMap& properties) { if (!properties.empty()) { - std::string targetName = this->Namespace; - targetName += target->GetExportName(); + std::string targetName = + cmStrCat(this->Namespace, target->GetExportName()); os << "set_target_properties(" << targetName << " PROPERTIES\n"; for (auto const& property : properties) { os << " " << property.first << " " @@ -841,19 +840,16 @@ void cmExportFileGenerator::SetImportDetailProperties( "IMPORTED_LINK_DEPENDENT_LIBRARIES", iface->SharedDeps, properties, dummy); if (iface->Multiplicity > 0) { - std::string prop = "IMPORTED_LINK_INTERFACE_MULTIPLICITY"; - prop += suffix; - std::ostringstream m; - m << iface->Multiplicity; - properties[prop] = m.str(); + std::string prop = + cmStrCat("IMPORTED_LINK_INTERFACE_MULTIPLICITY", suffix); + properties[prop] = std::to_string(iface->Multiplicity); } } // Add information if this target is a managed target if (target->GetManagedType(config) != cmGeneratorTarget::ManagedType::Native) { - std::string prop = "IMPORTED_COMMON_LANGUAGE_RUNTIME"; - prop += suffix; + std::string prop = cmStrCat("IMPORTED_COMMON_LANGUAGE_RUNTIME", suffix); std::string propval; if (auto* p = target->GetProperty("COMMON_LANGUAGE_RUNTIME")) { propval = p; @@ -904,8 +900,7 @@ void cmExportFileGenerator::SetImportLinkProperty( } // Store the property. - std::string prop = propName; - prop += suffix; + std::string prop = cmStrCat(propName, suffix); properties[prop] = link_entries; } @@ -1182,8 +1177,7 @@ void cmExportFileGenerator::GenerateImportedFileChecksCode( const std::set<std::string>& importedLocations) { // Construct the imported target name. - std::string targetName = this->Namespace; - targetName += target->GetExportName(); + std::string targetName = cmStrCat(this->Namespace, target->GetExportName()); os << "list(APPEND _IMPORT_CHECK_TARGETS " << targetName << " )\n" @@ -1205,15 +1199,12 @@ bool cmExportFileGenerator::PopulateExportProperties( std::string& errorMessage) { auto& targetProperties = gte->Target->GetProperties(); - const auto& exportProperties = targetProperties.find("EXPORT_PROPERTIES"); - if (exportProperties != targetProperties.end()) { - std::vector<std::string> propsToExport; - cmSystemTools::ExpandListArgument(exportProperties->second.GetValue(), - propsToExport); - for (auto& prop : propsToExport) { + if (const char* exportProperties = + targetProperties.GetPropertyValue("EXPORT_PROPERTIES")) { + for (auto& prop : cmExpandedList(exportProperties)) { /* Black list reserved properties */ - if (cmSystemTools::StringStartsWith(prop, "IMPORTED_") || - cmSystemTools::StringStartsWith(prop, "INTERFACE_")) { + if (cmHasLiteralPrefix(prop, "IMPORTED_") || + cmHasLiteralPrefix(prop, "INTERFACE_")) { std::ostringstream e; e << "Target \"" << gte->Target->GetName() << "\" contains property \"" << prop << "\" in EXPORT_PROPERTIES but IMPORTED_* and INTERFACE_* " diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx index 9bc8089..1b536c9 100644 --- a/Source/cmExportInstallAndroidMKGenerator.cxx +++ b/Source/cmExportInstallAndroidMKGenerator.cxx @@ -11,6 +11,7 @@ #include "cmInstallExportGenerator.h" #include "cmInstallTargetGenerator.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetExport.h" @@ -58,8 +59,7 @@ void cmExportInstallAndroidMKGenerator::GenerateImportTargetCode( std::ostream& os, cmGeneratorTarget const* target, cmStateEnums::TargetType /*targetType*/) { - std::string targetName = this->Namespace; - targetName += target->GetExportName(); + std::string targetName = cmStrCat(this->Namespace, target->GetExportName()); os << "include $(CLEAR_VARS)\n"; os << "LOCAL_MODULE := "; os << targetName << "\n"; diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index f8bc0ab..e7f301e 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExportInstallFileGenerator.h" -#include "cmAlgorithms.h" #include "cmExportSet.h" #include "cmExportSetMap.h" #include "cmGeneratedFileStream.h" @@ -15,6 +14,7 @@ #include "cmMakefile.h" #include "cmPolicies.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetExport.h" @@ -30,9 +30,7 @@ cmExportInstallFileGenerator::cmExportInstallFileGenerator( std::string cmExportInstallFileGenerator::GetConfigImportFileGlob() { - std::string glob = this->FileBase; - glob += "-*"; - glob += this->FileExt; + std::string glob = cmStrCat(this->FileBase, "-*", this->FileExt); return glob; } @@ -277,10 +275,7 @@ bool cmExportInstallFileGenerator::GenerateImportFileConfig( } // Construct the name of the file to generate. - std::string fileName = this->FileDir; - fileName += "/"; - fileName += this->FileBase; - fileName += "-"; + std::string fileName = cmStrCat(this->FileDir, '/', this->FileBase, '-'); if (!config.empty()) { fileName += cmSystemTools::LowerCase(config); } else { @@ -392,8 +387,7 @@ void cmExportInstallFileGenerator::SetImportLocationProperty( if (itgen->IsImportLibrary()) { // Construct the property name. - std::string prop = "IMPORTED_IMPLIB"; - prop += suffix; + std::string prop = cmStrCat("IMPORTED_IMPLIB", suffix); // Append the installed file name. value += cmInstallTargetGenerator::GetInstallFilename( @@ -404,15 +398,14 @@ void cmExportInstallFileGenerator::SetImportLocationProperty( importedLocations.insert(prop); } else if (itgen->GetTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) { // Construct the property name. - std::string prop = "IMPORTED_OBJECTS"; - prop += suffix; + std::string prop = cmStrCat("IMPORTED_OBJECTS", suffix); // Compute all the object files inside this target and setup // IMPORTED_OBJECTS as a list of object files std::vector<std::string> objects; itgen->GetInstallObjectNames(config, objects); for (std::string& obj : objects) { - obj = value + obj; + obj = cmStrCat(value, obj); } // Store the property. @@ -420,8 +413,7 @@ void cmExportInstallFileGenerator::SetImportLocationProperty( importedLocations.insert(prop); } else { // Construct the property name. - std::string prop = "IMPORTED_LOCATION"; - prop += suffix; + std::string prop = cmStrCat("IMPORTED_LOCATION", suffix); // Append the installed file name. if (target->IsAppBundleOnApple()) { @@ -458,10 +450,10 @@ void cmExportInstallFileGenerator::HandleMissingTarget( { const std::string name = dependee->GetName(); cmGlobalGenerator* gg = dependee->GetLocalGenerator()->GetGlobalGenerator(); - std::vector<std::string> namespaces = this->FindNamespaces(gg, name); - int targetOccurrences = static_cast<int>(namespaces.size()); - if (targetOccurrences == 1) { - std::string missingTarget = namespaces[0]; + auto exportInfo = this->FindNamespaces(gg, name); + std::vector<std::string> const& exportFiles = exportInfo.first; + if (exportFiles.size() == 1) { + std::string missingTarget = exportInfo.second; missingTarget += dependee->GetExportName(); link_libs += missingTarget; @@ -469,14 +461,16 @@ void cmExportInstallFileGenerator::HandleMissingTarget( } else { // All exported targets should be known here and should be unique. // This is probably user-error. - this->ComplainAboutMissingTarget(depender, dependee, targetOccurrences); + this->ComplainAboutMissingTarget(depender, dependee, exportFiles); } } -std::vector<std::string> cmExportInstallFileGenerator::FindNamespaces( - cmGlobalGenerator* gg, const std::string& name) +std::pair<std::vector<std::string>, std::string> +cmExportInstallFileGenerator::FindNamespaces(cmGlobalGenerator* gg, + const std::string& name) { - std::vector<std::string> namespaces; + std::vector<std::string> exportFiles; + std::string ns; const cmExportSetMap& exportSets = gg->GetExportSets(); for (auto const& expIt : exportSets) { @@ -496,27 +490,33 @@ std::vector<std::string> cmExportInstallFileGenerator::FindNamespaces( std::vector<cmInstallExportGenerator const*> const* installs = exportSet->GetInstallations(); for (cmInstallExportGenerator const* install : *installs) { - namespaces.push_back(install->GetNamespace()); + exportFiles.push_back(install->GetDestinationFile()); + ns = install->GetNamespace(); } } } - return namespaces; + return std::make_pair(exportFiles, ns); } void cmExportInstallFileGenerator::ComplainAboutMissingTarget( - cmGeneratorTarget* depender, cmGeneratorTarget* dependee, int occurrences) + cmGeneratorTarget* depender, cmGeneratorTarget* dependee, + std::vector<std::string> const& exportFiles) { std::ostringstream e; e << "install(EXPORT \"" << this->IEGen->GetExportSet()->GetName() << "\" ...) " << "includes target \"" << depender->GetName() << "\" which requires target \"" << dependee->GetName() << "\" "; - if (occurrences == 0) { - e << "that is not in the export set."; + if (exportFiles.empty()) { + e << "that is not in any export set."; } else { - e << "that is not in this export set, but " << occurrences - << " times in others."; + e << "that is not in this export set, but in multiple other export sets: " + << cmJoin(exportFiles, ", ") << ".\n"; + e << "An exported target cannot depend upon another target which is " + "exported multiple times. Consider consolidating the exports of the " + "\"" + << dependee->GetName() << "\" target to a single export."; } cmSystemTools::Error(e.str()); } diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index cbd6507..fcd1aca 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -12,6 +12,7 @@ #include <map> #include <set> #include <string> +#include <utility> #include <vector> class cmGeneratorTarget; @@ -70,10 +71,10 @@ protected: void ComplainAboutMissingTarget(cmGeneratorTarget* depender, cmGeneratorTarget* dependee, - int occurrences); + std::vector<std::string> const& exportFiles); - std::vector<std::string> FindNamespaces(cmGlobalGenerator* gg, - const std::string& name); + std::pair<std::vector<std::string>, std::string> FindNamespaces( + cmGlobalGenerator* gg, const std::string& name); /** Generate the relative import prefix. */ virtual void GenerateImportPrefix(std::ostream&); diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx index b60a053..81237db 100644 --- a/Source/cmExportLibraryDependenciesCommand.cxx +++ b/Source/cmExportLibraryDependenciesCommand.cxx @@ -4,14 +4,15 @@ #include "cmsys/FStream.hxx" #include <map> -#include <memory> // IWYU pragma: keep #include <utility> -#include "cmAlgorithms.h" +#include "cm_memory.hxx" + #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetLinkLibraryType.h" @@ -19,57 +20,31 @@ class cmExecutionStatus; -bool cmExportLibraryDependenciesCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) -{ - if (args.empty()) { - this->SetError("called with incorrect number of arguments"); - return false; - } - - // store the arguments for the final pass - this->Filename = args[0]; - this->Append = false; - if (args.size() > 1) { - if (args[1] == "APPEND") { - this->Append = true; - } - } - return true; -} - -void cmExportLibraryDependenciesCommand::FinalPass() -{ - // export_library_dependencies() shouldn't modify anything - // ensure this by calling a const method - this->ConstFinalPass(); -} - -void cmExportLibraryDependenciesCommand::ConstFinalPass() const +static void FinalAction(cmMakefile& makefile, std::string const& filename, + bool append) { // Use copy-if-different if not appending. std::unique_ptr<cmsys::ofstream> foutPtr; - if (this->Append) { + if (append) { const auto openmodeApp = std::ios::app; - foutPtr = - cm::make_unique<cmsys::ofstream>(this->Filename.c_str(), openmodeApp); + foutPtr = cm::make_unique<cmsys::ofstream>(filename.c_str(), openmodeApp); } else { std::unique_ptr<cmGeneratedFileStream> ap( - new cmGeneratedFileStream(this->Filename, true)); + new cmGeneratedFileStream(filename, true)); ap->SetCopyIfDifferent(true); foutPtr = std::move(ap); } std::ostream& fout = *foutPtr; if (!fout) { - cmSystemTools::Error("Error Writing " + this->Filename); + cmSystemTools::Error("Error Writing " + filename); cmSystemTools::ReportLastSystemError(""); return; } // Collect dependency information about all library targets built in // the project. - cmake* cm = this->Makefile->GetCMakeInstance(); + cmake* cm = makefile.GetCMakeInstance(); cmGlobalGenerator* global = cm->GetGlobalGenerator(); const std::vector<cmMakefile*>& locals = global->GetMakefiles(); std::map<std::string, std::string> libDepsOld; @@ -87,8 +62,7 @@ void cmExportLibraryDependenciesCommand::ConstFinalPass() const } // Construct the dependency variable name. - std::string targetEntry = target.GetName(); - targetEntry += "_LIB_DEPENDS"; + std::string targetEntry = cmStrCat(target.GetName(), "_LIB_DEPENDS"); // Construct the dependency variable value with the direct link // dependencies. @@ -97,8 +71,7 @@ void cmExportLibraryDependenciesCommand::ConstFinalPass() const cmTarget::LinkLibraryVectorType const& libs = target.GetOriginalLinkLibraries(); for (cmTarget::LibraryID const& li : libs) { - std::string ltVar = li.first; - ltVar += "_LINK_TYPE"; + std::string ltVar = cmStrCat(li.first, "_LINK_TYPE"); std::string ltValue; switch (li.second) { case GENERAL_LibraryType: @@ -166,3 +139,20 @@ void cmExportLibraryDependenciesCommand::ConstFinalPass() const } fout << "endif()\n"; } + +bool cmExportLibraryDependenciesCommand::InitialPass( + std::vector<std::string> const& args, cmExecutionStatus&) +{ + if (args.empty()) { + this->SetError("called with incorrect number of arguments"); + return false; + } + + std::string const& filename = args[0]; + bool const append = args.size() > 1 && args[1] == "APPEND"; + this->Makefile->AddFinalAction([filename, append](cmMakefile& makefile) { + FinalAction(makefile, filename, append); + }); + + return true; +} diff --git a/Source/cmExportLibraryDependenciesCommand.h b/Source/cmExportLibraryDependenciesCommand.h index 8414866..4817162 100644 --- a/Source/cmExportLibraryDependenciesCommand.h +++ b/Source/cmExportLibraryDependenciesCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -15,20 +17,12 @@ class cmExecutionStatus; class cmExportLibraryDependenciesCommand : public cmCommand { public: - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - return new cmExportLibraryDependenciesCommand; + return cm::make_unique<cmExportLibraryDependenciesCommand>(); } bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; - - void FinalPass() override; - bool HasFinalPass() const override { return true; } - -private: - std::string Filename; - bool Append = false; - void ConstFinalPass() const; }; #endif diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index c169032..5631d60 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -9,11 +9,11 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmStateTypes.h" -#include "cmSystemTools.h" +#include "cmStringAlgorithms.h" #include "cmTarget.h" #include <map> -#include <memory> // IWYU pragma: keep +#include <memory> #include <utility> cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator( @@ -103,8 +103,7 @@ void cmExportTryCompileFileGenerator::PopulateProperties( std::string evalResult = this->FindTargets(p, target, std::string(), emitted); - std::vector<std::string> depends; - cmSystemTools::ExpandListArgument(evalResult, depends); + std::vector<std::string> depends = cmExpandedList(evalResult); for (std::string const& li : depends) { cmGeneratorTarget* tgt = target->GetLocalGenerator()->FindGeneratorTargetToUse(li); diff --git a/Source/cmExprParserHelper.cxx b/Source/cmExprParserHelper.cxx index 80c78a3..c01e959 100644 --- a/Source/cmExprParserHelper.cxx +++ b/Source/cmExprParserHelper.cxx @@ -3,6 +3,7 @@ #include "cmExprParserHelper.h" #include "cmExprLexer.h" +#include "cmStringAlgorithms.h" #include <iostream> #include <sstream> @@ -41,16 +42,13 @@ int cmExprParserHelper::ParseString(const char* str, int verb) try { int res = cmExpr_yyparse(yyscanner); if (res != 0) { - std::string e = "cannot parse the expression: \"" + InputBuffer + "\": "; - e += ErrorString; - e += "."; + std::string e = cmStrCat("cannot parse the expression: \"", InputBuffer, + "\": ", ErrorString, '.'); this->SetError(std::move(e)); } } catch (std::runtime_error const& fail) { - std::string e = - "cannot evaluate the expression: \"" + InputBuffer + "\": "; - e += fail.what(); - e += "."; + std::string e = cmStrCat("cannot evaluate the expression: \"", InputBuffer, + "\": ", fail.what(), '.'); this->SetError(std::move(e)); } catch (std::out_of_range const&) { std::string e = "cannot evaluate the expression: \"" + InputBuffer + diff --git a/Source/cmExternalMakefileProjectGenerator.cxx b/Source/cmExternalMakefileProjectGenerator.cxx index ac54811..83a0ba6 100644 --- a/Source/cmExternalMakefileProjectGenerator.cxx +++ b/Source/cmExternalMakefileProjectGenerator.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExternalMakefileProjectGenerator.h" +#include "cmStringAlgorithms.h" + #include <utility> class cmMakefile; @@ -18,8 +20,7 @@ std::string cmExternalMakefileProjectGenerator::CreateFullGeneratorName( std::string fullName; if (!globalGenerator.empty()) { if (!extraGenerator.empty()) { - fullName = extraGenerator; - fullName += " - "; + fullName = cmStrCat(extraGenerator, " - "); } fullName += globalGenerator; } diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index f47744b..d8a1a49 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -16,6 +16,7 @@ #include "cmRange.h" #include "cmSourceFile.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" #include "cmake.h" @@ -73,10 +74,9 @@ void cmExtraCodeBlocksGenerator::CreateProjectFile( std::string outputDir = lgs[0]->GetCurrentBinaryDirectory(); std::string projectName = lgs[0]->GetProjectName(); - std::string filename = outputDir + "/"; - filename += projectName + ".cbp"; - std::string sessionFilename = outputDir + "/"; - sessionFilename += projectName + ".layout"; + std::string filename = cmStrCat(outputDir, '/', projectName, ".cbp"); + std::string sessionFilename = + cmStrCat(outputDir, '/', projectName, ".layout"); this->CreateNewProjectFile(lgs, filename); } @@ -178,18 +178,18 @@ void Tree::BuildUnitImpl(cmXMLWriter& xml, { for (std::string const& f : files) { xml.StartElement("Unit"); - xml.Attribute("filename", fsPath + path + "/" + f); + xml.Attribute("filename", cmStrCat(fsPath, path, "/", f)); xml.StartElement("Option"); xml.Attribute("virtualFolder", - "CMake Files\\" + virtualFolderPath + path + "\\"); + cmStrCat("CMake Files\\", virtualFolderPath, path, "\\")); xml.EndElement(); xml.EndElement(); } for (Tree const& folder : folders) { - folder.BuildUnitImpl(xml, virtualFolderPath + path + "\\", - fsPath + path + "/"); + folder.BuildUnitImpl(xml, cmStrCat(virtualFolderPath, path, "\\"), + cmStrCat(fsPath, path, "/")); } } @@ -234,7 +234,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( // Also we can disable external (outside the project) files by setting ON // CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES variable. const bool excludeExternal = - cmSystemTools::IsOn(it.second[0]->GetMakefile()->GetSafeDefinition( + cmIsOn(it.second[0]->GetMakefile()->GetSafeDefinition( "CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES")); if (!splitted.empty() && (!excludeExternal || (relative.find("..") == std::string::npos)) && @@ -318,8 +318,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( cmGeneratorTarget* gt = target; this->AppendTarget(xml, targetName, gt, make, lg, compiler, makeArgs); - std::string fastTarget = targetName; - fastTarget += "/fast"; + std::string fastTarget = cmStrCat(targetName, "/fast"); this->AppendTarget(xml, fastTarget, gt, make, lg, compiler, makeArgs); } break; @@ -380,7 +379,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( // Do not add this file if it has ".." in relative path and // if CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES variable is on. const bool excludeExternal = - cmSystemTools::IsOn(lg->GetMakefile()->GetSafeDefinition( + cmIsOn(lg->GetMakefile()->GetSafeDefinition( "CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES")); if (excludeExternal && (relative.find("..") != std::string::npos)) { @@ -412,15 +411,13 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( // A very similar version of that code exists also in the CodeLite // project generator. for (std::string const& fileName : cFiles) { - std::string headerBasename = cmSystemTools::GetFilenamePath(fileName); - headerBasename += "/"; - headerBasename += cmSystemTools::GetFilenameWithoutExtension(fileName); + std::string headerBasename = + cmStrCat(cmSystemTools::GetFilenamePath(fileName), '/', + cmSystemTools::GetFilenameWithoutExtension(fileName)); // check if there's a matching header around for (std::string const& ext : headerExts) { - std::string hname = headerBasename; - hname += "."; - hname += ext; + std::string hname = cmStrCat(headerBasename, '.', ext); // if it's already in the set, don't check if it exists on disk if (allFiles.find(hname) != allFiles.end()) { break; @@ -465,12 +462,9 @@ std::string cmExtraCodeBlocksGenerator::CreateDummyTargetFile( // this file doesn't seem to be used by C::B in custom makefile mode, // but we generate a unique file for each OBJECT library so in case // C::B uses it in some way, the targets don't interfere with each other. - std::string filename = lg->GetCurrentBinaryDirectory(); - filename += "/"; - filename += lg->GetTargetDirectory(target); - filename += "/"; - filename += target->GetName(); - filename += ".objlib"; + std::string filename = cmStrCat(lg->GetCurrentBinaryDirectory(), '/', + lg->GetTargetDirectory(target), '/', + target->GetName(), ".objlib"); cmGeneratedFileStream fout(filename); if (fout) { /* clang-format off */ @@ -490,8 +484,8 @@ void cmExtraCodeBlocksGenerator::AppendTarget( const std::string& compiler, const std::string& makeFlags) { cmMakefile const* makefile = lg->GetMakefile(); - std::string makefileName = lg->GetCurrentBinaryDirectory(); - makefileName += "/Makefile"; + std::string makefileName = + cmStrCat(lg->GetCurrentBinaryDirectory(), "/Makefile"); xml.StartElement("Target"); xml.Attribute("title", targetName); @@ -570,15 +564,13 @@ void cmExtraCodeBlocksGenerator::AppendTarget( std::string systemIncludeDirs = makefile->GetSafeDefinition( "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS"); if (!systemIncludeDirs.empty()) { - cmAppend(allIncludeDirs, - cmSystemTools::ExpandedListArgument(systemIncludeDirs)); + cmAppend(allIncludeDirs, cmExpandedList(systemIncludeDirs)); } systemIncludeDirs = makefile->GetSafeDefinition( "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS"); if (!systemIncludeDirs.empty()) { - cmAppend(allIncludeDirs, - cmSystemTools::ExpandedListArgument(systemIncludeDirs)); + cmAppend(allIncludeDirs, cmExpandedList(systemIncludeDirs)); } std::vector<std::string>::const_iterator end = diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx index 6fe8c14..7f71a2c 100644 --- a/Source/cmExtraCodeLiteGenerator.cxx +++ b/Source/cmExtraCodeLiteGenerator.cxx @@ -9,6 +9,7 @@ #include "cmMakefile.h" #include "cmSourceFile.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" #include "cmake.h" @@ -67,8 +68,8 @@ void cmExtraCodeLiteGenerator::Generate() workspaceOutputDir = lg->GetCurrentBinaryDirectory(); workspaceProjectName = lg->GetProjectName(); workspaceSourcePath = lg->GetSourceDirectory(); - workspaceFileName = workspaceOutputDir + "/"; - workspaceFileName += workspaceProjectName + ".workspace"; + workspaceFileName = + cmStrCat(workspaceOutputDir, '/', workspaceProjectName, ".workspace"); this->WorkspacePath = lg->GetCurrentBinaryDirectory(); break; } @@ -121,7 +122,7 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget( cmStateEnums::TargetType type = lt->GetType(); std::string const& outputDir = lg->GetCurrentBinaryDirectory(); std::string targetName = lt->GetName(); - std::string filename = outputDir + "/" + targetName + ".project"; + std::string filename = cmStrCat(outputDir, "/", targetName, ".project"); retval.push_back(targetName); // Make the project file relative to the workspace std::string relafilename = @@ -131,7 +132,7 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget( case cmStateEnums::SHARED_LIBRARY: case cmStateEnums::STATIC_LIBRARY: case cmStateEnums::MODULE_LIBRARY: - visualname = "lib" + visualname; + visualname = cmStrCat("lib", visualname); CM_FALLTHROUGH; case cmStateEnums::EXECUTABLE: xml->StartElement("Project"); @@ -161,7 +162,7 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByProjectMaps( std::string const& outputDir = it.second[0]->GetCurrentBinaryDirectory(); std::string projectName = it.second[0]->GetProjectName(); retval.push_back(projectName); - std::string filename = outputDir + "/" + projectName + ".project"; + std::string filename = cmStrCat(outputDir, "/", projectName, ".project"); // Make the project file relative to the workspace filename = cmSystemTools::RelativePath(this->WorkspacePath, filename); @@ -217,22 +218,21 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles( case cmStateEnums::STATIC_LIBRARY: case cmStateEnums::SHARED_LIBRARY: case cmStateEnums::MODULE_LIBRARY: { + cmake const* cm = makefile->GetCMakeInstance(); std::vector<cmSourceFile*> sources; gt->GetSourceFiles(sources, makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); for (cmSourceFile* s : sources) { + std::string const& fullPath = s->GetFullPath(); + std::string const& extLower = + cmSystemTools::LowerCase(s->GetExtension()); // check whether it is a source or a include file // then put it accordingly into one of the two containers - switch (cmSystemTools::GetFileFormat(s->GetExtension())) { - case cmSystemTools::C_FILE_FORMAT: - case cmSystemTools::CXX_FILE_FORMAT: - case cmSystemTools::CUDA_FILE_FORMAT: - case cmSystemTools::FORTRAN_FILE_FORMAT: { - cFiles[s->GetFullPath()] = s; - } break; - default: { - otherFiles.insert(s->GetFullPath()); - } + if (cm->IsSourceExtension(extLower) || cm->IsCudaExtension(extLower) || + cm->IsFortranExtension(extLower)) { + cFiles[fullPath] = s; + } else { + otherFiles.insert(fullPath); } } } @@ -299,15 +299,13 @@ void cmExtraCodeLiteGenerator::FindMatchingHeaderfiles( // A very similar version of that code exists also in the CodeBlocks // project generator. for (auto const& sit : cFiles) { - std::string headerBasename = cmSystemTools::GetFilenamePath(sit.first); - headerBasename += "/"; - headerBasename += cmSystemTools::GetFilenameWithoutExtension(sit.first); + std::string headerBasename = + cmStrCat(cmSystemTools::GetFilenamePath(sit.first), '/', + cmSystemTools::GetFilenameWithoutExtension(sit.first)); // check if there's a matching header around for (std::string const& ext : headerExts) { - std::string hname = headerBasename; - hname += "."; - hname += ext; + std::string hname = cmStrCat(headerBasename, '.', ext); // if it's already in the set, don't check if it exists on disk std::set<std::string>::const_iterator headerIt = otherFiles.find(hname); if (headerIt != otherFiles.end()) { diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index aece3bc..6c94aae 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -21,6 +21,7 @@ #include "cmSourceGroup.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" #include "cmake.h" @@ -44,6 +45,8 @@ void AppendDictionary(cmXMLWriter& xml, const char* key, T const& value) cmExtraEclipseCDT4Generator::cmExtraEclipseCDT4Generator() { + this->IsOutOfSourceBuild = false; + this->GenerateSourceProject = false; this->SupportsVirtualFolders = true; this->GenerateLinkedResources = true; this->SupportsGmakeErrorParser = true; @@ -164,6 +167,29 @@ void cmExtraEclipseCDT4Generator::Generate() // create a .cproject file this->CreateCProjectFile(); + + // create resource settings + this->CreateSettingsResourcePrefsFile(); +} + +void cmExtraEclipseCDT4Generator::CreateSettingsResourcePrefsFile() +{ + cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0]; + cmMakefile* mf = lg->GetMakefile(); + + const std::string filename = + this->HomeOutputDirectory + "/.settings/org.eclipse.core.resources.prefs"; + + cmGeneratedFileStream fout(filename); + if (!fout) { + return; + } + + fout << "eclipse.preferences.version=1" << std::endl; + const char* encoding = mf->GetDefinition("CMAKE_ECLIPSE_RESOURCE_ENCODING"); + if (encoding) { + fout << "encoding/<project>=" << encoding << std::endl; + } } void cmExtraEclipseCDT4Generator::CreateSourceProjectFile() @@ -214,8 +240,7 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, std::string envVarValue; const bool envVarSet = cmSystemTools::GetEnv(envVar, envVarValue); - std::string cacheEntryName = "CMAKE_ECLIPSE_ENVVAR_"; - cacheEntryName += envVar; + std::string cacheEntryName = cmStrCat("CMAKE_ECLIPSE_ENVVAR_", envVar); const std::string* cacheValue = lg->GetState()->GetInitializedCacheValue(cacheEntryName); @@ -390,8 +415,7 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile() if (const char* extraNaturesProp = mf->GetState()->GetGlobalProperty("ECLIPSE_EXTRA_NATURES")) { - std::vector<std::string> extraNatures; - cmSystemTools::ExpandListArgument(extraNaturesProp, extraNatures); + std::vector<std::string> extraNatures = cmExpandedList(extraNaturesProp); for (std::string const& n : extraNatures) { xml.Element("nature", n); } @@ -438,9 +462,7 @@ void cmExtraEclipseCDT4Generator::WriteGroups( cmXMLWriter& xml) { for (cmSourceGroup const& sg : sourceGroups) { - std::string linkName3 = linkName; - linkName3 += "/"; - linkName3 += sg.GetFullName(); + std::string linkName3 = cmStrCat(linkName, '/', sg.GetFullName()); std::replace(linkName3.begin(), linkName3.end(), '\\', '/'); @@ -455,9 +477,8 @@ void cmExtraEclipseCDT4Generator::WriteGroups( std::string const& fullPath = file->GetFullPath(); if (!cmSystemTools::FileIsDirectory(fullPath)) { - std::string linkName4 = linkName3; - linkName4 += "/"; - linkName4 += cmSystemTools::GetFilenameName(fullPath); + std::string linkName4 = + cmStrCat(linkName3, '/', cmSystemTools::GetFilenameName(fullPath)); cmExtraEclipseCDT4Generator::AppendLinkedResource( xml, linkName4, cmExtraEclipseCDT4Generator::GetEclipsePath(fullPath), LinkToFile); @@ -477,8 +498,7 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets(cmXMLWriter& xml) const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); for (cmGeneratorTarget* target : targets) { - std::string linkName2 = linkName; - linkName2 += "/"; + std::string linkName2 = cmStrCat(linkName, '/'); switch (target->GetType()) { case cmStateEnums::EXECUTABLE: case cmStateEnums::STATIC_LIBRARY: @@ -540,8 +560,7 @@ void cmExtraEclipseCDT4Generator::CreateLinksToSubprojects( // .project itself if ((baseDir != linkSourceDirectory) && !cmSystemTools::IsSubDirectory(baseDir, linkSourceDirectory)) { - std::string linkName = "[Subprojects]/"; - linkName += it.first; + std::string linkName = cmStrCat("[Subprojects]/", it.first); cmExtraEclipseCDT4Generator::AppendLinkedResource( xml, linkName, cmExtraEclipseCDT4Generator::GetEclipsePath(linkSourceDirectory), @@ -777,8 +796,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const mf->GetDefinition("CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS"); if (this->CEnabled && cDefs) { // Expand the list. - std::vector<std::string> defs; - cmSystemTools::ExpandListArgument(cDefs, defs, true); + std::vector<std::string> defs = cmExpandedList(cDefs, true); // the list must contain only definition-value pairs: if ((defs.size() % 2) == 0) { @@ -810,8 +828,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const mf->GetDefinition("CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS"); if (this->CXXEnabled && cxxDefs) { // Expand the list. - std::vector<std::string> defs; - cmSystemTools::ExpandListArgument(cxxDefs, defs, true); + std::vector<std::string> defs = cmExpandedList(cxxDefs, true); // the list must contain only definition-value pairs: if ((defs.size() % 2) == 0) { @@ -861,16 +878,14 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const if (this->CEnabled && !compiler.empty()) { std::string systemIncludeDirs = mf->GetSafeDefinition("CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS"); - std::vector<std::string> dirs; - cmSystemTools::ExpandListArgument(systemIncludeDirs, dirs); + std::vector<std::string> dirs = cmExpandedList(systemIncludeDirs); this->AppendIncludeDirectories(xml, dirs, emmited); } compiler = mf->GetSafeDefinition("CMAKE_CXX_COMPILER"); if (this->CXXEnabled && !compiler.empty()) { std::string systemIncludeDirs = mf->GetSafeDefinition("CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS"); - std::vector<std::string> dirs; - cmSystemTools::ExpandListArgument(systemIncludeDirs, dirs); + std::vector<std::string> dirs = cmExpandedList(systemIncludeDirs); this->AppendIncludeDirectories(xml, dirs, emmited); } @@ -944,28 +959,21 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const : "[lib] "); cmExtraEclipseCDT4Generator::AppendTarget(xml, targetName, make, makeArgs, subdir, prefix); - std::string fastTarget = targetName; - fastTarget += "/fast"; + std::string fastTarget = cmStrCat(targetName, "/fast"); cmExtraEclipseCDT4Generator::AppendTarget(xml, fastTarget, make, makeArgs, subdir, prefix); // Add Build and Clean targets in the virtual folder of targets: if (this->SupportsVirtualFolders) { - std::string virtDir = "[Targets]/"; - virtDir += prefix; - virtDir += targetName; - std::string buildArgs = "-C \""; - buildArgs += lgen->GetBinaryDirectory(); - buildArgs += "\" "; - buildArgs += makeArgs; + std::string virtDir = cmStrCat("[Targets]/", prefix, targetName); + std::string buildArgs = + cmStrCat("-C \"", lgen->GetBinaryDirectory(), "\" ", makeArgs); cmExtraEclipseCDT4Generator::AppendTarget( xml, "Build", make, buildArgs, virtDir, "", targetName.c_str()); - std::string cleanArgs = "-E chdir \""; - cleanArgs += lgen->GetCurrentBinaryDirectory(); - cleanArgs += "\" \""; - cleanArgs += cmSystemTools::GetCMakeCommand(); - cleanArgs += "\" -P \""; + std::string cleanArgs = + cmStrCat("-E chdir \"", lgen->GetCurrentBinaryDirectory(), + "\" \"", cmSystemTools::GetCMakeCommand(), "\" -P \""); cmGeneratorTarget* gt = target; cleanArgs += lgen->GetTargetDirectory(gt); cleanArgs += "/cmake_clean.cmake\""; diff --git a/Source/cmExtraEclipseCDT4Generator.h b/Source/cmExtraEclipseCDT4Generator.h index 5136660..ef038d9 100644 --- a/Source/cmExtraEclipseCDT4Generator.h +++ b/Source/cmExtraEclipseCDT4Generator.h @@ -43,6 +43,9 @@ private: // create .project file in the source tree void CreateSourceProjectFile(); + // create .settings/org.eclipse.core.resources.prefs + void CreateSettingsResourcePrefsFile(); + // create .project file void CreateProjectFile(); diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx index 877f109..2bfbb0d 100644 --- a/Source/cmExtraKateGenerator.cxx +++ b/Source/cmExtraKateGenerator.cxx @@ -9,6 +9,7 @@ #include "cmMakefile.h" #include "cmSourceFile.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include <ostream> @@ -53,8 +54,7 @@ void cmExtraKateGenerator::Generate() void cmExtraKateGenerator::CreateKateProjectFile( const cmLocalGenerator* lg) const { - std::string filename = lg->GetBinaryDirectory(); - filename += "/.kateproject"; + std::string filename = cmStrCat(lg->GetBinaryDirectory(), "/.kateproject"); cmGeneratedFileStream fout(filename); if (!fout) { return; @@ -164,8 +164,7 @@ void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator* lg, case cmStateEnums::OBJECT_LIBRARY: { this->AppendTarget(fout, targetName, make, makeArgs, currentDir, homeOutputDir); - std::string fastTarget = targetName; - fastTarget += "/fast"; + std::string fastTarget = cmStrCat(targetName, "/fast"); this->AppendTarget(fout, fastTarget, make, makeArgs, currentDir, homeOutputDir); @@ -208,10 +207,8 @@ void cmExtraKateGenerator::AppendTarget(cmGeneratedFileStream& fout, void cmExtraKateGenerator::CreateDummyKateProjectFile( const cmLocalGenerator* lg) const { - std::string filename = lg->GetBinaryDirectory(); - filename += "/"; - filename += this->ProjectName; - filename += ".kateproject"; + std::string filename = + cmStrCat(lg->GetBinaryDirectory(), '/', this->ProjectName, ".kateproject"); cmGeneratedFileStream fout(filename); if (!fout) { return; @@ -224,20 +221,17 @@ void cmExtraKateGenerator::CreateDummyKateProjectFile( std::string cmExtraKateGenerator::GenerateFilesString( const cmLocalGenerator* lg) const { - std::string s = lg->GetSourceDirectory(); - s += "/.git"; + std::string s = cmStrCat(lg->GetSourceDirectory(), "/.git"); if (cmSystemTools::FileExists(s)) { return "\"git\": 1 "; } - s = lg->GetSourceDirectory(); - s += "/.svn"; + s = cmStrCat(lg->GetSourceDirectory(), "/.svn"); if (cmSystemTools::FileExists(s)) { return "\"svn\": 1 "; } - s = lg->GetSourceDirectory(); - s += "/"; + s = cmStrCat(lg->GetSourceDirectory(), '/'); std::set<std::string> files; std::string tmp; diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index 71c8fcd..33f5157 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -17,6 +17,7 @@ #include "cmMessageType.h" #include "cmSourceFile.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" @@ -133,8 +134,7 @@ void cmExtraSublimeTextGenerator::CreateNewProjectFile( // End of build_systems fout << "\n\t]"; std::string systemName = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME"); - std::vector<std::string> tokens; - cmSystemTools::ExpandListArgument(this->EnvSettings, tokens); + std::vector<std::string> tokens = cmExpandedList(this->EnvSettings); if (!this->EnvSettings.empty()) { fout << ","; @@ -218,8 +218,7 @@ void cmExtraSublimeTextGenerator::AppendAllTargets( this->AppendTarget(fout, targetName, lg, target, make.c_str(), makefile, compiler.c_str(), sourceFileFlags, false); - std::string fastTarget = targetName; - fastTarget += "/fast"; + std::string fastTarget = cmStrCat(targetName, "/fast"); this->AppendTarget(fout, fastTarget, lg, target, make.c_str(), makefile, compiler.c_str(), sourceFileFlags, false); @@ -266,7 +265,7 @@ void cmExtraSublimeTextGenerator::AppendTarget( R"((^|[ ])-[DIOUWfgs][^= ]+(=\"[^"]+\"|=[^"][^ ]+)?)"; flagRegex.compile(regexString); std::string workString = - flagsString + " " + definesString + " " + includesString; + cmStrCat(flagsString, " ", definesString, " ", includesString); while (flagRegex.find(workString)) { std::string::size_type start = flagRegex.start(); if (workString[start] == ' ') { @@ -310,8 +309,7 @@ void cmExtraSublimeTextGenerator::AppendTarget( std::string cmExtraSublimeTextGenerator::BuildMakeCommand( const std::string& make, const char* makefile, const std::string& target) { - std::string command = "\""; - command += make + "\""; + std::string command = cmStrCat('"', make, '"'); std::string generator = this->GlobalGenerator->GetName(); if (generator == "NMake Makefiles") { std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile); @@ -392,8 +390,8 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines( defines, genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS)); } - std::string defPropName = "COMPILE_DEFINITIONS_"; - defPropName += cmSystemTools::UpperCase(config); + std::string defPropName = + cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config)); if (const char* config_compile_defs = source->GetProperty(defPropName)) { lg->AppendDefines( defines, @@ -444,7 +442,7 @@ bool cmExtraSublimeTextGenerator::Open(const std::string& bindir, if (!sublExecutable) { return false; } - if (cmSystemTools::IsNOTFOUND(sublExecutable)) { + if (cmIsNOTFOUND(sublExecutable)) { return false; } diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx index 89629c7..2150051 100644 --- a/Source/cmFLTKWrapUICommand.cxx +++ b/Source/cmFLTKWrapUICommand.cxx @@ -8,11 +8,28 @@ #include "cmMakefile.h" #include "cmRange.h" #include "cmSourceFile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmExecutionStatus; class cmTarget; +static void FinalAction(cmMakefile& makefile, std::string const& name) +{ + // people should add the srcs to the target themselves, but the old command + // didn't support that, so check and see if they added the files in and if + // they didn;t then print a warning and add then anyhow + cmTarget* target = makefile.FindLocalNonAliasTarget(name); + if (!target) { + std::string msg = cmStrCat( + "FLTK_WRAP_UI was called with a target that was never created: ", name, + ". The problem was found while processing the source directory: ", + makefile.GetCurrentSourceDirectory(), + ". This FLTK_WRAP_UI call will be ignored."); + cmSystemTools::Message(msg, "Warning"); + } +} + // cmFLTKWrapUICommand bool cmFLTKWrapUICommand::InitialPass(std::vector<std::string> const& args, cmExecutionStatus&) @@ -27,8 +44,8 @@ bool cmFLTKWrapUICommand::InitialPass(std::vector<std::string> const& args, std::string const& fluid_exe = this->Makefile->GetRequiredDefinition("FLTK_FLUID_EXECUTABLE"); - // get parameter for the command - this->Target = args[0]; // Target that will use the generated files + // Target that will use the generated files + std::string const& target = args[0]; // get the list of GUI files from which .cxx and .h will be generated std::string outputDirectory = this->Makefile->GetCurrentBinaryDirectory(); @@ -41,23 +58,23 @@ bool cmFLTKWrapUICommand::InitialPass(std::vector<std::string> const& args, this->Makefile->AddIncludeDirectories(outputDirectories); } + // List of produced files. + std::vector<cmSourceFile*> generatedSourcesClasses; + for (std::string const& arg : cmMakeRange(args).advance(1)) { cmSourceFile* curr = this->Makefile->GetSource(arg); // if we should use the source GUI // to generate .cxx and .h files if (!curr || !curr->GetPropertyAsBool("WRAP_EXCLUDE")) { - std::string outName = outputDirectory; - outName += "/"; - outName += cmSystemTools::GetFilenameWithoutExtension(arg); - std::string hname = outName; - hname += ".h"; - std::string origname = cdir + "/" + arg; + std::string outName = cmStrCat( + outputDirectory, "/", cmSystemTools::GetFilenameWithoutExtension(arg)); + std::string hname = cmStrCat(outName, ".h"); + std::string origname = cmStrCat(cdir, "/", arg); // add starting depends std::vector<std::string> depends; depends.push_back(origname); depends.push_back(fluid_exe); - std::string cxxres = outName; - cxxres += ".cxx"; + std::string cxxres = cmStrCat(outName, ".cxx"); cmCustomCommandLine commandLine; commandLine.push_back(fluid_exe); @@ -84,40 +101,24 @@ bool cmFLTKWrapUICommand::InitialPass(std::vector<std::string> const& args, cmSourceFile* sf = this->Makefile->GetSource(cxxres); sf->AddDepend(hname); sf->AddDepend(origname); - this->GeneratedSourcesClasses.push_back(sf); + generatedSourcesClasses.push_back(sf); } } // create the variable with the list of sources in it - size_t lastHeadersClass = this->GeneratedSourcesClasses.size(); + size_t lastHeadersClass = generatedSourcesClasses.size(); std::string sourceListValue; for (size_t classNum = 0; classNum < lastHeadersClass; classNum++) { if (classNum) { sourceListValue += ";"; } - sourceListValue += this->GeneratedSourcesClasses[classNum]->GetFullPath(); + sourceListValue += generatedSourcesClasses[classNum]->GetFullPath(); } - std::string varName = this->Target; - varName += "_FLTK_UI_SRCS"; - this->Makefile->AddDefinition(varName, sourceListValue.c_str()); - return true; -} + std::string const varName = target + "_FLTK_UI_SRCS"; + this->Makefile->AddDefinition(varName, sourceListValue); -void cmFLTKWrapUICommand::FinalPass() -{ - // people should add the srcs to the target themselves, but the old command - // didn't support that, so check and see if they added the files in and if - // they didn;t then print a warning and add then anyhow - cmTarget* target = this->Makefile->FindLocalNonAliasTarget(this->Target); - if (!target) { - std::string msg = - "FLTK_WRAP_UI was called with a target that was never created: "; - msg += this->Target; - msg += ". The problem was found while processing the source directory: "; - msg += this->Makefile->GetCurrentSourceDirectory(); - msg += ". This FLTK_WRAP_UI call will be ignored."; - cmSystemTools::Message(msg, "Warning"); - return; - } + this->Makefile->AddFinalAction( + [target](cmMakefile& makefile) { FinalAction(makefile, target); }); + return true; } diff --git a/Source/cmFLTKWrapUICommand.h b/Source/cmFLTKWrapUICommand.h index 044755e..ea8d401 100644 --- a/Source/cmFLTKWrapUICommand.h +++ b/Source/cmFLTKWrapUICommand.h @@ -8,10 +8,11 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; -class cmSourceFile; /** \class cmFLTKWrapUICommand * \brief Create .h and .cxx files rules for FLTK user interfaces files @@ -25,7 +26,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmFLTKWrapUICommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmFLTKWrapUICommand>(); + } /** * This is called when the command is first encountered in @@ -33,27 +37,6 @@ public: */ bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; - - /** - * This is called at the end after all the information - * specified by the command is accumulated. Most commands do - * not implement this method. At this point, reading and - * writing to the cache can be done. - */ - void FinalPass() override; - bool HasFinalPass() const override { return true; } - -private: - /** - * List of produced files. - */ - std::vector<cmSourceFile*> GeneratedSourcesClasses; - - /** - * List of Fluid files that provide the source - * generating .cxx and .h files - */ - std::string Target; }; #endif diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx index ba42669..5d9181a 100644 --- a/Source/cmFileAPI.cxx +++ b/Source/cmFileAPI.cxx @@ -2,12 +2,12 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmFileAPI.h" -#include "cmAlgorithms.h" #include "cmCryptoHash.h" #include "cmFileAPICMakeFiles.h" #include "cmFileAPICache.h" #include "cmFileAPICodemodel.h" #include "cmGlobalGenerator.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTimestamp.h" #include "cmake.h" @@ -94,7 +94,7 @@ void cmFileAPI::RemoveOldReplyFiles() std::vector<std::string> files = this->LoadDir(reply_dir); for (std::string const& f : files) { if (this->ReplyFiles.find(f) == this->ReplyFiles.end()) { - std::string file = reply_dir + "/" + f; + std::string file = cmStrCat(reply_dir, "/", f); cmSystemTools::RemoveFile(file); } } @@ -407,9 +407,7 @@ const char* cmFileAPI::ObjectKindName(ObjectKind kind) std::string cmFileAPI::ObjectName(Object const& o) { - std::string name = ObjectKindName(o.Kind); - name += "-v"; - name += std::to_string(o.Version); + std::string name = cmStrCat(ObjectKindName(o.Kind), "-v", o.Version); return name; } @@ -684,7 +682,6 @@ void cmFileAPI::BuildClientRequestCodeModel( Json::Value cmFileAPI::BuildCodeModel(Object const& object) { - using namespace std::placeholders; Json::Value codemodel = cmFileAPICodemodelDump(*this, object.Version); codemodel["kind"] = this->ObjectKindName(object.Kind); @@ -719,7 +716,6 @@ void cmFileAPI::BuildClientRequestCache( Json::Value cmFileAPI::BuildCache(Object const& object) { - using namespace std::placeholders; Json::Value cache = cmFileAPICacheDump(*this, object.Version); cache["kind"] = this->ObjectKindName(object.Kind); @@ -754,7 +750,6 @@ void cmFileAPI::BuildClientRequestCMakeFiles( Json::Value cmFileAPI::BuildCMakeFiles(Object const& object) { - using namespace std::placeholders; Json::Value cmakeFiles = cmFileAPICMakeFilesDump(*this, object.Version); cmakeFiles["kind"] = this->ObjectKindName(object.Kind); diff --git a/Source/cmFileAPI.h b/Source/cmFileAPI.h index 602efa8..aa5a42f 100644 --- a/Source/cmFileAPI.h +++ b/Source/cmFileAPI.h @@ -10,7 +10,7 @@ #include "cm_jsoncpp_writer.h" #include <map> -#include <memory> // IWYU pragma: keep +#include <memory> #include <string> #include <unordered_set> #include <vector> diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 6025025..e4b7670 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -21,6 +21,7 @@ #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetDepend.h" @@ -30,7 +31,11 @@ #include <algorithm> #include <cassert> +#include <cstddef> +#include <functional> +#include <limits> #include <map> +#include <memory> #include <set> #include <string> #include <unordered_map> @@ -134,6 +139,40 @@ std::string TargetId(cmGeneratorTarget const* gt, std::string const& topBuild) return gt->GetName() + CMAKE_DIRECTORY_ID_SEP + hash; } +class JBTIndex +{ +public: + JBTIndex() = default; + explicit operator bool() const { return Index != None; } + Json::ArrayIndex Index = None; + static Json::ArrayIndex const None = static_cast<Json::ArrayIndex>(-1); +}; + +template <typename T> +class JBT +{ +public: + JBT(T v = T(), JBTIndex bt = JBTIndex()) + : Value(std::move(v)) + , Backtrace(bt) + { + } + T Value; + JBTIndex Backtrace; + friend bool operator==(JBT<T> const& l, JBT<T> const& r) + { + return l.Value == r.Value && l.Backtrace.Index == r.Backtrace.Index; + } + static bool ValueEq(JBT<T> const& l, JBT<T> const& r) + { + return l.Value == r.Value; + } + static bool ValueLess(JBT<T> const& l, JBT<T> const& r) + { + return l.Value < r.Value; + } +}; + class BacktraceData { std::string TopSource; @@ -168,7 +207,7 @@ class BacktraceData public: BacktraceData(std::string topSource); - bool Add(cmListFileBacktrace const& bt, Json::ArrayIndex& index); + JBTIndex Add(cmListFileBacktrace const& bt); Json::Value Dump(); }; @@ -177,16 +216,17 @@ BacktraceData::BacktraceData(std::string topSource) { } -bool BacktraceData::Add(cmListFileBacktrace const& bt, Json::ArrayIndex& index) +JBTIndex BacktraceData::Add(cmListFileBacktrace const& bt) { + JBTIndex index; if (bt.Empty()) { - return false; + return index; } cmListFileContext const* top = &bt.Top(); auto found = this->NodeMap.find(top); if (found != this->NodeMap.end()) { - index = found->second; - return true; + index.Index = found->second; + return index; } Json::Value entry = Json::objectValue; entry["file"] = this->AddFile(top->FilePath); @@ -196,13 +236,12 @@ bool BacktraceData::Add(cmListFileBacktrace const& bt, Json::ArrayIndex& index) if (!top->Name.empty()) { entry["command"] = this->AddCommand(top->Name); } - Json::ArrayIndex parent; - if (this->Add(bt.Pop(), parent)) { - entry["parent"] = parent; + if (JBTIndex parent = this->Add(bt.Pop())) { + entry["parent"] = parent.Index; } - index = this->NodeMap[top] = this->Nodes.size(); + index.Index = this->NodeMap[top] = this->Nodes.size(); this->Nodes.append(std::move(entry)); // NOLINT(*) - return true; + return index; } Json::Value BacktraceData::Dump() @@ -221,32 +260,65 @@ struct CompileData { struct IncludeEntry { - BT<std::string> Path; + JBT<std::string> Path; bool IsSystem = false; - IncludeEntry(BT<std::string> path, bool isSystem) + IncludeEntry(JBT<std::string> path, bool isSystem) : Path(std::move(path)) , IsSystem(isSystem) { } + friend bool operator==(IncludeEntry const& l, IncludeEntry const& r) + { + return l.Path == r.Path && l.IsSystem == r.IsSystem; + } }; - void SetDefines(std::set<BT<std::string>> const& defines); - std::string Language; std::string Sysroot; - std::vector<BT<std::string>> Flags; - std::vector<BT<std::string>> Defines; + std::vector<JBT<std::string>> Flags; + std::vector<JBT<std::string>> Defines; std::vector<IncludeEntry> Includes; + + friend bool operator==(CompileData const& l, CompileData const& r) + { + return (l.Language == r.Language && l.Sysroot == r.Sysroot && + l.Flags == r.Flags && l.Defines == r.Defines && + l.Includes == r.Includes); + } }; +} + +namespace std { -void CompileData::SetDefines(std::set<BT<std::string>> const& defines) +template <> +struct hash<CompileData> { - this->Defines.reserve(defines.size()); - for (BT<std::string> const& d : defines) { - this->Defines.push_back(d); + std::size_t operator()(CompileData const& in) const + { + using std::hash; + size_t result = + hash<std::string>()(in.Language) ^ hash<std::string>()(in.Sysroot); + for (auto const& i : in.Includes) { + result = result ^ + (hash<std::string>()(i.Path.Value) ^ + hash<Json::ArrayIndex>()(i.Path.Backtrace.Index) ^ + (i.IsSystem ? std::numeric_limits<size_t>::max() : 0)); + } + for (auto const& i : in.Flags) { + result = result ^ hash<std::string>()(i.Value) ^ + hash<Json::ArrayIndex>()(i.Backtrace.Index); + } + for (auto const& i : in.Defines) { + result = result ^ hash<std::string>()(i.Value) ^ + hash<Json::ArrayIndex>()(i.Backtrace.Index); + } + return result; } -} +}; +} // namespace std + +namespace { class Target { cmGeneratorTarget* GT; @@ -271,24 +343,32 @@ class Target struct CompileGroup { - std::map<Json::Value, Json::ArrayIndex>::iterator Entry; + std::unordered_map<CompileData, Json::ArrayIndex>::iterator Entry; Json::Value SourceIndexes = Json::arrayValue; }; - std::map<Json::Value, Json::ArrayIndex> CompileGroupMap; + std::unordered_map<CompileData, Json::ArrayIndex> CompileGroupMap; std::vector<CompileGroup> CompileGroups; + template <typename T> + JBT<T> ToJBT(BT<T> const& bt) + { + return JBT<T>(bt.Value, this->Backtraces.Add(bt.Backtrace)); + } + void ProcessLanguages(); void ProcessLanguage(std::string const& lang); Json::ArrayIndex AddSourceGroup(cmSourceGroup* sg, Json::ArrayIndex si); CompileData BuildCompileData(cmSourceFile* sf); + CompileData MergeCompileData(CompileData const& fd); Json::ArrayIndex AddSourceCompileGroup(cmSourceFile* sf, Json::ArrayIndex si); void AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt); + void AddBacktrace(Json::Value& object, JBTIndex bt); Json::Value DumpPaths(); - Json::Value DumpCompileData(CompileData cd); + Json::Value DumpCompileData(CompileData const& cd); Json::Value DumpInclude(CompileData::IncludeEntry const& inc); - Json::Value DumpDefine(BT<std::string> const& def); + Json::Value DumpDefine(JBT<std::string> const& def); Json::Value DumpSources(); Json::Value DumpSource(cmGeneratorTarget::SourceAndKind const& sk, Json::ArrayIndex si); @@ -305,8 +385,8 @@ class Target Json::Value DumpLink(); Json::Value DumpArchive(); Json::Value DumpLinkCommandFragments(); - Json::Value DumpCommandFragments(std::vector<BT<std::string>> const& frags); - Json::Value DumpCommandFragment(BT<std::string> const& frag, + Json::Value DumpCommandFragments(std::vector<JBT<std::string>> const& frags); + Json::Value DumpCommandFragment(JBT<std::string> const& frag, std::string const& role = std::string()); Json::Value DumpDependencies(); Json::Value DumpDependency(cmTargetDepend const& td); @@ -721,16 +801,20 @@ void Target::ProcessLanguage(std::string const& lang) // which may need to be factored out. std::string flags; lg->GetTargetCompileFlags(this->GT, this->Config, lang, flags); - cd.Flags.emplace_back(std::move(flags), cmListFileBacktrace()); + cd.Flags.emplace_back(std::move(flags), JBTIndex()); } std::set<BT<std::string>> defines = lg->GetTargetDefines(this->GT, this->Config, lang); - cd.SetDefines(defines); + cd.Defines.reserve(defines.size()); + for (BT<std::string> const& d : defines) { + cd.Defines.emplace_back(this->ToJBT(d)); + } std::vector<BT<std::string>> includePathList = lg->GetIncludeDirectories(this->GT, lang, this->Config); for (BT<std::string> const& i : includePathList) { cd.Includes.emplace_back( - i, this->GT->IsSystemIncludeDirectory(i.Value, this->Config, lang)); + this->ToJBT(i), + this->GT->IsSystemIncludeDirectory(i.Value, this->Config, lang)); } } @@ -757,26 +841,22 @@ CompileData Target::BuildCompileData(cmSourceFile* sf) if (fd.Language.empty()) { return fd; } - CompileData const& cd = this->CompileDataMap.at(fd.Language); - - fd.Sysroot = cd.Sysroot; cmLocalGenerator* lg = this->GT->GetLocalGenerator(); cmGeneratorExpressionInterpreter genexInterpreter(lg, this->Config, this->GT, fd.Language); - fd.Flags = cd.Flags; const std::string COMPILE_FLAGS("COMPILE_FLAGS"); if (const char* cflags = sf->GetProperty(COMPILE_FLAGS)) { std::string flags = genexInterpreter.Evaluate(cflags, COMPILE_FLAGS); - fd.Flags.emplace_back(std::move(flags), cmListFileBacktrace()); + fd.Flags.emplace_back(std::move(flags), JBTIndex()); } const std::string COMPILE_OPTIONS("COMPILE_OPTIONS"); if (const char* coptions = sf->GetProperty(COMPILE_OPTIONS)) { std::string flags; lg->AppendCompileOptions( flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS)); - fd.Flags.emplace_back(std::move(flags), cmListFileBacktrace()); + fd.Flags.emplace_back(std::move(flags), JBTIndex()); } // Add include directories from source file properties. @@ -795,8 +875,6 @@ CompileData Target::BuildCompileData(cmSourceFile* sf) } } } - fd.Includes.insert(fd.Includes.end(), cd.Includes.begin(), - cd.Includes.end()); const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); std::set<std::string> fileDefines; @@ -813,27 +891,62 @@ CompileData Target::BuildCompileData(cmSourceFile* sf) genexInterpreter.Evaluate(config_defs, COMPILE_DEFINITIONS)); } - std::set<BT<std::string>> defines; - defines.insert(fileDefines.begin(), fileDefines.end()); - defines.insert(cd.Defines.begin(), cd.Defines.end()); - - fd.SetDefines(defines); + fd.Defines.reserve(fileDefines.size()); + for (std::string const& d : fileDefines) { + fd.Defines.emplace_back(d, JBTIndex()); + } return fd; } +CompileData Target::MergeCompileData(CompileData const& fd) +{ + CompileData cd; + cd.Language = fd.Language; + if (cd.Language.empty()) { + return cd; + } + CompileData const& td = this->CompileDataMap.at(cd.Language); + + // All compile groups share the sysroot of the target. + cd.Sysroot = td.Sysroot; + + // Use target-wide flags followed by source-specific flags. + cd.Flags.reserve(td.Flags.size() + fd.Flags.size()); + cd.Flags.insert(cd.Flags.end(), td.Flags.begin(), td.Flags.end()); + cd.Flags.insert(cd.Flags.end(), fd.Flags.begin(), fd.Flags.end()); + + // Use source-specific includes followed by target-wide includes. + cd.Includes.reserve(fd.Includes.size() + td.Includes.size()); + cd.Includes.insert(cd.Includes.end(), fd.Includes.begin(), + fd.Includes.end()); + cd.Includes.insert(cd.Includes.end(), td.Includes.begin(), + td.Includes.end()); + + // Use target-wide defines followed by source-specific defines. + cd.Defines.reserve(td.Defines.size() + fd.Defines.size()); + cd.Defines.insert(cd.Defines.end(), td.Defines.begin(), td.Defines.end()); + cd.Defines.insert(cd.Defines.end(), fd.Defines.begin(), fd.Defines.end()); + + // De-duplicate defines. + std::stable_sort(cd.Defines.begin(), cd.Defines.end(), + JBT<std::string>::ValueLess); + auto end = std::unique(cd.Defines.begin(), cd.Defines.end(), + JBT<std::string>::ValueEq); + cd.Defines.erase(end, cd.Defines.end()); + + return cd; +} + Json::ArrayIndex Target::AddSourceCompileGroup(cmSourceFile* sf, Json::ArrayIndex si) { - Json::Value compileDataJson = - this->DumpCompileData(this->BuildCompileData(sf)); - std::map<Json::Value, Json::ArrayIndex>::iterator i = - this->CompileGroupMap.find(compileDataJson); + CompileData compileData = this->BuildCompileData(sf); + auto i = this->CompileGroupMap.find(compileData); if (i == this->CompileGroupMap.end()) { Json::ArrayIndex cgIndex = static_cast<Json::ArrayIndex>(this->CompileGroups.size()); - i = - this->CompileGroupMap.emplace(std::move(compileDataJson), cgIndex).first; + i = this->CompileGroupMap.emplace(std::move(compileData), cgIndex).first; CompileGroup g; g.Entry = i; this->CompileGroups.push_back(std::move(g)); @@ -844,9 +957,15 @@ Json::ArrayIndex Target::AddSourceCompileGroup(cmSourceFile* sf, void Target::AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt) { - Json::ArrayIndex backtrace; - if (this->Backtraces.Add(bt, backtrace)) { - object["backtrace"] = backtrace; + if (JBTIndex backtrace = this->Backtraces.Add(bt)) { + object["backtrace"] = backtrace.Index; + } +} + +void Target::AddBacktrace(Json::Value& object, JBTIndex bt) +{ + if (bt) { + object["backtrace"] = bt.Index; } } @@ -914,7 +1033,7 @@ Json::Value Target::DumpSource(cmGeneratorTarget::SourceAndKind const& sk, return source; } -Json::Value Target::DumpCompileData(CompileData cd) +Json::Value Target::DumpCompileData(CompileData const& cd) { Json::Value result = Json::objectValue; @@ -936,7 +1055,7 @@ Json::Value Target::DumpCompileData(CompileData cd) } if (!cd.Defines.empty()) { Json::Value defines = Json::arrayValue; - for (BT<std::string> const& d : cd.Defines) { + for (JBT<std::string> const& d : cd.Defines) { defines.append(this->DumpDefine(d)); } result["defines"] = std::move(defines); @@ -956,7 +1075,7 @@ Json::Value Target::DumpInclude(CompileData::IncludeEntry const& inc) return include; } -Json::Value Target::DumpDefine(BT<std::string> const& def) +Json::Value Target::DumpDefine(JBT<std::string> const& def) { Json::Value define = Json::objectValue; define["define"] = def.Value; @@ -992,7 +1111,8 @@ Json::Value Target::DumpCompileGroups() Json::Value Target::DumpCompileGroup(CompileGroup& cg) { - Json::Value group = cg.Entry->first; + Json::Value group = + this->DumpCompileData(this->MergeCompileData(cg.Entry->first)); group["sourceIndexes"] = std::move(cg.SourceIndexes); return group; } @@ -1072,17 +1192,16 @@ Json::Value Target::DumpArtifacts() } // Add Windows-specific artifacts produced by the linker. + if (this->GT->HasImportLibrary(this->Config)) { + Json::Value artifact = Json::objectValue; + artifact["path"] = + RelativeIfUnder(this->TopBuild, + this->GT->GetFullPath( + this->Config, cmStateEnums::ImportLibraryArtifact)); + artifacts.append(std::move(artifact)); // NOLINT(*) + } if (this->GT->IsDLLPlatform() && this->GT->GetType() != cmStateEnums::STATIC_LIBRARY) { - if (this->GT->GetType() == cmStateEnums::SHARED_LIBRARY || - this->GT->IsExecutableWithExports()) { - Json::Value artifact = Json::objectValue; - artifact["path"] = - RelativeIfUnder(this->TopBuild, - this->GT->GetFullPath( - this->Config, cmStateEnums::ImportLibraryArtifact)); - artifacts.append(std::move(artifact)); // NOLINT(*) - } cmGeneratorTarget::OutputInfo const* output = this->GT->GetOutputInfo(this->Config); if (output && !output->PdbDir.empty()) { @@ -1152,11 +1271,11 @@ Json::Value Target::DumpLinkCommandFragments() lg->GetTargetFlags(&linkLineComputer, this->Config, linkLibs, linkLanguageFlags, linkFlags, frameworkPath, linkPath, this->GT); - linkLanguageFlags = cmSystemTools::TrimWhitespace(linkLanguageFlags); - linkFlags = cmSystemTools::TrimWhitespace(linkFlags); - frameworkPath = cmSystemTools::TrimWhitespace(frameworkPath); - linkPath = cmSystemTools::TrimWhitespace(linkPath); - linkLibs = cmSystemTools::TrimWhitespace(linkLibs); + linkLanguageFlags = cmTrimWhitespace(linkLanguageFlags); + linkFlags = cmTrimWhitespace(linkFlags); + frameworkPath = cmTrimWhitespace(frameworkPath); + linkPath = cmTrimWhitespace(linkPath); + linkLibs = cmTrimWhitespace(linkLibs); if (!linkLanguageFlags.empty()) { linkFragments.append( @@ -1187,16 +1306,16 @@ Json::Value Target::DumpLinkCommandFragments() } Json::Value Target::DumpCommandFragments( - std::vector<BT<std::string>> const& frags) + std::vector<JBT<std::string>> const& frags) { Json::Value commandFragments = Json::arrayValue; - for (BT<std::string> const& f : frags) { + for (JBT<std::string> const& f : frags) { commandFragments.append(this->DumpCommandFragment(f)); } return commandFragments; } -Json::Value Target::DumpCommandFragment(BT<std::string> const& frag, +Json::Value Target::DumpCommandFragment(JBT<std::string> const& frag, std::string const& role) { Json::Value fragment = Json::objectValue; diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 7a3954e..5589537 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -12,16 +12,20 @@ #include <assert.h> #include <cmath> #include <ctype.h> -#include <memory> // IWYU pragma: keep +#include <map> +#include <set> #include <sstream> #include <stdio.h> #include <stdlib.h> #include <utility> #include <vector> +#include "cm_memory.hxx" + #include "cmAlgorithms.h" #include "cmArgumentParser.h" #include "cmCryptoHash.h" +#include "cmExecutionStatus.h" #include "cmFileCopier.h" #include "cmFileInstaller.h" #include "cmFileLockPool.h" @@ -34,12 +38,16 @@ #include "cmMessageType.h" #include "cmPolicies.h" #include "cmRange.h" +#include "cmRuntimeDependencyArchive.h" +#include "cmState.h" +#include "cmStringAlgorithms.h" +#include "cmSubcommandTable.h" #include "cmSystemTools.h" #include "cmTimestamp.h" #include "cm_sys_stat.h" #include "cmake.h" -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) # include "cmCurl.h" # include "cmFileLockResult.h" # include "cm_curl.h" @@ -53,10 +61,12 @@ # include <windows.h> #endif +namespace { + #if defined(_WIN32) // libcurl doesn't support file:// urls for unicode filenames on Windows. // Convert string from UTF-8 to ACP if this is a file:// URL. -static std::string fix_file_url_windows(const std::string& url) +std::string fix_file_url_windows(const std::string& url) { std::string ret = url; if (strncmp(url.c_str(), "file://", 7) == 0) { @@ -78,120 +88,8 @@ static std::string fix_file_url_windows(const std::string& url) } #endif -// cmLibraryCommand -bool cmFileCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) -{ - if (args.size() < 2) { - this->SetError("must be called with at least two arguments."); - return false; - } - std::string const& subCommand = args[0]; - if (subCommand == "WRITE") { - return this->HandleWriteCommand(args, false); - } - if (subCommand == "APPEND") { - return this->HandleWriteCommand(args, true); - } - if (subCommand == "DOWNLOAD") { - return this->HandleDownloadCommand(args); - } - if (subCommand == "UPLOAD") { - return this->HandleUploadCommand(args); - } - if (subCommand == "READ") { - return this->HandleReadCommand(args); - } - if (subCommand == "MD5" || subCommand == "SHA1" || subCommand == "SHA224" || - subCommand == "SHA256" || subCommand == "SHA384" || - subCommand == "SHA512" || subCommand == "SHA3_224" || - subCommand == "SHA3_256" || subCommand == "SHA3_384" || - subCommand == "SHA3_512") { - return this->HandleHashCommand(args); - } - if (subCommand == "STRINGS") { - return this->HandleStringsCommand(args); - } - if (subCommand == "GLOB") { - return this->HandleGlobCommand(args, false); - } - if (subCommand == "GLOB_RECURSE") { - return this->HandleGlobCommand(args, true); - } - if (subCommand == "MAKE_DIRECTORY") { - return this->HandleMakeDirectoryCommand(args); - } - if (subCommand == "RENAME") { - return this->HandleRename(args); - } - if (subCommand == "REMOVE") { - return this->HandleRemove(args, false); - } - if (subCommand == "REMOVE_RECURSE") { - return this->HandleRemove(args, true); - } - if (subCommand == "COPY") { - return this->HandleCopyCommand(args); - } - if (subCommand == "INSTALL") { - return this->HandleInstallCommand(args); - } - if (subCommand == "DIFFERENT") { - return this->HandleDifferentCommand(args); - } - if (subCommand == "RPATH_CHANGE" || subCommand == "CHRPATH") { - return this->HandleRPathChangeCommand(args); - } - if (subCommand == "RPATH_CHECK") { - return this->HandleRPathCheckCommand(args); - } - if (subCommand == "RPATH_REMOVE") { - return this->HandleRPathRemoveCommand(args); - } - if (subCommand == "READ_ELF") { - return this->HandleReadElfCommand(args); - } - if (subCommand == "RELATIVE_PATH") { - return this->HandleRelativePathCommand(args); - } - if (subCommand == "TO_CMAKE_PATH") { - return this->HandleCMakePathCommand(args, false); - } - if (subCommand == "TO_NATIVE_PATH") { - return this->HandleCMakePathCommand(args, true); - } - if (subCommand == "TOUCH") { - return this->HandleTouchCommand(args, true); - } - if (subCommand == "TOUCH_NOCREATE") { - return this->HandleTouchCommand(args, false); - } - if (subCommand == "TIMESTAMP") { - return this->HandleTimestampCommand(args); - } - if (subCommand == "GENERATE") { - return this->HandleGenerateCommand(args); - } - if (subCommand == "LOCK") { - return this->HandleLockCommand(args); - } - if (subCommand == "SIZE") { - return this->HandleSizeCommand(args); - } - if (subCommand == "READ_SYMLINK") { - return this->HandleReadSymlinkCommand(args); - } - if (subCommand == "CREATE_LINK") { - return this->HandleCreateLinkCommand(args); - } - - std::string e = "does not recognize sub-command " + subCommand; - this->SetError(e); - return false; -} - -bool cmFileCommand::HandleWriteCommand(std::vector<std::string> const& args, - bool append) +bool HandleWriteImpl(std::vector<std::string> const& args, bool append, + cmExecutionStatus& status) { std::vector<std::string>::const_iterator i = args.begin(); @@ -199,16 +97,16 @@ bool cmFileCommand::HandleWriteCommand(std::vector<std::string> const& args, std::string fileName = *i; if (!cmsys::SystemTools::FileIsFullPath(*i)) { - fileName = this->Makefile->GetCurrentSourceDirectory(); - fileName += "/" + *i; + fileName = + cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', *i); } i++; - if (!this->Makefile->CanIWriteThisFile(fileName)) { + if (!status.GetMakefile().CanIWriteThisFile(fileName)) { std::string e = "attempted to write a file: " + fileName + " into a source directory."; - this->SetError(e); + status.SetError(e); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -236,21 +134,19 @@ bool cmFileCommand::HandleWriteCommand(std::vector<std::string> const& args, cmsys::ofstream file(fileName.c_str(), append ? std::ios::app : std::ios::out); if (!file) { - std::string error = "failed to open for writing ("; - error += cmSystemTools::GetLastSystemError(); - error += "):\n "; - error += fileName; - this->SetError(error); + std::string error = + cmStrCat("failed to open for writing (", + cmSystemTools::GetLastSystemError(), "):\n ", fileName); + status.SetError(error); return false; } std::string message = cmJoin(cmMakeRange(i, args.end()), std::string()); file << message; if (!file) { - std::string error = "write failed ("; - error += cmSystemTools::GetLastSystemError(); - error += "):\n "; - error += fileName; - this->SetError(error); + std::string error = + cmStrCat("write failed (", cmSystemTools::GetLastSystemError(), "):\n ", + fileName); + status.SetError(error); return false; } file.close(); @@ -260,11 +156,24 @@ bool cmFileCommand::HandleWriteCommand(std::vector<std::string> const& args, return true; } -bool cmFileCommand::HandleReadCommand(std::vector<std::string> const& args) +bool HandleWriteCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleWriteImpl(args, false, status); +} + +bool HandleAppendCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleWriteImpl(args, true, status); +} + +bool HandleReadCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 3) { - this->SetError("READ must be called with at least two additional " - "arguments"); + status.SetError("READ must be called with at least two additional " + "arguments"); return false; } @@ -287,8 +196,8 @@ bool cmFileCommand::HandleReadCommand(std::vector<std::string> const& args) std::string fileName = fileNameArg; if (!cmsys::SystemTools::FileIsFullPath(fileName)) { - fileName = this->Makefile->GetCurrentSourceDirectory(); - fileName += "/" + fileNameArg; + fileName = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', + fileNameArg); } // Open the specified file. @@ -301,11 +210,10 @@ bool cmFileCommand::HandleReadCommand(std::vector<std::string> const& args) #endif if (!file) { - std::string error = "failed to open for reading ("; - error += cmSystemTools::GetLastSystemError(); - error += "):\n "; - error += fileName; - this->SetError(error); + std::string error = + cmStrCat("failed to open for reading (", + cmSystemTools::GetLastSystemError(), "):\n ", fileName); + status.SetError(error); return false; } @@ -357,53 +265,55 @@ bool cmFileCommand::HandleReadCommand(std::vector<std::string> const& args) } } } - this->Makefile->AddDefinition(variable, output.c_str()); + status.GetMakefile().AddDefinition(variable, output); return true; } -bool cmFileCommand::HandleHashCommand(std::vector<std::string> const& args) +bool HandleHashCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) if (args.size() != 3) { std::ostringstream e; e << args[0] << " requires a file name and output variable"; - this->SetError(e.str()); + status.SetError(e.str()); return false; } - std::unique_ptr<cmCryptoHash> hash(cmCryptoHash::New(args[0].c_str())); + std::unique_ptr<cmCryptoHash> hash(cmCryptoHash::New(args[0])); if (hash) { std::string out = hash->HashFile(args[1]); if (!out.empty()) { - this->Makefile->AddDefinition(args[2], out.c_str()); + status.GetMakefile().AddDefinition(args[2], out); return true; } std::ostringstream e; e << args[0] << " failed to read file \"" << args[1] << "\": " << cmSystemTools::GetLastSystemError(); - this->SetError(e.str()); + status.SetError(e.str()); } return false; #else std::ostringstream e; e << args[0] << " not available during bootstrap"; - this->SetError(e.str()); + status.SetError(e.str()); return false; #endif } -bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) +bool HandleStringsCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 3) { - this->SetError("STRINGS requires a file name and output variable"); + status.SetError("STRINGS requires a file name and output variable"); return false; } // Get the file to read. std::string fileName = args[1]; if (!cmsys::SystemTools::FileIsFullPath(fileName)) { - fileName = this->Makefile->GetCurrentSourceDirectory(); - fileName += "/" + args[1]; + fileName = + cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[1]); } // Get the variable in which to store the results. @@ -469,7 +379,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) std::ostringstream e; e << "STRINGS option LIMIT_INPUT value \"" << args[i] << "\" is not an unsigned integer."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } arg_mode = arg_none; @@ -479,7 +389,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) std::ostringstream e; e << "STRINGS option LIMIT_OUTPUT value \"" << args[i] << "\" is not an unsigned integer."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } arg_mode = arg_none; @@ -489,7 +399,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) std::ostringstream e; e << "STRINGS option LIMIT_COUNT value \"" << args[i] << "\" is not an unsigned integer."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } limit_count = count; @@ -500,7 +410,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) std::ostringstream e; e << "STRINGS option LENGTH_MINIMUM value \"" << args[i] << "\" is not an unsigned integer."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } minlen = len; @@ -511,7 +421,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) std::ostringstream e; e << "STRINGS option LENGTH_MAXIMUM value \"" << args[i] << "\" is not an unsigned integer."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } maxlen = len; @@ -521,7 +431,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) std::ostringstream e; e << "STRINGS option REGEX value \"" << args[i] << "\" could not be compiled."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } have_regex = true; @@ -540,23 +450,23 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) } else { std::ostringstream e; e << "STRINGS option ENCODING \"" << args[i] << "\" not recognized."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } arg_mode = arg_none; } else { std::ostringstream e; e << "STRINGS given unknown argument \"" << args[i] << "\""; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } if (hex_conversion_enabled) { // TODO: should work without temp file, but just on a memory buffer - std::string binaryFileName = this->Makefile->GetCurrentBinaryDirectory(); - binaryFileName += "/CMakeFiles"; - binaryFileName += "/FileCommandStringsBinaryFile"; + std::string binaryFileName = + cmStrCat(status.GetMakefile().GetCurrentBinaryDirectory(), + "/CMakeFiles/FileCommandStringsBinaryFile"); if (cmHexFileConverter::TryConvert(fileName, binaryFileName)) { fileName = binaryFileName; } @@ -571,7 +481,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) if (!fin) { std::ostringstream e; e << "STRINGS file \"" << fileName << "\" cannot be read."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } @@ -743,12 +653,12 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args) } // Save the output in a makefile variable. - this->Makefile->AddDefinition(outVar, output.c_str()); + status.GetMakefile().AddDefinition(outVar, output); return true; } -bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, - bool recurse) +bool HandleGlobImpl(std::vector<std::string> const& args, bool recurse, + cmExecutionStatus& status) { // File commands has at least one argument assert(args.size() > 1); @@ -763,10 +673,10 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, g.SetRecurse(recurse); bool explicitFollowSymlinks = false; - cmPolicies::PolicyStatus status = - this->Makefile->GetPolicyStatus(cmPolicies::CMP0009); + cmPolicies::PolicyStatus policyStatus = + status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0009); if (recurse) { - switch (status) { + switch (policyStatus) { case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: @@ -784,24 +694,24 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, bool warnConfigureLate = false; bool warnFollowedSymlinks = false; const cmake::WorkingMode workingMode = - this->Makefile->GetCMakeInstance()->GetWorkingMode(); + status.GetMakefile().GetCMakeInstance()->GetWorkingMode(); while (i != args.end()) { if (*i == "LIST_DIRECTORIES") { ++i; // skip LIST_DIRECTORIES if (i != args.end()) { - if (cmSystemTools::IsOn(*i)) { + if (cmIsOn(*i)) { g.SetListDirs(true); g.SetRecurseListDirs(true); - } else if (cmSystemTools::IsOff(*i)) { + } else if (cmIsOff(*i)) { g.SetListDirs(false); g.SetRecurseListDirs(false); } else { - this->SetError("LIST_DIRECTORIES missing bool value."); + status.SetError("LIST_DIRECTORIES missing bool value."); return false; } ++i; } else { - this->SetError("LIST_DIRECTORIES missing bool value."); + status.SetError("LIST_DIRECTORIES missing bool value."); return false; } } else if (*i == "FOLLOW_SYMLINKS") { @@ -810,7 +720,7 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, explicitFollowSymlinks = true; g.RecurseThroughSymlinksOn(); if (i == args.end()) { - this->SetError( + status.SetError( "GLOB_RECURSE requires a glob expression after FOLLOW_SYMLINKS."); return false; } @@ -818,25 +728,26 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, } else if (*i == "RELATIVE") { ++i; // skip RELATIVE if (i == args.end()) { - this->SetError("GLOB requires a directory after the RELATIVE tag."); + status.SetError("GLOB requires a directory after the RELATIVE tag."); return false; } g.SetRelative(i->c_str()); ++i; if (i == args.end()) { - this->SetError("GLOB requires a glob expression after the directory."); + status.SetError( + "GLOB requires a glob expression after the directory."); return false; } } else if (*i == "CONFIGURE_DEPENDS") { // Generated build system depends on glob results if (!configureDepends && warnConfigureLate) { - this->Makefile->IssueMessage( + status.GetMakefile().IssueMessage( MessageType::AUTHOR_WARNING, "CONFIGURE_DEPENDS flag was given after a glob expression was " "already evaluated."); } if (workingMode != cmake::NORMAL_MODE) { - this->Makefile->IssueMessage( + status.GetMakefile().IssueMessage( MessageType::FATAL_ERROR, "CONFIGURE_DEPENDS is invalid for script and find package modes."); return false; @@ -844,14 +755,14 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, configureDepends = true; ++i; if (i == args.end()) { - this->SetError( + status.SetError( "GLOB requires a glob expression after CONFIGURE_DEPENDS."); return false; } } else { std::string expr = *i; if (!cmsys::SystemTools::FileIsFullPath(*i)) { - expr = this->Makefile->GetCurrentSourceDirectory(); + expr = status.GetMakefile().GetCurrentSourceDirectory(); // Handle script mode if (!expr.empty()) { expr += "/" + *i; @@ -867,12 +778,12 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, bool shouldExit = false; for (cmsys::Glob::Message const& globMessage : globMessages) { if (globMessage.type == cmsys::Glob::cyclicRecursion) { - this->Makefile->IssueMessage( + status.GetMakefile().IssueMessage( MessageType::AUTHOR_WARNING, "Cyclic recursion detected while globbing for '" + *i + "':\n" + globMessage.content); } else { - this->Makefile->IssueMessage( + status.GetMakefile().IssueMessage( MessageType::FATAL_ERROR, "Error has occurred while globbing for '" + *i + "' - " + globMessage.content); @@ -896,11 +807,11 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, std::sort(foundFiles.begin(), foundFiles.end()); foundFiles.erase(std::unique(foundFiles.begin(), foundFiles.end()), foundFiles.end()); - this->Makefile->GetCMakeInstance()->AddGlobCacheEntry( + status.GetMakefile().GetCMakeInstance()->AddGlobCacheEntry( recurse, (recurse ? g.GetRecurseListDirs() : g.GetListDirs()), (recurse ? g.GetRecurseThroughSymlinks() : false), (g.GetRelative() ? g.GetRelative() : ""), expr, foundFiles, variable, - this->Makefile->GetBacktrace()); + status.GetMakefile().GetBacktrace()); } else { warnConfigureLate = true; } @@ -908,7 +819,7 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, } } - switch (status) { + switch (policyStatus) { case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: @@ -921,7 +832,7 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, // Possibly unexpected old behavior *and* we actually traversed // symlinks without being explicitly asked to: warn the author. if (warnFollowedSymlinks) { - this->Makefile->IssueMessage( + status.GetMakefile().IssueMessage( MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0009)); } @@ -930,12 +841,24 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, std::sort(files.begin(), files.end()); files.erase(std::unique(files.begin(), files.end()), files.end()); - this->Makefile->AddDefinition(variable, cmJoin(files, ";").c_str()); + status.GetMakefile().AddDefinition(variable, cmJoin(files, ";")); return true; } -bool cmFileCommand::HandleMakeDirectoryCommand( - std::vector<std::string> const& args) +bool HandleGlobCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleGlobImpl(args, false, status); +} + +bool HandleGlobRecurseCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleGlobImpl(args, true, status); +} + +bool HandleMakeDirectoryCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { // File command has at least one argument assert(args.size() > 1); @@ -946,28 +869,28 @@ bool cmFileCommand::HandleMakeDirectoryCommand( { const std::string* cdir = &arg; if (!cmsys::SystemTools::FileIsFullPath(arg)) { - expr = this->Makefile->GetCurrentSourceDirectory(); - expr += "/" + arg; + expr = + cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', arg); cdir = &expr; } - if (!this->Makefile->CanIWriteThisFile(*cdir)) { + if (!status.GetMakefile().CanIWriteThisFile(*cdir)) { std::string e = "attempted to create a directory: " + *cdir + " into a source directory."; - this->SetError(e); + status.SetError(e); cmSystemTools::SetFatalErrorOccured(); return false; } if (!cmSystemTools::MakeDirectory(*cdir)) { std::string error = "problem creating directory: " + *cdir; - this->SetError(error); + status.SetError(error); return false; } } return true; } -bool cmFileCommand::HandleTouchCommand(std::vector<std::string> const& args, - bool create) +bool HandleTouchImpl(std::vector<std::string> const& args, bool create, + cmExecutionStatus& status) { // File command has at least one argument assert(args.size() > 1); @@ -977,27 +900,39 @@ bool cmFileCommand::HandleTouchCommand(std::vector<std::string> const& args, { std::string tfile = arg; if (!cmsys::SystemTools::FileIsFullPath(tfile)) { - tfile = this->Makefile->GetCurrentSourceDirectory(); - tfile += "/" + arg; + tfile = + cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', arg); } - if (!this->Makefile->CanIWriteThisFile(tfile)) { + if (!status.GetMakefile().CanIWriteThisFile(tfile)) { std::string e = "attempted to touch a file: " + tfile + " in a source directory."; - this->SetError(e); + status.SetError(e); cmSystemTools::SetFatalErrorOccured(); return false; } if (!cmSystemTools::Touch(tfile, create)) { std::string error = "problem touching file: " + tfile; - this->SetError(error); + status.SetError(error); return false; } } return true; } -bool cmFileCommand::HandleDifferentCommand( - std::vector<std::string> const& args) +bool HandleTouchCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleTouchImpl(args, true, status); +} + +bool HandleTouchNocreateCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleTouchImpl(args, false, status); +} + +bool HandleDifferentCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { /* FILE(DIFFERENT <variable> FILES <lhs> <rhs>) @@ -1030,39 +965,41 @@ bool cmFileCommand::HandleDifferentCommand( } else { std::ostringstream e; e << "DIFFERENT given unknown argument " << args[i]; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } if (!var) { - this->SetError("DIFFERENT not given result variable name."); + status.SetError("DIFFERENT not given result variable name."); return false; } if (!file_lhs || !file_rhs) { - this->SetError("DIFFERENT not given FILES option with two file names."); + status.SetError("DIFFERENT not given FILES option with two file names."); return false; } // Compare the files. const char* result = cmSystemTools::FilesDiffer(file_lhs, file_rhs) ? "1" : "0"; - this->Makefile->AddDefinition(var, result); + status.GetMakefile().AddDefinition(var, result); return true; } -bool cmFileCommand::HandleCopyCommand(std::vector<std::string> const& args) +bool HandleCopyCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { - cmFileCopier copier(this); + cmFileCopier copier(status); return copier.Run(args); } -bool cmFileCommand::HandleRPathChangeCommand( - std::vector<std::string> const& args) +bool HandleRPathChangeCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { // Evaluate arguments. std::string file; const char* oldRPath = nullptr; const char* newRPath = nullptr; + bool removeEnvironmentRPath = false; enum Doing { DoingNone, @@ -1078,6 +1015,8 @@ bool cmFileCommand::HandleRPathChangeCommand( doing = DoingNew; } else if (args[i] == "FILE") { doing = DoingFile; + } else if (args[i] == "INSTALL_REMOVE_ENVIRONMENT_RPATH") { + removeEnvironmentRPath = true; } else if (doing == DoingFile) { file = args[i]; doing = DoingNone; @@ -1090,33 +1029,35 @@ bool cmFileCommand::HandleRPathChangeCommand( } else { std::ostringstream e; e << "RPATH_CHANGE given unknown argument " << args[i]; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } if (file.empty()) { - this->SetError("RPATH_CHANGE not given FILE option."); + status.SetError("RPATH_CHANGE not given FILE option."); return false; } if (!oldRPath) { - this->SetError("RPATH_CHANGE not given OLD_RPATH option."); + status.SetError("RPATH_CHANGE not given OLD_RPATH option."); return false; } if (!newRPath) { - this->SetError("RPATH_CHANGE not given NEW_RPATH option."); + status.SetError("RPATH_CHANGE not given NEW_RPATH option."); return false; } if (!cmSystemTools::FileExists(file, true)) { std::ostringstream e; e << "RPATH_CHANGE given FILE \"" << file << "\" that does not exist."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } bool success = true; cmFileTimes const ft(file); std::string emsg; bool changed; - if (!cmSystemTools::ChangeRPath(file, oldRPath, newRPath, &emsg, &changed)) { + + if (!cmSystemTools::ChangeRPath(file, oldRPath, newRPath, + removeEnvironmentRPath, &emsg, &changed)) { std::ostringstream e; /* clang-format off */ e << "RPATH_CHANGE could not write new RPATH:\n" @@ -1125,25 +1066,22 @@ bool cmFileCommand::HandleRPathChangeCommand( << " " << file << "\n" << emsg; /* clang-format on */ - this->SetError(e.str()); + status.SetError(e.str()); success = false; } if (success) { if (changed) { - std::string message = "Set runtime path of \""; - message += file; - message += "\" to \""; - message += newRPath; - message += "\""; - this->Makefile->DisplayStatus(message, -1); + std::string message = + cmStrCat("Set runtime path of \"", file, "\" to \"", newRPath, '"'); + status.GetMakefile().DisplayStatus(message, -1); } ft.Store(file); } return success; } -bool cmFileCommand::HandleRPathRemoveCommand( - std::vector<std::string> const& args) +bool HandleRPathRemoveCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { // Evaluate arguments. std::string file; @@ -1162,18 +1100,18 @@ bool cmFileCommand::HandleRPathRemoveCommand( } else { std::ostringstream e; e << "RPATH_REMOVE given unknown argument " << args[i]; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } if (file.empty()) { - this->SetError("RPATH_REMOVE not given FILE option."); + status.SetError("RPATH_REMOVE not given FILE option."); return false; } if (!cmSystemTools::FileExists(file, true)) { std::ostringstream e; e << "RPATH_REMOVE given FILE \"" << file << "\" that does not exist."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } bool success = true; @@ -1187,23 +1125,22 @@ bool cmFileCommand::HandleRPathRemoveCommand( << " " << file << "\n" << emsg; /* clang-format on */ - this->SetError(e.str()); + status.SetError(e.str()); success = false; } if (success) { if (removed) { - std::string message = "Removed runtime path from \""; - message += file; - message += "\""; - this->Makefile->DisplayStatus(message, -1); + std::string message = + cmStrCat("Removed runtime path from \"", file, '"'); + status.GetMakefile().DisplayStatus(message, -1); } ft.Store(file); } return success; } -bool cmFileCommand::HandleRPathCheckCommand( - std::vector<std::string> const& args) +bool HandleRPathCheckCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { // Evaluate arguments. std::string file; @@ -1229,16 +1166,16 @@ bool cmFileCommand::HandleRPathCheckCommand( } else { std::ostringstream e; e << "RPATH_CHECK given unknown argument " << args[i]; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } if (file.empty()) { - this->SetError("RPATH_CHECK not given FILE option."); + status.SetError("RPATH_CHECK not given FILE option."); return false; } if (!rpath) { - this->SetError("RPATH_CHECK not given RPATH option."); + status.SetError("RPATH_CHECK not given RPATH option."); return false; } @@ -1253,11 +1190,12 @@ bool cmFileCommand::HandleRPathCheckCommand( return true; } -bool cmFileCommand::HandleReadElfCommand(std::vector<std::string> const& args) +bool HandleReadElfCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 4) { - this->SetError("READ_ELF must be called with at least three additional " - "arguments."); + status.SetError("READ_ELF must be called with at least three additional " + "arguments."); return false; } @@ -1279,7 +1217,7 @@ bool cmFileCommand::HandleReadElfCommand(std::vector<std::string> const& args) if (!cmSystemTools::FileExists(fileNameArg, true)) { std::ostringstream e; e << "READ_ELF given FILE \"" << fileNameArg << "\" that does not exist."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } @@ -1290,14 +1228,14 @@ bool cmFileCommand::HandleReadElfCommand(std::vector<std::string> const& args) if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) { std::string rpath(se_rpath->Value); std::replace(rpath.begin(), rpath.end(), ':', ';'); - this->Makefile->AddDefinition(arguments.RPath, rpath.c_str()); + status.GetMakefile().AddDefinition(arguments.RPath, rpath); } } if (!arguments.RunPath.empty()) { if (cmELF::StringEntry const* se_runpath = elf.GetRunPath()) { std::string runpath(se_runpath->Value); std::replace(runpath.begin(), runpath.end(), ':', ';'); - this->Makefile->AddDefinition(arguments.RunPath, runpath.c_str()); + status.GetMakefile().AddDefinition(arguments.RunPath, runpath); } } @@ -1305,25 +1243,26 @@ bool cmFileCommand::HandleReadElfCommand(std::vector<std::string> const& args) #else std::string error = "ELF parser not available on this platform."; if (arguments.Error.empty()) { - this->SetError(error); + status.SetError(error); return false; } - this->Makefile->AddDefinition(arguments.Error, error.c_str()); + status.GetMakefile().AddDefinition(arguments.Error, error); return true; #endif } -bool cmFileCommand::HandleInstallCommand(std::vector<std::string> const& args) +bool HandleInstallCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { - cmFileInstaller installer(this); + cmFileInstaller installer(status); return installer.Run(args); } -bool cmFileCommand::HandleRelativePathCommand( - std::vector<std::string> const& args) +bool HandleRelativePathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 4) { - this->SetError("RELATIVE_PATH called with incorrect number of arguments"); + status.SetError("RELATIVE_PATH called with incorrect number of arguments"); return false; } @@ -1335,38 +1274,39 @@ bool cmFileCommand::HandleRelativePathCommand( std::string errstring = "RELATIVE_PATH must be passed a full path to the directory: " + directoryName; - this->SetError(errstring); + status.SetError(errstring); return false; } if (!cmSystemTools::FileIsFullPath(fileName)) { std::string errstring = "RELATIVE_PATH must be passed a full path to the file: " + fileName; - this->SetError(errstring); + status.SetError(errstring); return false; } std::string res = cmSystemTools::RelativePath(directoryName, fileName); - this->Makefile->AddDefinition(outVar, res.c_str()); + status.GetMakefile().AddDefinition(outVar, res); return true; } -bool cmFileCommand::HandleRename(std::vector<std::string> const& args) +bool HandleRename(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 3) { - this->SetError("RENAME given incorrect number of arguments."); + status.SetError("RENAME given incorrect number of arguments."); return false; } // Compute full path for old and new names. std::string oldname = args[1]; if (!cmsys::SystemTools::FileIsFullPath(oldname)) { - oldname = this->Makefile->GetCurrentSourceDirectory(); - oldname += "/" + args[1]; + oldname = + cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[1]); } std::string newname = args[2]; if (!cmsys::SystemTools::FileIsFullPath(newname)) { - newname = this->Makefile->GetCurrentSourceDirectory(); - newname += "/" + args[2]; + newname = + cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[2]); } if (!cmSystemTools::RenameFile(oldname, newname)) { @@ -1379,14 +1319,14 @@ bool cmFileCommand::HandleRename(std::vector<std::string> const& args) << " " << newname << "\n" << "because: " << err << "\n"; /* clang-format on */ - this->SetError(e.str()); + status.SetError(e.str()); return false; } return true; } -bool cmFileCommand::HandleRemove(std::vector<std::string> const& args, - bool recurse) +bool HandleRemoveImpl(std::vector<std::string> const& args, bool recurse, + cmExecutionStatus& status) { std::string message; @@ -1397,18 +1337,18 @@ bool cmFileCommand::HandleRemove(std::vector<std::string> const& args, std::string fileName = arg; if (fileName.empty()) { std::string const r = recurse ? "REMOVE_RECURSE" : "REMOVE"; - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, - "Ignoring empty file name in " + r + "."); + status.GetMakefile().IssueMessage( + MessageType::AUTHOR_WARNING, "Ignoring empty file name in " + r + "."); continue; } if (!cmsys::SystemTools::FileIsFullPath(fileName)) { - fileName = this->Makefile->GetCurrentSourceDirectory(); - fileName += "/" + arg; + fileName = + cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', arg); } if (cmSystemTools::FileIsDirectory(fileName) && !cmSystemTools::FileIsSymlink(fileName) && recurse) { - cmSystemTools::RemoveADirectory(fileName); + cmSystemTools::RepeatedRemoveDirectory(fileName); } else { cmSystemTools::RemoveFile(fileName); } @@ -1416,7 +1356,18 @@ bool cmFileCommand::HandleRemove(std::vector<std::string> const& args, return true; } -namespace { +bool HandleRemove(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleRemoveImpl(args, false, status); +} + +bool HandleRemoveRecurse(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleRemoveImpl(args, true, status); +} + std::string ToNativePath(const std::string& path) { const auto& outPath = cmSystemTools::ConvertToOutputPath(path); @@ -1433,14 +1384,14 @@ std::string ToCMakePath(const std::string& path) cmSystemTools::ConvertToUnixSlashes(temp); return temp; } -} -bool cmFileCommand::HandleCMakePathCommand( - std::vector<std::string> const& args, bool nativePath) +bool HandlePathCommand(std::vector<std::string> const& args, + std::string (*convert)(std::string const&), + cmExecutionStatus& status) { if (args.size() != 3) { - this->SetError("FILE([TO_CMAKE_PATH|TO_NATIVE_PATH] path result) must be " - "called with exactly three arguments."); + status.SetError("FILE([TO_CMAKE_PATH|TO_NATIVE_PATH] path result) must be " + "called with exactly three arguments."); return false; } #if defined(_WIN32) && !defined(__CYGWIN__) @@ -1450,19 +1401,28 @@ bool cmFileCommand::HandleCMakePathCommand( #endif std::vector<std::string> path = cmSystemTools::SplitString(args[1], pathSep); - std::string value = cmJoin( - cmMakeRange(path).transform(nativePath ? ToNativePath : ToCMakePath), ";"); - this->Makefile->AddDefinition(args[2], value.c_str()); + std::string value = cmJoin(cmMakeRange(path).transform(convert), ";"); + status.GetMakefile().AddDefinition(args[2], value); return true; } -#if defined(CMAKE_BUILD_WITH_CMAKE) +bool HandleCMakePathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandlePathCommand(args, ToCMakePath, status); +} + +bool HandleNativePathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandlePathCommand(args, ToNativePath, status); +} + +#if !defined(CMAKE_BOOTSTRAP) // Stuff for curl download/upload typedef std::vector<char> cmFileCommandVectorOfChar; -namespace { - size_t cmWriteToFileCallback(void* ptr, size_t size, size_t nmemb, void* data) { int realsize = static_cast<int>(size * nmemb); @@ -1513,11 +1473,10 @@ size_t cmFileCommandCurlDebugCallback(CURL*, curl_infotype type, char* chPtr, class cURLProgressHelper { public: - cURLProgressHelper(cmFileCommand* fc, const char* text) + cURLProgressHelper(cmMakefile* mf, const char* text) + : Makefile(mf) + , Text(text) { - this->CurrentPercentage = -1; - this->FileCommand = fc; - this->Text = text; } bool UpdatePercentage(double value, double total, std::string& status) @@ -1544,11 +1503,11 @@ public: return updated; } - cmFileCommand* GetFileCommand() { return this->FileCommand; } + cmMakefile* GetMakefile() { return this->Makefile; } private: - long CurrentPercentage; - cmFileCommand* FileCommand; + long CurrentPercentage = -1; + cmMakefile* Makefile; std::string Text; }; @@ -1562,8 +1521,7 @@ int cmFileDownloadProgressCallback(void* clientp, double dltotal, double dlnow, std::string status; if (helper->UpdatePercentage(dlnow, dltotal, status)) { - cmFileCommand* fc = helper->GetFileCommand(); - cmMakefile* mf = fc->GetMakefile(); + cmMakefile* mf = helper->GetMakefile(); mf->DisplayStatus(status, -1); } @@ -1580,16 +1538,12 @@ int cmFileUploadProgressCallback(void* clientp, double dltotal, double dlnow, std::string status; if (helper->UpdatePercentage(ulnow, ultotal, status)) { - cmFileCommand* fc = helper->GetFileCommand(); - cmMakefile* mf = fc->GetMakefile(); + cmMakefile* mf = helper->GetMakefile(); mf->DisplayStatus(status, -1); } return 0; } -} - -namespace { class cURLEasyGuard { @@ -1614,7 +1568,7 @@ public: private: ::CURL* Easy; }; -} + #endif #define check_curl_result(result, errstr) \ @@ -1622,17 +1576,18 @@ private: if (result != CURLE_OK) { \ std::string e(errstr); \ e += ::curl_easy_strerror(result); \ - this->SetError(e); \ + status.SetError(e); \ return false; \ } \ } while (false) -bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) +bool HandleDownloadCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) std::vector<std::string>::const_iterator i = args.begin(); if (args.size() < 3) { - this->SetError("DOWNLOAD must be called with at least three arguments."); + status.SetError("DOWNLOAD must be called with at least three arguments."); return false; } ++i; // Get rid of subcommand @@ -1645,11 +1600,12 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) long inactivity_timeout = 0; std::string logVar; std::string statusVar; - bool tls_verify = this->Makefile->IsOn("CMAKE_TLS_VERIFY"); - const char* cainfo = this->Makefile->GetDefinition("CMAKE_TLS_CAINFO"); - std::string netrc_level = this->Makefile->GetSafeDefinition("CMAKE_NETRC"); + bool tls_verify = status.GetMakefile().IsOn("CMAKE_TLS_VERIFY"); + const char* cainfo = status.GetMakefile().GetDefinition("CMAKE_TLS_CAINFO"); + std::string netrc_level = + status.GetMakefile().GetSafeDefinition("CMAKE_NETRC"); std::string netrc_file = - this->Makefile->GetSafeDefinition("CMAKE_NETRC_FILE"); + status.GetMakefile().GetSafeDefinition("CMAKE_NETRC_FILE"); std::string expectedHash; std::string hashMatchMSG; std::unique_ptr<cmCryptoHash> hash; @@ -1664,7 +1620,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) if (i != args.end()) { timeout = atol(i->c_str()); } else { - this->SetError("DOWNLOAD missing time for TIMEOUT."); + status.SetError("DOWNLOAD missing time for TIMEOUT."); return false; } } else if (*i == "INACTIVITY_TIMEOUT") { @@ -1672,29 +1628,29 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) if (i != args.end()) { inactivity_timeout = atol(i->c_str()); } else { - this->SetError("DOWNLOAD missing time for INACTIVITY_TIMEOUT."); + status.SetError("DOWNLOAD missing time for INACTIVITY_TIMEOUT."); return false; } } else if (*i == "LOG") { ++i; if (i == args.end()) { - this->SetError("DOWNLOAD missing VAR for LOG."); + status.SetError("DOWNLOAD missing VAR for LOG."); return false; } logVar = *i; } else if (*i == "STATUS") { ++i; if (i == args.end()) { - this->SetError("DOWNLOAD missing VAR for STATUS."); + status.SetError("DOWNLOAD missing VAR for STATUS."); return false; } statusVar = *i; } else if (*i == "TLS_VERIFY") { ++i; if (i != args.end()) { - tls_verify = cmSystemTools::IsOn(*i); + tls_verify = cmIsOn(*i); } else { - this->SetError("TLS_VERIFY missing bool value."); + status.SetError("TLS_VERIFY missing bool value."); return false; } } else if (*i == "TLS_CAINFO") { @@ -1702,7 +1658,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) if (i != args.end()) { cainfo = i->c_str(); } else { - this->SetError("TLS_CAFILE missing file value."); + status.SetError("TLS_CAFILE missing file value."); return false; } } else if (*i == "NETRC_FILE") { @@ -1710,7 +1666,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) if (i != args.end()) { netrc_file = *i; } else { - this->SetError("DOWNLOAD missing file value for NETRC_FILE."); + status.SetError("DOWNLOAD missing file value for NETRC_FILE."); return false; } } else if (*i == "NETRC") { @@ -1718,13 +1674,13 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) if (i != args.end()) { netrc_level = *i; } else { - this->SetError("DOWNLOAD missing level value for NETRC."); + status.SetError("DOWNLOAD missing level value for NETRC."); return false; } } else if (*i == "EXPECTED_MD5") { ++i; if (i == args.end()) { - this->SetError("DOWNLOAD missing sum value for EXPECTED_MD5."); + status.SetError("DOWNLOAD missing sum value for EXPECTED_MD5."); return false; } hash = cm::make_unique<cmCryptoHash>(cmCryptoHash::AlgoMD5); @@ -1735,46 +1691,44 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) } else if (*i == "EXPECTED_HASH") { ++i; if (i == args.end()) { - this->SetError("DOWNLOAD missing ALGO=value for EXPECTED_HASH."); + status.SetError("DOWNLOAD missing ALGO=value for EXPECTED_HASH."); return false; } std::string::size_type pos = i->find("="); if (pos == std::string::npos) { std::string err = - "DOWNLOAD EXPECTED_HASH expects ALGO=value but got: "; - err += *i; - this->SetError(err); + cmStrCat("DOWNLOAD EXPECTED_HASH expects ALGO=value but got: ", *i); + status.SetError(err); return false; } std::string algo = i->substr(0, pos); expectedHash = cmSystemTools::LowerCase(i->substr(pos + 1)); - hash = std::unique_ptr<cmCryptoHash>(cmCryptoHash::New(algo.c_str())); + hash = std::unique_ptr<cmCryptoHash>(cmCryptoHash::New(algo)); if (!hash) { - std::string err = "DOWNLOAD EXPECTED_HASH given unknown ALGO: "; - err += algo; - this->SetError(err); + std::string err = + cmStrCat("DOWNLOAD EXPECTED_HASH given unknown ALGO: ", algo); + status.SetError(err); return false; } hashMatchMSG = algo + " hash"; } else if (*i == "USERPWD") { ++i; if (i == args.end()) { - this->SetError("DOWNLOAD missing string for USERPWD."); + status.SetError("DOWNLOAD missing string for USERPWD."); return false; } userpwd = *i; } else if (*i == "HTTPHEADER") { ++i; if (i == args.end()) { - this->SetError("DOWNLOAD missing string for HTTPHEADER."); + status.SetError("DOWNLOAD missing string for HTTPHEADER."); return false; } curl_headers.push_back(*i); } else { // Do not return error for compatibility reason. - std::string err = "Unexpected argument: "; - err += *i; - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, err); + std::string err = cmStrCat("Unexpected argument: ", *i); + status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, err); } ++i; } @@ -1786,13 +1740,12 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) std::string msg; std::string actualHash = hash->HashFile(file); if (actualHash == expectedHash) { - msg = "returning early; file already exists with expected "; - msg += hashMatchMSG; - msg += "\""; + msg = cmStrCat("returning early; file already exists with expected ", + hashMatchMSG, '"'); if (!statusVar.empty()) { std::ostringstream result; result << 0 << ";\"" << msg; - this->Makefile->AddDefinition(statusVar, result.str().c_str()); + status.GetMakefile().AddDefinition(statusVar, result.str()); } return true; } @@ -1805,13 +1758,13 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) std::string errstring = "DOWNLOAD error: cannot create directory '" + dir + "' - Specify file by full path name and verify that you " "have directory creation and file write privileges."; - this->SetError(errstring); + status.SetError(errstring); return false; } cmsys::ofstream fout(file.c_str(), std::ios::binary); if (!fout) { - this->SetError("DOWNLOAD cannot open file for write."); + status.SetError("DOWNLOAD cannot open file for write."); return false; } @@ -1823,7 +1776,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) ::curl_global_init(CURL_GLOBAL_DEFAULT); curl = ::curl_easy_init(); if (!curl) { - this->SetError("DOWNLOAD error initializing curl."); + status.SetError("DOWNLOAD error initializing curl."); return false; } @@ -1857,7 +1810,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) // command arg comes first std::string const& cainfo_err = cmCurlSetCAInfo(curl, cainfo); if (!cainfo_err.empty()) { - this->SetError(cainfo_err); + status.SetError(cainfo_err); return false; } @@ -1867,7 +1820,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) std::string const& netrc_option_err = cmCurlSetNETRCOption(curl, netrc_level, netrc_file); if (!netrc_option_err.empty()) { - this->SetError(netrc_option_err); + status.SetError(netrc_option_err); return false; } @@ -1903,7 +1856,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) // scope intentionally, rather than inside the "if(showProgress)" // block... // - cURLProgressHelper helper(this, "download"); + cURLProgressHelper helper(&status.GetMakefile(), "download"); if (showProgress) { res = ::curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); @@ -1941,7 +1894,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) std::ostringstream result; result << static_cast<int>(res) << ";\"" << ::curl_easy_strerror(res) << "\""; - this->Makefile->AddDefinition(statusVar, result.str().c_str()); + status.GetMakefile().AddDefinition(statusVar, result.str()); } ::curl_global_cleanup(); @@ -1956,7 +1909,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) if (hash) { std::string actualHash = hash->HashFile(file); if (actualHash.empty()) { - this->SetError("DOWNLOAD cannot compute hash on downloaded file"); + status.SetError("DOWNLOAD cannot compute hash on downloaded file"); return false; } @@ -1970,34 +1923,36 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) << ::curl_easy_strerror(res) << "\"]" << std::endl; if (!statusVar.empty() && res == 0) { - std::string status = "1;HASH mismatch: " - "expected: " + - expectedHash + " actual: " + actualHash; - this->Makefile->AddDefinition(statusVar, status.c_str()); + status.GetMakefile().AddDefinition(statusVar, + "1;HASH mismatch: " + "expected: " + + expectedHash + + " actual: " + actualHash); } - this->SetError(oss.str()); + status.SetError(oss.str()); return false; } } if (!logVar.empty()) { chunkDebug.push_back(0); - this->Makefile->AddDefinition(logVar, chunkDebug.data()); + status.GetMakefile().AddDefinition(logVar, chunkDebug.data()); } return true; #else - this->SetError("DOWNLOAD not supported by bootstrap cmake."); + status.SetError("DOWNLOAD not supported by bootstrap cmake."); return false; #endif } -bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) +bool HandleUploadCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) if (args.size() < 3) { - this->SetError("UPLOAD must be called with at least three arguments."); + status.SetError("UPLOAD must be called with at least three arguments."); return false; } std::vector<std::string>::const_iterator i = args.begin(); @@ -2013,9 +1968,10 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) std::string statusVar; bool showProgress = false; std::string userpwd; - std::string netrc_level = this->Makefile->GetSafeDefinition("CMAKE_NETRC"); + std::string netrc_level = + status.GetMakefile().GetSafeDefinition("CMAKE_NETRC"); std::string netrc_file = - this->Makefile->GetSafeDefinition("CMAKE_NETRC_FILE"); + status.GetMakefile().GetSafeDefinition("CMAKE_NETRC_FILE"); std::vector<std::string> curl_headers; @@ -2025,7 +1981,7 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) if (i != args.end()) { timeout = atol(i->c_str()); } else { - this->SetError("UPLOAD missing time for TIMEOUT."); + status.SetError("UPLOAD missing time for TIMEOUT."); return false; } } else if (*i == "INACTIVITY_TIMEOUT") { @@ -2033,20 +1989,20 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) if (i != args.end()) { inactivity_timeout = atol(i->c_str()); } else { - this->SetError("UPLOAD missing time for INACTIVITY_TIMEOUT."); + status.SetError("UPLOAD missing time for INACTIVITY_TIMEOUT."); return false; } } else if (*i == "LOG") { ++i; if (i == args.end()) { - this->SetError("UPLOAD missing VAR for LOG."); + status.SetError("UPLOAD missing VAR for LOG."); return false; } logVar = *i; } else if (*i == "STATUS") { ++i; if (i == args.end()) { - this->SetError("UPLOAD missing VAR for STATUS."); + status.SetError("UPLOAD missing VAR for STATUS."); return false; } statusVar = *i; @@ -2057,7 +2013,7 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) if (i != args.end()) { netrc_file = *i; } else { - this->SetError("UPLOAD missing file value for NETRC_FILE."); + status.SetError("UPLOAD missing file value for NETRC_FILE."); return false; } } else if (*i == "NETRC") { @@ -2065,28 +2021,27 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) if (i != args.end()) { netrc_level = *i; } else { - this->SetError("UPLOAD missing level value for NETRC."); + status.SetError("UPLOAD missing level value for NETRC."); return false; } } else if (*i == "USERPWD") { ++i; if (i == args.end()) { - this->SetError("UPLOAD missing string for USERPWD."); + status.SetError("UPLOAD missing string for USERPWD."); return false; } userpwd = *i; } else if (*i == "HTTPHEADER") { ++i; if (i == args.end()) { - this->SetError("UPLOAD missing string for HTTPHEADER."); + status.SetError("UPLOAD missing string for HTTPHEADER."); return false; } curl_headers.push_back(*i); } else { // Do not return error for compatibility reason. - std::string err = "Unexpected argument: "; - err += *i; - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, err); + std::string err = cmStrCat("Unexpected argument: ", *i); + status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, err); } ++i; @@ -2096,9 +2051,9 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) // FILE* fin = cmsys::SystemTools::Fopen(filename, "rb"); if (!fin) { - std::string errStr = "UPLOAD cannot open file '"; - errStr += filename + "' for reading."; - this->SetError(errStr); + std::string errStr = + cmStrCat("UPLOAD cannot open file '", filename, "' for reading."); + status.SetError(errStr); return false; } @@ -2112,7 +2067,7 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) ::curl_global_init(CURL_GLOBAL_DEFAULT); curl = ::curl_easy_init(); if (!curl) { - this->SetError("UPLOAD error initializing curl."); + status.SetError("UPLOAD error initializing curl."); fclose(fin); return false; } @@ -2171,7 +2126,7 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) // scope intentionally, rather than inside the "if(showProgress)" // block... // - cURLProgressHelper helper(this, "upload"); + cURLProgressHelper helper(&status.GetMakefile(), "upload"); if (showProgress) { res = ::curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); @@ -2206,7 +2161,7 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) std::string const& netrc_option_err = cmCurlSetNETRCOption(curl, netrc_level, netrc_file); if (!netrc_option_err.empty()) { - this->SetError(netrc_option_err); + status.SetError(netrc_option_err); return false; } @@ -2228,7 +2183,7 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) std::ostringstream result; result << static_cast<int>(res) << ";\"" << ::curl_easy_strerror(res) << "\""; - this->Makefile->AddDefinition(statusVar, result.str().c_str()); + status.GetMakefile().AddDefinition(statusVar, result.str()); } ::curl_global_cleanup(); @@ -2253,22 +2208,22 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args) log += "\n"; } - this->Makefile->AddDefinition(logVar, log.c_str()); + status.GetMakefile().AddDefinition(logVar, log); } return true; #else - this->SetError("UPLOAD not supported by bootstrap cmake."); + status.SetError("UPLOAD not supported by bootstrap cmake."); return false; #endif } -void cmFileCommand::AddEvaluationFile(const std::string& inputName, - const std::string& outputExpr, - const std::string& condition, - bool inputIsContent) +void AddEvaluationFile(const std::string& inputName, + const std::string& outputExpr, + const std::string& condition, bool inputIsContent, + cmExecutionStatus& status) { - cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); + cmListFileBacktrace lfbt = status.GetMakefile().GetBacktrace(); cmGeneratorExpression outputGe(lfbt); std::unique_ptr<cmCompiledGeneratorExpression> outputCge = @@ -2278,52 +2233,54 @@ void cmFileCommand::AddEvaluationFile(const std::string& inputName, std::unique_ptr<cmCompiledGeneratorExpression> conditionCge = conditionGe.Parse(condition); - this->Makefile->AddEvaluationFile(inputName, std::move(outputCge), - std::move(conditionCge), inputIsContent); + status.GetMakefile().AddEvaluationFile( + inputName, std::move(outputCge), std::move(conditionCge), inputIsContent); } -bool cmFileCommand::HandleGenerateCommand(std::vector<std::string> const& args) +bool HandleGenerateCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 5) { - this->SetError("Incorrect arguments to GENERATE subcommand."); + status.SetError("Incorrect arguments to GENERATE subcommand."); return false; } if (args[1] != "OUTPUT") { - this->SetError("Incorrect arguments to GENERATE subcommand."); + status.SetError("Incorrect arguments to GENERATE subcommand."); return false; } std::string condition; if (args.size() > 5) { if (args[5] != "CONDITION") { - this->SetError("Incorrect arguments to GENERATE subcommand."); + status.SetError("Incorrect arguments to GENERATE subcommand."); return false; } if (args.size() != 7) { - this->SetError("Incorrect arguments to GENERATE subcommand."); + status.SetError("Incorrect arguments to GENERATE subcommand."); return false; } condition = args[6]; if (condition.empty()) { - this->SetError("CONDITION of sub-command GENERATE must not be empty if " - "specified."); + status.SetError("CONDITION of sub-command GENERATE must not be empty if " + "specified."); return false; } } std::string output = args[2]; const bool inputIsContent = args[3] != "INPUT"; if (inputIsContent && args[3] != "CONTENT") { - this->SetError("Incorrect arguments to GENERATE subcommand."); + status.SetError("Incorrect arguments to GENERATE subcommand."); return false; } std::string input = args[4]; - this->AddEvaluationFile(input, output, condition, inputIsContent); + AddEvaluationFile(input, output, condition, inputIsContent, status); return true; } -bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) +bool HandleLockCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) // Default values bool directory = false; bool release = false; @@ -2339,7 +2296,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) // Parse arguments if (args.size() < 2) { - this->Makefile->IssueMessage( + status.GetMakefile().IssueMessage( MessageType::FATAL_ERROR, "sub-command LOCK requires at least two arguments."); return false; @@ -2355,7 +2312,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) ++i; const char* merr = "expected FUNCTION, FILE or PROCESS after GUARD"; if (i >= args.size()) { - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, merr); + status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, merr); return false; } if (args[i] == "FUNCTION") { @@ -2367,14 +2324,14 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) } else { std::ostringstream e; e << merr << ", but got:\n \"" << args[i] << "\"."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } } else if (args[i] == "RESULT_VARIABLE") { ++i; if (i >= args.size()) { - this->Makefile->IssueMessage( + status.GetMakefile().IssueMessage( MessageType::FATAL_ERROR, "expected variable name after RESULT_VARIABLE"); return false; @@ -2383,16 +2340,15 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) } else if (args[i] == "TIMEOUT") { ++i; if (i >= args.size()) { - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, - "expected timeout value after TIMEOUT"); + status.GetMakefile().IssueMessage( + MessageType::FATAL_ERROR, "expected timeout value after TIMEOUT"); return false; } long scanned; - if (!cmSystemTools::StringToLong(args[i].c_str(), &scanned) || - scanned < 0) { + if (!cmStrToLong(args[i], &scanned) || scanned < 0) { std::ostringstream e; e << "TIMEOUT value \"" << args[i] << "\" is not an unsigned integer."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } timeout = static_cast<unsigned long>(scanned); @@ -2400,7 +2356,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) std::ostringstream e; e << "expected DIRECTORY, RELEASE, GUARD, RESULT_VARIABLE or TIMEOUT\n"; e << "but got: \"" << args[i] << "\"."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } } @@ -2410,7 +2366,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) } if (!cmsys::SystemTools::FileIsFullPath(path)) { - path = this->Makefile->GetCurrentSourceDirectory() + "/" + path; + path = status.GetMakefile().GetCurrentSourceDirectory() + "/" + path; } // Unify path (remove '//', '/../', ...) @@ -2422,7 +2378,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) std::ostringstream e; e << "directory\n \"" << parentDir << "\"\ncreation failed "; e << "(check permissions)."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -2430,7 +2386,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) if (!file) { std::ostringstream e; e << "file\n \"" << path << "\"\ncreation failed (check permissions)."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -2438,7 +2394,7 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) // Actual lock/unlock cmFileLockPool& lockPool = - this->Makefile->GetGlobalGenerator()->GetFileLockPool(); + status.GetMakefile().GetGlobalGenerator()->GetFileLockPool(); cmFileLockResult fileLockResult(cmFileLockResult::MakeOk()); if (release) { @@ -2465,32 +2421,32 @@ bool cmFileCommand::HandleLockCommand(std::vector<std::string> const& args) if (resultVariable.empty() && !fileLockResult.IsOk()) { std::ostringstream e; e << "error locking file\n \"" << path << "\"\n" << result << "."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return false; } if (!resultVariable.empty()) { - this->Makefile->AddDefinition(resultVariable, result.c_str()); + status.GetMakefile().AddDefinition(resultVariable, result); } return true; #else static_cast<void>(args); - this->SetError("sub-command LOCK not implemented in bootstrap cmake"); + status.SetError("sub-command LOCK not implemented in bootstrap cmake"); return false; #endif } -bool cmFileCommand::HandleTimestampCommand( - std::vector<std::string> const& args) +bool HandleTimestampCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 3) { - this->SetError("sub-command TIMESTAMP requires at least two arguments."); + status.SetError("sub-command TIMESTAMP requires at least two arguments."); return false; } if (args.size() > 5) { - this->SetError("sub-command TIMESTAMP takes at most four arguments."); + status.SetError("sub-command TIMESTAMP takes at most four arguments."); return false; } @@ -2512,7 +2468,7 @@ bool cmFileCommand::HandleTimestampCommand( } else { std::string e = " TIMESTAMP sub-command does not recognize option " + args[argsIndex] + "."; - this->SetError(e); + status.SetError(e); return false; } } @@ -2520,17 +2476,18 @@ bool cmFileCommand::HandleTimestampCommand( cmTimestamp timestamp; std::string result = timestamp.FileModificationTime(filename.c_str(), formatString, utcFlag); - this->Makefile->AddDefinition(outputVariable, result.c_str()); + status.GetMakefile().AddDefinition(outputVariable, result); return true; } -bool cmFileCommand::HandleSizeCommand(std::vector<std::string> const& args) +bool HandleSizeCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 3) { std::ostringstream e; e << args[0] << " requires a file name and output variable"; - this->SetError(e.str()); + status.SetError(e.str()); return false; } @@ -2543,24 +2500,23 @@ bool cmFileCommand::HandleSizeCommand(std::vector<std::string> const& args) if (!cmSystemTools::FileExists(filename, true)) { std::ostringstream e; e << "SIZE requested of path that is not readable:\n " << filename; - this->SetError(e.str()); + status.SetError(e.str()); return false; } - this->Makefile->AddDefinition( - outputVariable, - std::to_string(cmSystemTools::FileLength(filename)).c_str()); + status.GetMakefile().AddDefinition( + outputVariable, std::to_string(cmSystemTools::FileLength(filename))); return true; } -bool cmFileCommand::HandleReadSymlinkCommand( - std::vector<std::string> const& args) +bool HandleReadSymlinkCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 3) { std::ostringstream e; e << args[0] << " requires a file name and output variable"; - this->SetError(e.str()); + status.SetError(e.str()); return false; } @@ -2572,21 +2528,21 @@ bool cmFileCommand::HandleReadSymlinkCommand( std::ostringstream e; e << "READ_SYMLINK requested of path that is not a symlink:\n " << filename; - this->SetError(e.str()); + status.SetError(e.str()); return false; } - this->Makefile->AddDefinition(outputVariable, result.c_str()); + status.GetMakefile().AddDefinition(outputVariable, result); return true; } -bool cmFileCommand::HandleCreateLinkCommand( - std::vector<std::string> const& args) +bool HandleCreateLinkCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 3) { - this->SetError("CREATE_LINK must be called with at least two additional " - "arguments"); + status.SetError("CREATE_LINK must be called with at least two additional " + "arguments"); return false; } @@ -2611,7 +2567,7 @@ bool cmFileCommand::HandleCreateLinkCommand( parser.Parse(cmMakeRange(args).advance(3), &unconsumedArgs); if (!unconsumedArgs.empty()) { - this->SetError("unknown argument: \"" + unconsumedArgs.front() + '\"'); + status.SetError("unknown argument: \"" + unconsumedArgs.front() + '\"'); return false; } @@ -2622,10 +2578,10 @@ bool cmFileCommand::HandleCreateLinkCommand( if (fileName == newFileName) { result = "CREATE_LINK cannot use same file and newfile"; if (!arguments.Result.empty()) { - this->Makefile->AddDefinition(arguments.Result, result.c_str()); + status.GetMakefile().AddDefinition(arguments.Result, result); return true; } - this->SetError(result); + status.SetError(result); return false; } @@ -2633,10 +2589,10 @@ bool cmFileCommand::HandleCreateLinkCommand( if (!arguments.Symbolic && !cmSystemTools::FileExists(fileName)) { result = "Cannot hard link \'" + fileName + "\' as it does not exist."; if (!arguments.Result.empty()) { - this->Makefile->AddDefinition(arguments.Result, result.c_str()); + status.GetMakefile().AddDefinition(arguments.Result, result); return true; } - this->SetError(result); + status.SetError(result); return false; } @@ -2650,10 +2606,10 @@ bool cmFileCommand::HandleCreateLinkCommand( << cmSystemTools::GetLastSystemError() << "\n"; if (!arguments.Result.empty()) { - this->Makefile->AddDefinition(arguments.Result, e.str().c_str()); + status.GetMakefile().AddDefinition(arguments.Result, e.str()); return true; } - this->SetError(e.str()); + status.SetError(e.str()); return false; } @@ -2680,13 +2636,242 @@ bool cmFileCommand::HandleCreateLinkCommand( result = "0"; } else if (arguments.Result.empty()) { // The operation failed and the result is not reported in a variable. - this->SetError(result); + status.SetError(result); return false; } if (!arguments.Result.empty()) { - this->Makefile->AddDefinition(arguments.Result, result.c_str()); + status.GetMakefile().AddDefinition(arguments.Result, result); + } + + return true; +} + +bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + static const std::set<std::string> supportedPlatforms = { "Windows", "Linux", + "Darwin" }; + std::string platform = + status.GetMakefile().GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME"); + if (!supportedPlatforms.count(platform)) { + std::ostringstream e; + e << "GET_RUNTIME_DEPENDENCIES is not supported on system \"" << platform + << "\""; + status.SetError(e.str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + if (status.GetMakefile().GetState()->GetMode() == cmState::Project) { + status.GetMakefile().IssueMessage( + MessageType::AUTHOR_WARNING, + "You have used file(GET_RUNTIME_DEPENDENCIES)" + " in project mode. This is probably not what " + "you intended to do. Instead, please consider" + " using it in an install(CODE) or " + "install(SCRIPT) command. For example:" + "\n install(CODE [[" + "\n file(GET_RUNTIME_DEPENDENCIES" + "\n # ..." + "\n )" + "\n ]])"); + } + + struct Arguments + { + std::string ResolvedDependenciesVar; + std::string UnresolvedDependenciesVar; + std::string ConflictingDependenciesPrefix; + std::string BundleExecutable; + std::vector<std::string> Executables; + std::vector<std::string> Libraries; + std::vector<std::string> Directories; + std::vector<std::string> Modules; + std::vector<std::string> PreIncludeRegexes; + std::vector<std::string> PreExcludeRegexes; + std::vector<std::string> PostIncludeRegexes; + std::vector<std::string> PostExcludeRegexes; + }; + + static auto const parser = + cmArgumentParser<Arguments>{} + .Bind("RESOLVED_DEPENDENCIES_VAR"_s, &Arguments::ResolvedDependenciesVar) + .Bind("UNRESOLVED_DEPENDENCIES_VAR"_s, + &Arguments::UnresolvedDependenciesVar) + .Bind("CONFLICTING_DEPENDENCIES_PREFIX"_s, + &Arguments::ConflictingDependenciesPrefix) + .Bind("BUNDLE_EXECUTABLE"_s, &Arguments::BundleExecutable) + .Bind("EXECUTABLES"_s, &Arguments::Executables) + .Bind("LIBRARIES"_s, &Arguments::Libraries) + .Bind("MODULES"_s, &Arguments::Modules) + .Bind("DIRECTORIES"_s, &Arguments::Directories) + .Bind("PRE_INCLUDE_REGEXES"_s, &Arguments::PreIncludeRegexes) + .Bind("PRE_EXCLUDE_REGEXES"_s, &Arguments::PreExcludeRegexes) + .Bind("POST_INCLUDE_REGEXES"_s, &Arguments::PostIncludeRegexes) + .Bind("POST_EXCLUDE_REGEXES"_s, &Arguments::PostExcludeRegexes); + + std::vector<std::string> unrecognizedArguments; + std::vector<std::string> keywordsMissingValues; + auto parsedArgs = + parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments, + &keywordsMissingValues); + auto argIt = unrecognizedArguments.begin(); + if (argIt != unrecognizedArguments.end()) { + std::ostringstream e; + e << "Unrecognized argument: \"" << *argIt << "\""; + status.SetError(e.str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + argIt = keywordsMissingValues.begin(); + if (argIt != keywordsMissingValues.end()) { + std::ostringstream e; + e << "Keyword missing value: " << *argIt; + status.SetError(e.str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + cmRuntimeDependencyArchive archive( + status, parsedArgs.Directories, parsedArgs.BundleExecutable, + parsedArgs.PreIncludeRegexes, parsedArgs.PreExcludeRegexes, + parsedArgs.PostIncludeRegexes, parsedArgs.PostExcludeRegexes); + if (!archive.Prepare()) { + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + if (!archive.GetRuntimeDependencies( + parsedArgs.Executables, parsedArgs.Libraries, parsedArgs.Modules)) { + cmSystemTools::SetFatalErrorOccured(); + return false; } + std::vector<std::string> deps; + std::vector<std::string> unresolvedDeps; + std::vector<std::string> conflictingDeps; + for (auto const& val : archive.GetResolvedPaths()) { + bool unique = true; + auto it = val.second.begin(); + assert(it != val.second.end()); + auto const& firstPath = *it; + while (++it != val.second.end()) { + if (!cmSystemTools::SameFile(firstPath, *it)) { + unique = false; + break; + } + } + + if (unique) { + deps.push_back(firstPath); + } else if (!parsedArgs.ConflictingDependenciesPrefix.empty()) { + conflictingDeps.push_back(val.first); + std::vector<std::string> paths; + paths.insert(paths.begin(), val.second.begin(), val.second.end()); + std::string varName = + parsedArgs.ConflictingDependenciesPrefix + "_" + val.first; + std::string pathsStr = cmJoin(paths, ";"); + status.GetMakefile().AddDefinition(varName, pathsStr); + } else { + std::ostringstream e; + e << "Multiple conflicting paths found for " << val.first << ":"; + for (auto const& path : val.second) { + e << "\n " << path; + } + status.SetError(e.str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + } + if (!archive.GetUnresolvedPaths().empty()) { + if (!parsedArgs.UnresolvedDependenciesVar.empty()) { + unresolvedDeps.insert(unresolvedDeps.begin(), + archive.GetUnresolvedPaths().begin(), + archive.GetUnresolvedPaths().end()); + } else { + auto it = archive.GetUnresolvedPaths().begin(); + assert(it != archive.GetUnresolvedPaths().end()); + std::ostringstream e; + e << "Could not resolve file " << *it; + status.SetError(e.str()); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + } + + if (!parsedArgs.ResolvedDependenciesVar.empty()) { + std::string val = cmJoin(deps, ";"); + status.GetMakefile().AddDefinition(parsedArgs.ResolvedDependenciesVar, + val); + } + if (!parsedArgs.UnresolvedDependenciesVar.empty()) { + std::string val = cmJoin(unresolvedDeps, ";"); + status.GetMakefile().AddDefinition(parsedArgs.UnresolvedDependenciesVar, + val); + } + if (!parsedArgs.ConflictingDependenciesPrefix.empty()) { + std::string val = cmJoin(conflictingDeps, ";"); + status.GetMakefile().AddDefinition( + parsedArgs.ConflictingDependenciesPrefix + "_FILENAMES", val); + } return true; } + +} // namespace + +bool cmFileCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + if (args.size() < 2) { + status.SetError("must be called with at least two arguments."); + return false; + } + + static cmSubcommandTable const subcommand{ + { "WRITE"_s, HandleWriteCommand }, + { "APPEND"_s, HandleAppendCommand }, + { "DOWNLOAD"_s, HandleDownloadCommand }, + { "UPLOAD"_s, HandleUploadCommand }, + { "READ"_s, HandleReadCommand }, + { "MD5"_s, HandleHashCommand }, + { "SHA1"_s, HandleHashCommand }, + { "SHA224"_s, HandleHashCommand }, + { "SHA256"_s, HandleHashCommand }, + { "SHA384"_s, HandleHashCommand }, + { "SHA512"_s, HandleHashCommand }, + { "SHA3_224"_s, HandleHashCommand }, + { "SHA3_256"_s, HandleHashCommand }, + { "SHA3_384"_s, HandleHashCommand }, + { "SHA3_512"_s, HandleHashCommand }, + { "STRINGS"_s, HandleStringsCommand }, + { "GLOB"_s, HandleGlobCommand }, + { "GLOB_RECURSE"_s, HandleGlobRecurseCommand }, + { "MAKE_DIRECTORY"_s, HandleMakeDirectoryCommand }, + { "RENAME"_s, HandleRename }, + { "REMOVE"_s, HandleRemove }, + { "REMOVE_RECURSE"_s, HandleRemoveRecurse }, + { "COPY"_s, HandleCopyCommand }, + { "INSTALL"_s, HandleInstallCommand }, + { "DIFFERENT"_s, HandleDifferentCommand }, + { "RPATH_CHANGE"_s, HandleRPathChangeCommand }, + { "CHRPATH"_s, HandleRPathChangeCommand }, + { "RPATH_CHECK"_s, HandleRPathCheckCommand }, + { "RPATH_REMOVE"_s, HandleRPathRemoveCommand }, + { "READ_ELF"_s, HandleReadElfCommand }, + { "RELATIVE_PATH"_s, HandleRelativePathCommand }, + { "TO_CMAKE_PATH"_s, HandleCMakePathCommand }, + { "TO_NATIVE_PATH"_s, HandleNativePathCommand }, + { "TOUCH"_s, HandleTouchCommand }, + { "TOUCH_NOCREATE"_s, HandleTouchNocreateCommand }, + { "TIMESTAMP"_s, HandleTimestampCommand }, + { "GENERATE"_s, HandleGenerateCommand }, + { "LOCK"_s, HandleLockCommand }, + { "SIZE"_s, HandleSizeCommand }, + { "READ_SYMLINK"_s, HandleReadSymlinkCommand }, + { "CREATE_LINK"_s, HandleCreateLinkCommand }, + { "GET_RUNTIME_DEPENDENCIES"_s, HandleGetRuntimeDependenciesCommand }, + }; + + return subcommand(args[0], args, status); +} diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index 12c5115..8c9b219 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -8,65 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmFileCommand - * \brief Command for manipulation of files - * - */ -class cmFileCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmFileCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -protected: - bool HandleRename(std::vector<std::string> const& args); - bool HandleRemove(std::vector<std::string> const& args, bool recurse); - bool HandleWriteCommand(std::vector<std::string> const& args, bool append); - bool HandleReadCommand(std::vector<std::string> const& args); - bool HandleHashCommand(std::vector<std::string> const& args); - bool HandleStringsCommand(std::vector<std::string> const& args); - bool HandleGlobCommand(std::vector<std::string> const& args, bool recurse); - bool HandleTouchCommand(std::vector<std::string> const& args, bool create); - bool HandleMakeDirectoryCommand(std::vector<std::string> const& args); - - bool HandleRelativePathCommand(std::vector<std::string> const& args); - bool HandleCMakePathCommand(std::vector<std::string> const& args, - bool nativePath); - bool HandleReadElfCommand(std::vector<std::string> const& args); - bool HandleRPathChangeCommand(std::vector<std::string> const& args); - bool HandleRPathCheckCommand(std::vector<std::string> const& args); - bool HandleRPathRemoveCommand(std::vector<std::string> const& args); - bool HandleDifferentCommand(std::vector<std::string> const& args); - - bool HandleCopyCommand(std::vector<std::string> const& args); - bool HandleInstallCommand(std::vector<std::string> const& args); - bool HandleDownloadCommand(std::vector<std::string> const& args); - bool HandleUploadCommand(std::vector<std::string> const& args); - - bool HandleTimestampCommand(std::vector<std::string> const& args); - bool HandleGenerateCommand(std::vector<std::string> const& args); - bool HandleLockCommand(std::vector<std::string> const& args); - bool HandleSizeCommand(std::vector<std::string> const& args); - bool HandleReadSymlinkCommand(std::vector<std::string> const& args); - bool HandleCreateLinkCommand(std::vector<std::string> const& args); - -private: - void AddEvaluationFile(const std::string& inputName, - const std::string& outputExpr, - const std::string& condition, bool inputIsContent); -}; +bool cmFileCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx index 49e8cd5..e00e726 100644 --- a/Source/cmFileCopier.cxx +++ b/Source/cmFileCopier.cxx @@ -3,10 +3,11 @@ #include "cmFileCopier.h" +#include "cmExecutionStatus.h" #include "cmFSPermissions.h" -#include "cmFileCommand.h" #include "cmFileTimes.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmsys/Directory.hxx" #include "cmsys/Glob.hxx" @@ -20,9 +21,9 @@ using namespace cmFSPermissions; -cmFileCopier::cmFileCopier(cmFileCommand* command, const char* name) - : FileCommand(command) - , Makefile(command->GetMakefile()) +cmFileCopier::cmFileCopier(cmExecutionStatus& status, const char* name) + : Status(status) + , Makefile(&status.GetMakefile()) , Name(name) , Always(false) , MatchlessFiles(true) @@ -90,8 +91,9 @@ bool cmFileCopier::SetPermissions(const std::string& toFile, if (!cmSystemTools::SetPermissions(toFile, permissions)) { std::ostringstream e; - e << this->Name << " cannot set permissions on \"" << toFile << "\""; - this->FileCommand->SetError(e.str()); + e << this->Name << " cannot set permissions on \"" << toFile + << "\": " << cmSystemTools::GetLastSystemError() << "."; + this->Status.SetError(e.str()); return false; } } @@ -105,7 +107,7 @@ bool cmFileCopier::CheckPermissions(std::string const& arg, if (!cmFSPermissions::stringToModeT(arg, permissions)) { std::ostringstream e; e << this->Name << " given invalid permission \"" << arg << "\"."; - this->FileCommand->SetError(e.str()); + this->Status.SetError(e.str()); return false; } return true; @@ -120,8 +122,9 @@ bool cmFileCopier::ReportMissing(const std::string& fromFile) { // The input file does not exist and installation is not optional. std::ostringstream e; - e << this->Name << " cannot find \"" << fromFile << "\"."; - this->FileCommand->SetError(e.str()); + e << this->Name << " cannot find \"" << fromFile + << "\": " << cmSystemTools::GetLastSystemError() << "."; + this->Status.SetError(e.str()); return false; } @@ -129,7 +132,7 @@ void cmFileCopier::NotBeforeMatch(std::string const& arg) { std::ostringstream e; e << "option " << arg << " may not appear before PATTERN or REGEX."; - this->FileCommand->SetError(e.str()); + this->Status.SetError(e.str()); this->Doing = DoingError; } @@ -137,7 +140,7 @@ void cmFileCopier::NotAfterMatch(std::string const& arg) { std::ostringstream e; e << "option " << arg << " may not appear after PATTERN or REGEX."; - this->FileCommand->SetError(e.str()); + this->Status.SetError(e.str()); this->Doing = DoingError; } @@ -170,15 +173,12 @@ bool cmFileCopier::GetDefaultDirectoryPermissions(mode_t** mode) const char* default_dir_install_permissions = this->Makefile->GetDefinition( "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); if (default_dir_install_permissions && *default_dir_install_permissions) { - std::vector<std::string> items; - cmSystemTools::ExpandListArgument(default_dir_install_permissions, items); + std::vector<std::string> items = + cmExpandedList(default_dir_install_permissions); for (const auto& arg : items) { if (!this->CheckPermissions(arg, **mode)) { - std::ostringstream e; - e << this->FileCommand->GetError() - << " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS " - "variable."; - this->FileCommand->SetError(e.str()); + this->Status.SetError( + " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS variable."); return false; } } @@ -197,7 +197,7 @@ bool cmFileCopier::Parse(std::vector<std::string> const& args) if (!this->CheckKeyword(args[i]) && !this->CheckValue(args[i])) { std::ostringstream e; e << "called with unknown argument \"" << args[i] << "\"."; - this->FileCommand->SetError(e.str()); + this->Status.SetError(e.str()); return false; } @@ -211,7 +211,7 @@ bool cmFileCopier::Parse(std::vector<std::string> const& args) if (this->Destination.empty()) { std::ostringstream e; e << this->Name << " given no DESTINATION"; - this->FileCommand->SetError(e.str()); + this->Status.SetError(e.str()); return false; } @@ -314,8 +314,8 @@ bool cmFileCopier::CheckValue(std::string const& arg) if (arg.empty() || cmSystemTools::FileIsFullPath(arg)) { this->Destination = arg; } else { - this->Destination = this->Makefile->GetCurrentBinaryDirectory(); - this->Destination += "/" + arg; + this->Destination = + cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', arg); } this->Doing = DoingNone; break; @@ -323,8 +323,8 @@ bool cmFileCopier::CheckValue(std::string const& arg) if (cmSystemTools::FileIsFullPath(arg)) { this->FilesFromDir = arg; } else { - this->FilesFromDir = this->Makefile->GetCurrentSourceDirectory(); - this->FilesFromDir += "/" + arg; + this->FilesFromDir = + cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', arg); } cmSystemTools::ConvertToUnixSlashes(this->FilesFromDir); this->Doing = DoingNone; @@ -334,9 +334,8 @@ bool cmFileCopier::CheckValue(std::string const& arg) // leading slash and trailing end-of-string in the matched // string to make sure the pattern matches only whole file // names. - std::string regex = "/"; - regex += cmsys::Glob::PatternToRegex(arg, false); - regex += "$"; + std::string regex = + cmStrCat('/', cmsys::Glob::PatternToRegex(arg, false), '$'); this->MatchRules.emplace_back(regex); this->CurrentMatchRule = &*(this->MatchRules.end() - 1); if (this->CurrentMatchRule->Regex.is_valid()) { @@ -344,7 +343,7 @@ bool cmFileCopier::CheckValue(std::string const& arg) } else { std::ostringstream e; e << "could not compile PATTERN \"" << arg << "\"."; - this->FileCommand->SetError(e.str()); + this->Status.SetError(e.str()); this->Doing = DoingError; } } break; @@ -356,7 +355,7 @@ bool cmFileCopier::CheckValue(std::string const& arg) } else { std::ostringstream e; e << "could not compile REGEX \"" << arg << "\"."; - this->FileCommand->SetError(e.str()); + this->Status.SetError(e.str()); this->Doing = DoingError; } break; @@ -399,8 +398,8 @@ bool cmFileCopier::Run(std::vector<std::string> const& args) file += "/"; file += f; } else if (!this->FilesFromDir.empty()) { - this->FileCommand->SetError("option FILES_FROM_DIR requires all files " - "to be specified as relative paths."); + this->Status.SetError("option FILES_FROM_DIR requires all files " + "to be specified as relative paths."); return false; } else { file = f; @@ -447,9 +446,8 @@ bool cmFileCopier::Install(const std::string& fromFile, const std::string& toFile) { if (fromFile.empty()) { - std::ostringstream e; - e << "INSTALL encountered an empty string input file name."; - this->FileCommand->SetError(e.str()); + this->Status.SetError( + "INSTALL encountered an empty string input file name."); return false; } @@ -493,7 +491,7 @@ bool cmFileCopier::InstallSymlinkChain(std::string& fromFile, while (cmSystemTools::ReadSymlink(fromFile, newFromFile)) { if (!cmSystemTools::FileIsFullPath(newFromFile)) { std::string fromFilePath = cmSystemTools::GetFilenamePath(fromFile); - newFromFile = fromFilePath + "/" + newFromFile; + newFromFile = cmStrCat(fromFilePath, "/", newFromFile); } std::string symlinkTarget = cmSystemTools::GetFilenameName(newFromFile); @@ -516,14 +514,15 @@ bool cmFileCopier::InstallSymlinkChain(std::string& fromFile, if (!cmSystemTools::CreateSymlink(symlinkTarget, toFile)) { std::ostringstream e; - e << this->Name << " cannot create symlink \"" << toFile << "\"."; - this->FileCommand->SetError(e.str()); + e << this->Name << " cannot create symlink \"" << toFile + << "\": " << cmSystemTools::GetLastSystemError() << "."; + this->Status.SetError(e.str()); return false; } } fromFile = newFromFile; - toFile = toFilePath + "/" + symlinkTarget; + toFile = cmStrCat(toFilePath, "/", symlinkTarget); } return true; @@ -537,8 +536,9 @@ bool cmFileCopier::InstallSymlink(const std::string& fromFile, if (!cmSystemTools::ReadSymlink(fromFile, symlinkTarget)) { std::ostringstream e; e << this->Name << " cannot read symlink \"" << fromFile - << "\" to duplicate at \"" << toFile << "\"."; - this->FileCommand->SetError(e.str()); + << "\" to duplicate at \"" << toFile + << "\": " << cmSystemTools::GetLastSystemError() << "."; + this->Status.SetError(e.str()); return false; } @@ -568,8 +568,9 @@ bool cmFileCopier::InstallSymlink(const std::string& fromFile, if (!cmSystemTools::CreateSymlink(symlinkTarget, toFile)) { std::ostringstream e; e << this->Name << " cannot duplicate symlink \"" << fromFile - << "\" at \"" << toFile << "\"."; - this->FileCommand->SetError(e.str()); + << "\" at \"" << toFile + << "\": " << cmSystemTools::GetLastSystemError() << "."; + this->Status.SetError(e.str()); return false; } } @@ -597,8 +598,8 @@ bool cmFileCopier::InstallFile(const std::string& fromFile, if (copy && !cmSystemTools::CopyAFile(fromFile, toFile, true)) { std::ostringstream e; e << this->Name << " cannot copy file \"" << fromFile << "\" to \"" - << toFile << "\"."; - this->FileCommand->SetError(e.str()); + << toFile << "\": " << cmSystemTools::GetLastSystemError() << "."; + this->Status.SetError(e.str()); return false; } @@ -613,8 +614,8 @@ bool cmFileCopier::InstallFile(const std::string& fromFile, if (!cmFileTimes::Copy(fromFile, toFile)) { std::ostringstream e; e << this->Name << " cannot set modification time on \"" << toFile - << "\""; - this->FileCommand->SetError(e.str()); + << "\": " << cmSystemTools::GetLastSystemError() << "."; + this->Status.SetError(e.str()); return false; } } @@ -650,8 +651,8 @@ bool cmFileCopier::InstallDirectory(const std::string& source, if (!cmSystemTools::MakeDirectory(destination, default_dir_mode)) { std::ostringstream e; e << this->Name << " cannot make directory \"" << destination - << "\": " << cmSystemTools::GetLastSystemError(); - this->FileCommand->SetError(e.str()); + << "\": " << cmSystemTools::GetLastSystemError() << "."; + this->Status.SetError(e.str()); return false; } @@ -696,12 +697,8 @@ bool cmFileCopier::InstallDirectory(const std::string& source, for (unsigned long fileNum = 0; fileNum < numFiles; ++fileNum) { if (!(strcmp(dir.GetFile(fileNum), ".") == 0 || strcmp(dir.GetFile(fileNum), "..") == 0)) { - std::string fromPath = source; - fromPath += "/"; - fromPath += dir.GetFile(fileNum); - std::string toPath = destination; - toPath += "/"; - toPath += dir.GetFile(fileNum); + std::string fromPath = cmStrCat(source, '/', dir.GetFile(fileNum)); + std::string toPath = cmStrCat(destination, '/', dir.GetFile(fileNum)); if (!this->Install(fromPath, toPath)) { return false; } diff --git a/Source/cmFileCopier.h b/Source/cmFileCopier.h index a79a60b..263a365 100644 --- a/Source/cmFileCopier.h +++ b/Source/cmFileCopier.h @@ -12,19 +12,19 @@ #include <string> #include <vector> -class cmFileCommand; +class cmExecutionStatus; class cmMakefile; // File installation helper class. struct cmFileCopier { - cmFileCopier(cmFileCommand* command, const char* name = "COPY"); + cmFileCopier(cmExecutionStatus& status, const char* name = "COPY"); virtual ~cmFileCopier(); bool Run(std::vector<std::string> const& args); protected: - cmFileCommand* FileCommand; + cmExecutionStatus& Status; cmMakefile* Makefile; const char* Name; bool Always; diff --git a/Source/cmFileInstaller.cxx b/Source/cmFileInstaller.cxx index d4f76fd..a773738 100644 --- a/Source/cmFileInstaller.cxx +++ b/Source/cmFileInstaller.cxx @@ -3,9 +3,10 @@ #include "cmFileInstaller.h" +#include "cmExecutionStatus.h" #include "cmFSPermissions.h" -#include "cmFileCommand.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cm_sys_stat.h" @@ -14,8 +15,8 @@ using namespace cmFSPermissions; -cmFileInstaller::cmFileInstaller(cmFileCommand* command) - : cmFileCopier(command, "INSTALL") +cmFileInstaller::cmFileInstaller(cmExecutionStatus& status) + : cmFileCopier(status, "INSTALL") , InstallType(cmInstallType_FILES) , Optional(false) , MessageAlways(false) @@ -28,7 +29,7 @@ cmFileInstaller::cmFileInstaller(cmFileCommand* command) // Check whether to copy files always or only if they have changed. std::string install_always; if (cmSystemTools::GetEnv("CMAKE_INSTALL_ALWAYS", install_always)) { - this->Always = cmSystemTools::IsOn(install_always); + this->Always = cmIsOn(install_always); } // Get the current manifest. this->Manifest = @@ -38,7 +39,7 @@ cmFileInstaller::~cmFileInstaller() { // Save the updated install manifest. this->Makefile->AddDefinition("CMAKE_INSTALL_MANIFEST_FILES", - this->Manifest.c_str()); + this->Manifest); } void cmFileInstaller::ManifestAppend(std::string const& file) @@ -58,8 +59,8 @@ void cmFileInstaller::ReportCopy(const std::string& toFile, Type type, bool copy) { if (!this->MessageNever && (copy || !this->MessageLazy)) { - std::string message = (copy ? "Installing: " : "Up-to-date: "); - message += toFile; + std::string message = + cmStrCat((copy ? "Installing: " : "Up-to-date: "), toFile); this->Makefile->DisplayStatus(message, -1); } if (type != TypeDir) { @@ -111,19 +112,19 @@ bool cmFileInstaller::Parse(std::vector<std::string> const& args) if (!this->Rename.empty()) { if (!this->FilesFromDir.empty()) { - this->FileCommand->SetError("INSTALL option RENAME may not be " - "combined with FILES_FROM_DIR."); + this->Status.SetError("INSTALL option RENAME may not be " + "combined with FILES_FROM_DIR."); return false; } if (this->InstallType != cmInstallType_FILES && this->InstallType != cmInstallType_PROGRAMS) { - this->FileCommand->SetError("INSTALL option RENAME may be used " - "only with FILES or PROGRAMS."); + this->Status.SetError("INSTALL option RENAME may be used " + "only with FILES or PROGRAMS."); return false; } if (this->Files.size() > 1) { - this->FileCommand->SetError("INSTALL option RENAME may be used " - "only with one file."); + this->Status.SetError("INSTALL option RENAME may be used " + "only with one file."); return false; } } @@ -134,9 +135,9 @@ bool cmFileInstaller::Parse(std::vector<std::string> const& args) if (((this->MessageAlways ? 1 : 0) + (this->MessageLazy ? 1 : 0) + (this->MessageNever ? 1 : 0)) > 1) { - this->FileCommand->SetError("INSTALL options MESSAGE_ALWAYS, " - "MESSAGE_LAZY, and MESSAGE_NEVER " - "are mutually exclusive."); + this->Status.SetError("INSTALL options MESSAGE_ALWAYS, " + "MESSAGE_LAZY, and MESSAGE_NEVER " + "are mutually exclusive."); return false; } @@ -213,7 +214,7 @@ bool cmFileInstaller::CheckKeyword(std::string const& arg) e << "INSTALL called with old-style " << arg << " argument. " << "This script was generated with an older version of CMake. " << "Re-run this cmake version on your build tree."; - this->FileCommand->SetError(e.str()); + this->Status.SetError(e.str()); this->Doing = DoingError; } else { return this->cmFileCopier::CheckKeyword(arg); @@ -257,7 +258,7 @@ bool cmFileInstaller::GetTargetTypeFromString(const std::string& stype) } else { std::ostringstream e; e << "Option TYPE given unknown value \"" << stype << "\"."; - this->FileCommand->SetError(e.str()); + this->Status.SetError(e.str()); return false; } return true; @@ -269,8 +270,8 @@ bool cmFileInstaller::HandleInstallDestination() // allow for / to be a valid destination if (destination.size() < 2 && destination != "/") { - this->FileCommand->SetError("called with inappropriate arguments. " - "No DESTINATION provided or ."); + this->Status.SetError("called with inappropriate arguments. " + "No DESTINATION provided or ."); return false; } @@ -300,7 +301,7 @@ bool cmFileInstaller::HandleInstallDestination() if (relative) { // This is relative path on unix or windows. Since we are doing // destdir, this case does not make sense. - this->FileCommand->SetError( + this->Status.SetError( "called with relative DESTINATION. This " "does not make sense when using DESTDIR. Specify " "absolute path or remove DESTDIR environment variable."); @@ -310,12 +311,12 @@ bool cmFileInstaller::HandleInstallDestination() if (ch2 == '/') { // looks like a network path. std::string message = - "called with network path DESTINATION. This " - "does not make sense when using DESTDIR. Specify local " - "absolute path or remove DESTDIR environment variable." - "\nDESTINATION=\n"; - message += destination; - this->FileCommand->SetError(message); + cmStrCat("called with network path DESTINATION. This " + "does not make sense when using DESTDIR. Specify local " + "absolute path or remove DESTDIR environment variable." + "\nDESTINATION=\n", + destination); + this->Status.SetError(message); return false; } } @@ -335,14 +336,14 @@ bool cmFileInstaller::HandleInstallDestination() if (!cmSystemTools::MakeDirectory(destination, default_dir_mode)) { std::string errstring = "cannot create directory: " + destination + ". Maybe need administrative privileges."; - this->FileCommand->SetError(errstring); + this->Status.SetError(errstring); return false; } } if (!cmSystemTools::FileIsDirectory(destination)) { std::string errstring = "INSTALL destination: " + destination + " is not a directory."; - this->FileCommand->SetError(errstring); + this->Status.SetError(errstring); return false; } } diff --git a/Source/cmFileInstaller.h b/Source/cmFileInstaller.h index 312529a..fd883ea 100644 --- a/Source/cmFileInstaller.h +++ b/Source/cmFileInstaller.h @@ -12,11 +12,11 @@ #include <string> #include <vector> -class cmFileCommand; +class cmExecutionStatus; struct cmFileInstaller : public cmFileCopier { - cmFileInstaller(cmFileCommand* command); + cmFileInstaller(cmExecutionStatus& status); ~cmFileInstaller() override; protected: diff --git a/Source/cmFileTimeCache.cxx b/Source/cmFileTimeCache.cxx index 24d6bf6..0d1dae5 100644 --- a/Source/cmFileTimeCache.cxx +++ b/Source/cmFileTimeCache.cxx @@ -38,7 +38,8 @@ bool cmFileTimeCache::Compare(std::string const& f1, std::string const& f2, int* result) { // Get the modification time for each file. - cmFileTime ft1, ft2; + cmFileTime ft1; + cmFileTime ft2; if (this->Load(f1, ft1) && this->Load(f2, ft2)) { // Compare the two modification times. *result = ft1.Compare(ft2); @@ -52,7 +53,8 @@ bool cmFileTimeCache::Compare(std::string const& f1, std::string const& f2, bool cmFileTimeCache::DifferS(std::string const& f1, std::string const& f2) { // Get the modification time for each file. - cmFileTime ft1, ft2; + cmFileTime ft1; + cmFileTime ft2; if (this->Load(f1, ft1) && this->Load(f2, ft2)) { // Compare the two modification times. return ft1.DifferS(ft2); diff --git a/Source/cmFileTimes.cxx b/Source/cmFileTimes.cxx index fd4f679..3824e9b 100644 --- a/Source/cmFileTimes.cxx +++ b/Source/cmFileTimes.cxx @@ -2,11 +2,12 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmFileTimes.h" -#include "cmAlgorithms.h" #include "cm_sys_stat.h" #include <utility> +#include "cm_memory.hxx" + #if defined(_WIN32) # include "cmSystemTools.h" # include <windows.h> diff --git a/Source/cmFileTimes.h b/Source/cmFileTimes.h index cbf0fe2..191d89e 100644 --- a/Source/cmFileTimes.h +++ b/Source/cmFileTimes.h @@ -5,7 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <memory> // IWYU pragma: keep +#include <memory> #include <string> /** \class cmFileTimes diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index e590802..191d7bb 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -13,6 +13,7 @@ #include "cmSearchPath.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmFindBase::cmFindBase() @@ -67,6 +68,9 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn) } this->AlreadyInCache = false; + // Find what search path locations have been enabled/disable + this->SelectDefaultSearchModes(); + // Find the current root path mode. this->SelectDefaultRootPathMode(); @@ -185,9 +189,7 @@ void cmFindBase::FillCMakeEnvironmentPath() cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeEnvironment]; // Add CMAKE_*_PATH environment variables - std::string var = "CMAKE_"; - var += this->CMakePathName; - var += "_PATH"; + std::string var = cmStrCat("CMAKE_", this->CMakePathName, "_PATH"); paths.AddEnvPrefixPath("CMAKE_PREFIX_PATH"); paths.AddEnvPath(var); @@ -219,9 +221,7 @@ void cmFindBase::FillCMakeVariablePath() // Add CMake variables of the same name as the previous environment // variables CMAKE_*_PATH to be used most of the time with -D // command line options - std::string var = "CMAKE_"; - var += this->CMakePathName; - var += "_PATH"; + std::string var = cmStrCat("CMAKE_", this->CMakePathName, "_PATH"); paths.AddCMakePrefixPath("CMAKE_PREFIX_PATH"); paths.AddCMakePath(var); @@ -253,9 +253,7 @@ void cmFindBase::FillCMakeSystemVariablePath() { cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeSystem]; - std::string var = "CMAKE_SYSTEM_"; - var += this->CMakePathName; - var += "_PATH"; + std::string var = cmStrCat("CMAKE_SYSTEM_", this->CMakePathName, "_PATH"); paths.AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH"); paths.AddCMakePath(var); @@ -320,7 +318,7 @@ bool cmFindBase::CheckForVariableInCache() this->Makefile->GetDefinition(this->VariableName)) { cmState* state = this->Makefile->GetState(); const char* cacheEntry = state->GetCacheEntryValue(this->VariableName); - bool found = !cmSystemTools::IsNOTFOUND(cacheValue); + bool found = !cmIsNOTFOUND(cacheValue); bool cached = cacheEntry != nullptr; if (found) { // If the user specifies the entry on the command line without a diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx index 954558f..9425f99 100644 --- a/Source/cmFindCommon.cxx +++ b/Source/cmFindCommon.cxx @@ -3,11 +3,13 @@ #include "cmFindCommon.h" #include <algorithm> +#include <array> #include <string.h> #include <utility> #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmFindCommon::PathGroup cmFindCommon::PathGroup::All("ALL"); @@ -90,8 +92,8 @@ void cmFindCommon::InitializeSearchPathGroups() void cmFindCommon::SelectDefaultRootPathMode() { // Check the policy variable for this find command type. - std::string findRootPathVar = "CMAKE_FIND_ROOT_PATH_MODE_"; - findRootPathVar += this->CMakePathName; + std::string findRootPathVar = + cmStrCat("CMAKE_FIND_ROOT_PATH_MODE_", this->CMakePathName); std::string rootPathMode = this->Makefile->GetSafeDefinition(findRootPathVar); if (rootPathMode == "NEVER") { @@ -144,6 +146,26 @@ void cmFindCommon::SelectDefaultMacMode() } } +void cmFindCommon::SelectDefaultSearchModes() +{ + const std::array<std::pair<bool&, std::string>, 5> search_paths = { + { { this->NoPackageRootPath, "CMAKE_FIND_USE_PACKAGE_ROOT_PATH" }, + { this->NoCMakePath, "CMAKE_FIND_USE_CMAKE_PATH" }, + { this->NoCMakeEnvironmentPath, + "CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH" }, + { this->NoSystemEnvironmentPath, + "CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH" }, + { this->NoCMakeSystemPath, "CMAKE_FIND_USE_CMAKE_SYSTEM_PATH" } } + }; + + for (auto& path : search_paths) { + const char* def = this->Makefile->GetDefinition(path.second); + if (def) { + path.first = !cmIsOn(def); + } + } +} + void cmFindCommon::RerootPaths(std::vector<std::string>& paths) { #if 0 @@ -174,7 +196,7 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) // Construct the list of path roots with no trailing slashes. std::vector<std::string> roots; if (rootPath) { - cmSystemTools::ExpandListArgument(rootPath, roots); + cmExpandList(rootPath, roots); } if (sysrootCompile) { roots.emplace_back(sysrootCompile); @@ -207,8 +229,7 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths) rootedDir = up; } else if (!up.empty() && up[0] != '~') { // Start with the new root. - rootedDir = r; - rootedDir += "/"; + rootedDir = cmStrCat(r, '/'); // Append the original path with its old root removed. rootedDir += cmSystemTools::SplitPathRootComponent(up); @@ -240,7 +261,7 @@ void cmFindCommon::GetIgnoredPaths(std::vector<std::string>& ignore) continue; } - cmSystemTools::ExpandListArgument(ignorePath, ignore); + cmExpandList(ignorePath, ignore); } for (std::string& i : ignore) { diff --git a/Source/cmFindCommon.h b/Source/cmFindCommon.h index 89ff174..d95eeb1 100644 --- a/Source/cmFindCommon.h +++ b/Source/cmFindCommon.h @@ -90,6 +90,9 @@ protected: /** Compute the current default bundle/framework search policy. */ void SelectDefaultMacMode(); + /** Compute the current default search modes based on global variables. */ + void SelectDefaultSearchModes(); + // Path arguments prior to path manipulation routines std::vector<std::string> UserHintsArgs; std::vector<std::string> UserGuessArgs; diff --git a/Source/cmFindFileCommand.h b/Source/cmFindFileCommand.h index 4309449..152b505 100644 --- a/Source/cmFindFileCommand.h +++ b/Source/cmFindFileCommand.h @@ -5,9 +5,10 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include "cmFindPathCommand.h" +#include "cm_memory.hxx" -class cmCommand; +#include "cmCommand.h" +#include "cmFindPathCommand.h" /** \class cmFindFileCommand * \brief Define a command to search for an executable program. @@ -24,7 +25,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmFindFileCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmFindFileCommand>(); + } }; #endif diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 73d602d..924a14e 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -13,6 +13,7 @@ #include "cmMakefile.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmExecutionStatus; @@ -237,8 +238,8 @@ cmFindLibraryHelper::cmFindLibraryHelper(cmMakefile* mf) this->Makefile->GetRequiredDefinition("CMAKE_FIND_LIBRARY_PREFIXES"); std::string const& suffixes_list = this->Makefile->GetRequiredDefinition("CMAKE_FIND_LIBRARY_SUFFIXES"); - cmSystemTools::ExpandListArgument(prefixes_list, this->Prefixes, true); - cmSystemTools::ExpandListArgument(suffixes_list, this->Suffixes, true); + cmExpandList(prefixes_list, this->Prefixes, true); + cmExpandList(suffixes_list, this->Suffixes, true); this->RegexFromList(this->PrefixRegexStr, this->Prefixes); this->RegexFromList(this->SuffixRegexStr, this->Suffixes); @@ -311,8 +312,7 @@ void cmFindLibraryHelper::AddName(std::string const& name) entry.Raw = name; // Build a regular expression to match library names. - std::string regex = "^"; - regex += this->PrefixRegexStr; + std::string regex = cmStrCat('^', this->PrefixRegexStr); this->RegexFromLiteral(regex, name); regex += this->SuffixRegexStr; if (this->OpenBSD) { @@ -348,8 +348,7 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path, // one cannot tell just from the library name whether it is a static // library or an import library). if (name.TryRaw) { - this->TestPath = path; - this->TestPath += name.Raw; + this->TestPath = cmStrCat(path, name.Raw); if (cmSystemTools::FileExists(this->TestPath, true)) { this->BestPath = cmSystemTools::CollapseFullPath(this->TestPath); cmSystemTools::ConvertToUnixSlashes(this->BestPath); @@ -374,8 +373,7 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path, std::string const& testName = origName; #endif if (name.Regex.find(testName)) { - this->TestPath = path; - this->TestPath += origName; + this->TestPath = cmStrCat(path, origName); if (!cmSystemTools::FileIsDirectory(this->TestPath)) { // This is a matching file. Check if it is better than the // best name found so far. Earlier prefixes are preferred, @@ -465,9 +463,7 @@ std::string cmFindLibraryCommand::FindFrameworkLibraryNamesPerDir() // Search for all names in each search path. for (std::string const& d : this->SearchPaths) { for (std::string const& n : this->Names) { - fwPath = d; - fwPath += n; - fwPath += ".framework"; + fwPath = cmStrCat(d, n, ".framework"); if (cmSystemTools::FileIsDirectory(fwPath)) { return cmSystemTools::CollapseFullPath(fwPath); } @@ -484,9 +480,7 @@ std::string cmFindLibraryCommand::FindFrameworkLibraryDirsPerName() // Search for each name in all search paths. for (std::string const& n : this->Names) { for (std::string const& d : this->SearchPaths) { - fwPath = d; - fwPath += n; - fwPath += ".framework"; + fwPath = cmStrCat(d, n, ".framework"); if (cmSystemTools::FileIsDirectory(fwPath)) { return cmSystemTools::CollapseFullPath(fwPath); } diff --git a/Source/cmFindLibraryCommand.h b/Source/cmFindLibraryCommand.h index fb8a700..af17d60 100644 --- a/Source/cmFindLibraryCommand.h +++ b/Source/cmFindLibraryCommand.h @@ -8,9 +8,11 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + +#include "cmCommand.h" #include "cmFindBase.h" -class cmCommand; class cmExecutionStatus; /** \class cmFindLibraryCommand @@ -27,7 +29,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmFindLibraryCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmFindLibraryCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 171fa77..9132760 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -13,12 +13,13 @@ #include <deque> #include <functional> #include <iterator> -#include <memory> // IWYU pragma: keep #include <sstream> #include <stdio.h> #include <string.h> #include <utility> +#include "cm_memory.hxx" + #include "cmAlgorithms.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -27,6 +28,7 @@ #include "cmSearchPath.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmVersion.h" #if defined(__HAIKU__) @@ -188,7 +190,12 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, } // Check if User Package Registry should be disabled - if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY")) { + // The `CMAKE_FIND_USE_PACKAGE_REGISTRY` has + // priority over the deprecated CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY + if (const char* def = + this->Makefile->GetDefinition("CMAKE_FIND_USE_PACKAGE_REGISTRY")) { + this->NoUserRegistry = !cmIsOn(def); + } else if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY")) { this->NoUserRegistry = true; } @@ -219,6 +226,9 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, this->SortDirection = strcmp(sd, "ASC") == 0 ? Asc : Dec; } + // Find what search path locations have been enabled/disable + this->SelectDefaultSearchModes(); + // Find the current root path mode. this->SelectDefaultRootPathMode(); @@ -398,19 +408,16 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, if (this->Version.empty() || components.empty()) { // Check whether we are recursing inside "Find<name>.cmake" within // another find_package(<name>) call. - std::string mod = this->Name; - mod += "_FIND_MODULE"; + std::string mod = cmStrCat(this->Name, "_FIND_MODULE"); if (this->Makefile->IsOn(mod)) { if (this->Version.empty()) { // Get version information from the outer call if necessary. // Requested version string. - std::string ver = this->Name; - ver += "_FIND_VERSION"; + std::string ver = cmStrCat(this->Name, "_FIND_VERSION"); this->Version = this->Makefile->GetSafeDefinition(ver); // Whether an exact version is required. - std::string exact = this->Name; - exact += "_FIND_VERSION_EXACT"; + std::string exact = cmStrCat(this->Name, "_FIND_VERSION_EXACT"); this->VersionExact = this->Makefile->IsOn(exact); } if (components.empty()) { @@ -448,8 +455,8 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, } } - std::string disableFindPackageVar = "CMAKE_DISABLE_FIND_PACKAGE_"; - disableFindPackageVar += this->Name; + std::string disableFindPackageVar = + cmStrCat("CMAKE_DISABLE_FIND_PACKAGE_", this->Name); if (this->Makefile->IsOn(disableFindPackageVar)) { if (this->Required) { std::ostringstream e; @@ -488,7 +495,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args, // NEW behavior is to honor the <pkg>_ROOT variables. std::string const rootVar = this->Name + "_ROOT"; if (const char* pkgRoot = this->Makefile->GetDefinition(rootVar)) { - cmSystemTools::ExpandListArgument(pkgRoot, rootPaths, false); + cmExpandList(pkgRoot, rootPaths, false); } cmSystemTools::GetPath(rootPaths, rootVar.c_str()); } break; @@ -579,8 +586,7 @@ bool cmFindPackageCommand::FindPackageUsingModuleMode() bool cmFindPackageCommand::FindPackageUsingConfigMode() { - this->Variable = this->Name; - this->Variable += "_DIR"; + this->Variable = cmStrCat(this->Name, "_DIR"); // Add the default name. if (this->Names.empty()) { @@ -590,12 +596,10 @@ bool cmFindPackageCommand::FindPackageUsingConfigMode() // Add the default configs. if (this->Configs.empty()) { for (std::string const& n : this->Names) { - std::string config = n; - config += "Config.cmake"; + std::string config = cmStrCat(n, "Config.cmake"); this->Configs.push_back(config); - config = cmSystemTools::LowerCase(n); - config += "-config.cmake"; + config = cmStrCat(cmSystemTools::LowerCase(n), "-config.cmake"); this->Configs.push_back(std::move(config)); } } @@ -624,24 +628,21 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components) if (this->Quiet) { // Tell the module that is about to be read that it should find // quietly. - std::string quietly = this->Name; - quietly += "_FIND_QUIETLY"; + std::string quietly = cmStrCat(this->Name, "_FIND_QUIETLY"); this->AddFindDefinition(quietly, "1"); } if (this->Required) { // Tell the module that is about to be read that it should report // a fatal error if the package is not found. - std::string req = this->Name; - req += "_FIND_REQUIRED"; + std::string req = cmStrCat(this->Name, "_FIND_REQUIRED"); this->AddFindDefinition(req, "1"); } if (!this->Version.empty()) { // Tell the module that is about to be read what version of the // package has been requested. - std::string ver = this->Name; - ver += "_FIND_VERSION"; + std::string ver = cmStrCat(this->Name, "_FIND_VERSION"); this->AddFindDefinition(ver, this->Version.c_str()); char buf[64]; sprintf(buf, "%u", this->VersionMajor); @@ -656,8 +657,7 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components) this->AddFindDefinition(ver + "_COUNT", buf); // Tell the module whether an exact version has been requested. - std::string exact = this->Name; - exact += "_FIND_VERSION_EXACT"; + std::string exact = cmStrCat(this->Name, "_FIND_VERSION_EXACT"); this->AddFindDefinition(exact, this->VersionExact ? "1" : "0"); } } @@ -671,7 +671,9 @@ void cmFindPackageCommand::AddFindDefinition(const std::string& var, } else { this->OriginalDefs[var].exists = false; } - this->Makefile->AddDefinition(var, val); + if (val) { + this->Makefile->AddDefinition(var, val); + } } void cmFindPackageCommand::RestoreFindDefinitions() @@ -679,7 +681,7 @@ void cmFindPackageCommand::RestoreFindDefinitions() for (auto const& i : this->OriginalDefs) { OriginalDef const& od = i.second; if (od.exists) { - this->Makefile->AddDefinition(i.first, od.value.c_str()); + this->Makefile->AddDefinition(i.first, od.value); } else { this->Makefile->RemoveDefinition(i.first); } @@ -688,9 +690,7 @@ void cmFindPackageCommand::RestoreFindDefinitions() bool cmFindPackageCommand::FindModule(bool& found) { - std::string module = "Find"; - module += this->Name; - module += ".cmake"; + std::string module = cmStrCat("Find", this->Name, ".cmake"); bool system = false; std::string mfile = this->Makefile->GetModulesFile(module, system); if (!mfile.empty()) { @@ -719,8 +719,7 @@ bool cmFindPackageCommand::FindModule(bool& found) // Load the module we found, and set "<name>_FIND_MODULE" to true // while inside it. found = true; - std::string var = this->Name; - var += "_FIND_MODULE"; + std::string var = cmStrCat(this->Name, "_FIND_MODULE"); this->Makefile->AddDefinition(var, "1"); bool result = this->ReadListFile(mfile, DoPolicyScope); this->Makefile->RemoveDefinition(var); @@ -734,19 +733,13 @@ bool cmFindPackageCommand::HandlePackageMode( { this->ConsideredConfigs.clear(); - // Support old capitalization behavior. - std::string upperDir = cmSystemTools::UpperCase(this->Name); - std::string upperFound = cmSystemTools::UpperCase(this->Name); - upperDir += "_DIR"; - upperFound += "_FOUND"; - // Try to find the config file. const char* def = this->Makefile->GetDefinition(this->Variable); // Try to load the config file if the directory is known bool fileFound = false; if (this->UseConfigFiles) { - if (!cmSystemTools::IsOff(def)) { + if (!cmIsOff(def)) { // Get the directory from the variable value. std::string dir = def; cmSystemTools::ConvertToUnixSlashes(dir); @@ -766,7 +759,7 @@ bool cmFindPackageCommand::HandlePackageMode( } // Search for the config file if it is not already found. - if (cmSystemTools::IsOff(def) || !fileFound) { + if (cmIsOff(def) || !fileFound) { fileFound = this->FindConfig(); } @@ -779,10 +772,8 @@ bool cmFindPackageCommand::HandlePackageMode( } } - std::string foundVar = this->Name; - foundVar += "_FOUND"; - std::string notFoundMessageVar = this->Name; - notFoundMessageVar += "_NOT_FOUND_MESSAGE"; + std::string foundVar = cmStrCat(this->Name, "_FOUND"); + std::string notFoundMessageVar = cmStrCat(this->Name, "_NOT_FOUND_MESSAGE"); std::string notFoundMessage; // If the directory for the config file was found, try to read the file. @@ -872,9 +863,8 @@ bool cmFindPackageCommand::HandlePackageMode( } else { std::string requestedVersionString; if (!this->Version.empty()) { - requestedVersionString = " (requested version "; - requestedVersionString += this->Version; - requestedVersionString += ")"; + requestedVersionString = + cmStrCat(" (requested version ", this->Version, ')'); } if (this->UseConfigFiles) { @@ -956,18 +946,17 @@ bool cmFindPackageCommand::HandlePackageMode( this->Makefile->AddDefinition(foundVar, found ? "1" : "0"); // Set a variable naming the configuration file that was found. - std::string fileVar = this->Name; - fileVar += "_CONFIG"; + std::string fileVar = cmStrCat(this->Name, "_CONFIG"); if (found) { - this->Makefile->AddDefinition(fileVar, this->FileFound.c_str()); + this->Makefile->AddDefinition(fileVar, this->FileFound); } else { this->Makefile->RemoveDefinition(fileVar); } - std::string consideredConfigsVar = this->Name; - consideredConfigsVar += "_CONSIDERED_CONFIGS"; - std::string consideredVersionsVar = this->Name; - consideredVersionsVar += "_CONSIDERED_VERSIONS"; + std::string consideredConfigsVar = + cmStrCat(this->Name, "_CONSIDERED_CONFIGS"); + std::string consideredVersionsVar = + cmStrCat(this->Name, "_CONSIDERED_VERSIONS"); std::string consideredConfigFiles; std::string consideredVersions; @@ -981,11 +970,9 @@ bool cmFindPackageCommand::HandlePackageMode( sep = ";"; } - this->Makefile->AddDefinition(consideredConfigsVar, - consideredConfigFiles.c_str()); + this->Makefile->AddDefinition(consideredConfigsVar, consideredConfigFiles); - this->Makefile->AddDefinition(consideredVersionsVar, - consideredVersions.c_str()); + this->Makefile->AddDefinition(consideredVersionsVar, consideredVersions); return result; } @@ -1031,9 +1018,8 @@ bool cmFindPackageCommand::FindConfig() init = this->Variable + "-NOTFOUND"; } std::string help = - "The directory containing a CMake configuration file for "; - help += this->Name; - help += "."; + cmStrCat("The directory containing a CMake configuration file for ", + this->Name, '.'); // We force the value since we do not get here if it was already set. this->Makefile->AddCacheDefinition(this->Variable, init.c_str(), help.c_str(), cmStateEnums::PATH, true); @@ -1080,9 +1066,7 @@ bool cmFindPackageCommand::ReadListFile(const std::string& f, if (this->Makefile->ReadDependentFile(f, noPolicyScope)) { return true; } - std::string e = "Error reading CMake code from \""; - e += f; - e += "\"."; + std::string e = cmStrCat("Error reading CMake code from \"", f, "\"."); this->SetError(e); return false; } @@ -1095,7 +1079,7 @@ void cmFindPackageCommand::AppendToFoundProperty(bool found) if (foundProp && *foundProp) { std::string tmp = foundProp; - cmSystemTools::ExpandListArgument(tmp, foundContents, false); + cmExpandList(tmp, foundContents, false); std::vector<std::string>::iterator nameIt = std::find(foundContents.begin(), foundContents.end(), this->Name); if (nameIt != foundContents.end()) { @@ -1109,7 +1093,7 @@ void cmFindPackageCommand::AppendToFoundProperty(bool found) if (notFoundProp && *notFoundProp) { std::string tmp = notFoundProp; - cmSystemTools::ExpandListArgument(tmp, notFoundContents, false); + cmExpandList(tmp, notFoundContents, false); std::vector<std::string>::iterator nameIt = std::find(notFoundContents.begin(), notFoundContents.end(), this->Name); if (nameIt != notFoundContents.end()) { @@ -1134,45 +1118,38 @@ void cmFindPackageCommand::AppendToFoundProperty(bool found) void cmFindPackageCommand::AppendSuccessInformation() { { - std::string transitivePropName = "_CMAKE_"; - transitivePropName += this->Name + "_TRANSITIVE_DEPENDENCY"; + std::string transitivePropName = + cmStrCat("_CMAKE_", this->Name, "_TRANSITIVE_DEPENDENCY"); this->Makefile->GetState()->SetGlobalProperty(transitivePropName, "False"); } - std::string found = this->Name; - found += "_FOUND"; + std::string found = cmStrCat(this->Name, "_FOUND"); std::string upperFound = cmSystemTools::UpperCase(found); const char* upperResult = this->Makefile->GetDefinition(upperFound); const char* result = this->Makefile->GetDefinition(found); - bool packageFound = - ((cmSystemTools::IsOn(result)) || (cmSystemTools::IsOn(upperResult))); + bool packageFound = ((cmIsOn(result)) || (cmIsOn(upperResult))); this->AppendToFoundProperty(packageFound); // Record whether the find was quiet or not, so this can be used // e.g. in FeatureSummary.cmake - std::string quietInfoPropName = "_CMAKE_"; - quietInfoPropName += this->Name; - quietInfoPropName += "_QUIET"; + std::string quietInfoPropName = cmStrCat("_CMAKE_", this->Name, "_QUIET"); this->Makefile->GetState()->SetGlobalProperty( quietInfoPropName, this->Quiet ? "TRUE" : "FALSE"); // set a global property to record the required version of this package - std::string versionInfoPropName = "_CMAKE_"; - versionInfoPropName += this->Name; - versionInfoPropName += "_REQUIRED_VERSION"; + std::string versionInfoPropName = + cmStrCat("_CMAKE_", this->Name, "_REQUIRED_VERSION"); std::string versionInfo; if (!this->Version.empty()) { - versionInfo = this->VersionExact ? "==" : ">="; - versionInfo += " "; - versionInfo += this->Version; + versionInfo = + cmStrCat(this->VersionExact ? "==" : ">=", ' ', this->Version); } this->Makefile->GetState()->SetGlobalProperty(versionInfoPropName, versionInfo.c_str()); if (this->Required) { - std::string requiredInfoPropName = "_CMAKE_"; - requiredInfoPropName += this->Name; - requiredInfoPropName += "_TYPE"; + std::string requiredInfoPropName = + cmStrCat("_CMAKE_", this->Name, "_TYPE"); this->Makefile->GetState()->SetGlobalProperty(requiredInfoPropName, "REQUIRED"); } @@ -1282,9 +1259,7 @@ void cmFindPackageCommand::FillPrefixesUserRegistry() char dir[B_PATH_NAME_LENGTH]; if (find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, dir, sizeof(dir)) == B_OK) { - std::string fname = dir; - fname += "/cmake/packages/"; - fname += Name; + std::string fname = cmStrCat(dir, "/cmake/packages/", Name); this->LoadPackageRegistryDir(fname, this->LabeledPaths[PathLabel::UserRegistry]); } @@ -1425,9 +1400,7 @@ void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir, std::string fname; for (unsigned long i = 0; i < files.GetNumberOfFiles(); ++i) { - fname = dir; - fname += "/"; - fname += files.GetFile(i); + fname = cmStrCat(dir, '/', files.GetFile(i)); if (!cmSystemTools::FileIsDirectory(fname)) { // Hold this file hostage until it behaves. @@ -1542,9 +1515,7 @@ bool cmFindPackageCommand::FindConfigFile(std::string const& dir, } for (std::string const& c : this->Configs) { - file = dir; - file += "/"; - file += c; + file = cmStrCat(dir, '/', c); if (this->DebugMode) { fprintf(stderr, "Checking file [%s]\n", file.c_str()); } @@ -1570,16 +1541,14 @@ bool cmFindPackageCommand::CheckVersion(std::string const& config_file) std::string version_file_base = config_file.substr(0, pos); // Look for foo-config-version.cmake - std::string version_file = version_file_base; - version_file += "-version.cmake"; + std::string version_file = cmStrCat(version_file_base, "-version.cmake"); if (!haveResult && cmSystemTools::FileExists(version_file, true)) { result = this->CheckVersionFile(version_file, version); haveResult = true; } // Look for fooConfigVersion.cmake - version_file = version_file_base; - version_file += "Version.cmake"; + version_file = cmStrCat(version_file_base, "Version.cmake"); if (!haveResult && cmSystemTools::FileExists(version_file, true)) { result = this->CheckVersionFile(version_file, version); haveResult = true; @@ -1614,8 +1583,8 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file, this->Makefile->RemoveDefinition("PACKAGE_VERSION_EXACT"); // Set the input variables. - this->Makefile->AddDefinition("PACKAGE_FIND_NAME", this->Name.c_str()); - this->Makefile->AddDefinition("PACKAGE_FIND_VERSION", this->Version.c_str()); + this->Makefile->AddDefinition("PACKAGE_FIND_NAME", this->Name); + this->Makefile->AddDefinition("PACKAGE_FIND_VERSION", this->Version); char buf[64]; sprintf(buf, "%u", this->VersionMajor); this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_MAJOR", buf); @@ -1687,12 +1656,11 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file, void cmFindPackageCommand::StoreVersionFound() { // Store the whole version string. - std::string ver = this->Name; - ver += "_VERSION"; + std::string ver = cmStrCat(this->Name, "_VERSION"); if (this->VersionFound.empty()) { this->Makefile->RemoveDefinition(ver); } else { - this->Makefile->AddDefinition(ver, this->VersionFound.c_str()); + this->Makefile->AddDefinition(ver, this->VersionFound); } // Store the version components. @@ -2036,8 +2004,7 @@ private: bool Search(std::string const& parent, cmFileList& lister) override { // Glob the set of matching files. - std::string expr = parent; - expr += this->Pattern; + std::string expr = cmStrCat(parent, this->Pattern); cmsys::Glob g; if (!g.FindFiles(expr)) { return false; diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index 316ca0f..f6645ae 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -3,6 +3,7 @@ #ifndef cmFindPackageCommand_h #define cmFindPackageCommand_h +#include "cmCommand.h" #include "cmConfigure.h" // IWYU pragma: keep #include "cmPolicies.h" @@ -14,6 +15,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + // IWYU insists we should forward-declare instead of including <functional>, // but we cannot forward-declare reliably because some C++ standard libraries // put the template in an inline namespace. @@ -27,7 +30,6 @@ namespace std { #include "cmFindCommon.h" -class cmCommand; class cmExecutionStatus; class cmSearchPath; @@ -65,7 +67,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmFindPackageCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmFindPackageCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx index 38ff2ed..41f5e51 100644 --- a/Source/cmFindPathCommand.cxx +++ b/Source/cmFindPathCommand.cxx @@ -6,6 +6,7 @@ #include "cmMakefile.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmExecutionStatus; @@ -88,12 +89,8 @@ std::string cmFindPathCommand::FindHeaderInFramework(std::string const& file, frameWorkName.clear(); } if (!frameWorkName.empty()) { - std::string fpath = dir; - fpath += frameWorkName; - fpath += ".framework"; - std::string intPath = fpath; - intPath += "/Headers/"; - intPath += fileName; + std::string fpath = cmStrCat(dir, frameWorkName, ".framework"); + std::string intPath = cmStrCat(fpath, "/Headers/", fileName); if (cmSystemTools::FileExists(intPath)) { if (this->IncludeFileInPath) { return intPath; @@ -104,9 +101,7 @@ std::string cmFindPathCommand::FindHeaderInFramework(std::string const& file, } // if it is not found yet or not a framework header, then do a glob search // for all frameworks in the directory: dir/*.framework/Headers/<file> - std::string glob = dir; - glob += "*.framework/Headers/"; - glob += file; + std::string glob = cmStrCat(dir, "*.framework/Headers/", file); cmsys::Glob globIt; globIt.FindFiles(glob); std::vector<std::string> files = globIt.GetFiles(); @@ -126,8 +121,7 @@ std::string cmFindPathCommand::FindNormalHeader() std::string tryPath; for (std::string const& n : this->Names) { for (std::string const& sp : this->SearchPaths) { - tryPath = sp; - tryPath += n; + tryPath = cmStrCat(sp, n); if (cmSystemTools::FileExists(tryPath)) { if (this->IncludeFileInPath) { return tryPath; diff --git a/Source/cmFindPathCommand.h b/Source/cmFindPathCommand.h index cb0db4c..89e2cef 100644 --- a/Source/cmFindPathCommand.h +++ b/Source/cmFindPathCommand.h @@ -8,9 +8,11 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + +#include "cmCommand.h" #include "cmFindBase.h" -class cmCommand; class cmExecutionStatus; /** \class cmFindPathCommand @@ -27,7 +29,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmFindPathCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmFindPathCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index 782f746..a2db65c 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -4,6 +4,7 @@ #include "cmMakefile.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmExecutionStatus; @@ -71,11 +72,10 @@ struct cmFindProgramHelper bool CheckDirectoryForName(std::string const& path, std::string const& name) { for (std::string const& ext : this->Extensions) { - if (!ext.empty() && cmSystemTools::StringEndsWith(name, ext.c_str())) { + if (!ext.empty() && cmHasSuffix(name, ext)) { continue; } - this->TestNameExt = name; - this->TestNameExt += ext; + this->TestNameExt = cmStrCat(name, ext); this->TestPath = cmSystemTools::CollapseFullPath(this->TestNameExt, path); diff --git a/Source/cmFindProgramCommand.h b/Source/cmFindProgramCommand.h index 147936c..40e455e 100644 --- a/Source/cmFindProgramCommand.h +++ b/Source/cmFindProgramCommand.h @@ -8,9 +8,11 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + +#include "cmCommand.h" #include "cmFindBase.h" -class cmCommand; class cmExecutionStatus; /** \class cmFindProgramCommand @@ -28,7 +30,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmFindProgramCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmFindProgramCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index 08003eb..f0633aa 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -2,21 +2,50 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmForEachCommand.h" -#include <memory> // IWYU pragma: keep #include <sstream> #include <stdio.h> #include <stdlib.h> +#include <utility> + +#include "cm_memory.hxx" +#include "cm_static_string_view.hxx" +#include "cm_string_view.hxx" -#include "cmAlgorithms.h" #include "cmExecutionStatus.h" +#include "cmFunctionBlocker.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmRange.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" +namespace { +bool HandleInMode(std::vector<std::string> const& args, cmMakefile& makefile); + +class cmForEachFunctionBlocker : public cmFunctionBlocker +{ +public: + cmForEachFunctionBlocker(cmMakefile* mf); + ~cmForEachFunctionBlocker() override; + + cm::string_view StartCommandName() const override { return "foreach"_s; } + cm::string_view EndCommandName() const override { return "endforeach"_s; } + + bool ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile& mf) const override; + + bool Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& inStatus) override; + + std::vector<std::string> Args; + +private: + cmMakefile* Makefile; +}; + cmForEachFunctionBlocker::cmForEachFunctionBlocker(cmMakefile* mf) : Makefile(mf) - , Depth(0) { this->Makefile->PushLoopBlock(); } @@ -26,102 +55,71 @@ cmForEachFunctionBlocker::~cmForEachFunctionBlocker() this->Makefile->PopLoopBlock(); } -bool cmForEachFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, - cmMakefile& mf, - cmExecutionStatus& inStatus) +bool cmForEachFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile& mf) const { - if (lff.Name.Lower == "foreach") { - // record the number of nested foreach commands - this->Depth++; - } else if (lff.Name.Lower == "endforeach") { - // if this is the endofreach for this statement - if (!this->Depth) { - // Remove the function blocker for this scope or bail. - std::unique_ptr<cmFunctionBlocker> fb( - mf.RemoveFunctionBlocker(this, lff)); - if (!fb) { - return false; - } + std::vector<std::string> expandedArguments; + mf.ExpandArguments(lff.Arguments, expandedArguments); + return expandedArguments.empty() || expandedArguments[0] == this->Args[0]; +} - // at end of for each execute recorded commands - // store the old value - std::string oldDef; - if (mf.GetDefinition(this->Args[0])) { - oldDef = mf.GetDefinition(this->Args[0]); - } +bool cmForEachFunctionBlocker::Replay( + std::vector<cmListFileFunction> functions, cmExecutionStatus& inStatus) +{ + cmMakefile& mf = inStatus.GetMakefile(); + // at end of for each execute recorded commands + // store the old value + std::string oldDef; + if (mf.GetDefinition(this->Args[0])) { + oldDef = mf.GetDefinition(this->Args[0]); + } - for (std::string const& arg : cmMakeRange(this->Args).advance(1)) { - // set the variable to the loop value - mf.AddDefinition(this->Args[0], arg.c_str()); - // Invoke all the functions that were collected in the block. - cmExecutionStatus status; - for (cmListFileFunction const& func : this->Functions) { - status.Clear(); - mf.ExecuteCommand(func, status); - if (status.GetReturnInvoked()) { - inStatus.SetReturnInvoked(); - // restore the variable to its prior value - mf.AddDefinition(this->Args[0], oldDef.c_str()); - return true; - } - if (status.GetBreakInvoked()) { - // restore the variable to its prior value - mf.AddDefinition(this->Args[0], oldDef.c_str()); - return true; - } - if (status.GetContinueInvoked()) { - break; - } - if (cmSystemTools::GetFatalErrorOccured()) { - return true; - } - } + for (std::string const& arg : cmMakeRange(this->Args).advance(1)) { + // set the variable to the loop value + mf.AddDefinition(this->Args[0], arg); + // Invoke all the functions that were collected in the block. + for (cmListFileFunction const& func : functions) { + cmExecutionStatus status(mf); + mf.ExecuteCommand(func, status); + if (status.GetReturnInvoked()) { + inStatus.SetReturnInvoked(); + // restore the variable to its prior value + mf.AddDefinition(this->Args[0], oldDef); + return true; + } + if (status.GetBreakInvoked()) { + // restore the variable to its prior value + mf.AddDefinition(this->Args[0], oldDef); + return true; + } + if (status.GetContinueInvoked()) { + break; + } + if (cmSystemTools::GetFatalErrorOccured()) { + return true; } - - // restore the variable to its prior value - mf.AddDefinition(this->Args[0], oldDef.c_str()); - return true; } - // close out a nested foreach - this->Depth--; } - // record the command - this->Functions.push_back(lff); - - // always return true + // restore the variable to its prior value + mf.AddDefinition(this->Args[0], oldDef); return true; } - -bool cmForEachFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, - cmMakefile& mf) -{ - if (lff.Name.Lower == "endforeach") { - std::vector<std::string> expandedArguments; - mf.ExpandArguments(lff.Arguments, expandedArguments); - // if the endforeach has arguments then make sure - // they match the begin foreach arguments - if ((expandedArguments.empty() || - (expandedArguments[0] == this->Args[0]))) { - return true; - } - } - return false; } -bool cmForEachCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmForEachCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } if (args.size() > 1 && args[1] == "IN") { - return this->HandleInMode(args); + return HandleInMode(args, status.GetMakefile()); } // create a function blocker - auto f = cm::make_unique<cmForEachFunctionBlocker>(this->Makefile); + auto fb = cm::make_unique<cmForEachFunctionBlocker>(&status.GetMakefile()); if (args.size() > 1) { if (args[1] == "RANGE") { int start = 0; @@ -151,7 +149,7 @@ bool cmForEachCommand::InitialPass(std::vector<std::string> const& args, std::ostringstream str; str << "called with incorrect range specification: start "; str << start << ", stop " << stop << ", step " << step; - this->SetError(str.str()); + status.SetError(str.str()); return false; } std::vector<std::string> range; @@ -168,23 +166,23 @@ bool cmForEachCommand::InitialPass(std::vector<std::string> const& args, break; } } - f->Args = range; + fb->Args = range; } else { - f->Args = args; + fb->Args = args; } } else { - f->Args = args; + fb->Args = args; } - this->Makefile->AddFunctionBlocker(f.release()); + status.GetMakefile().AddFunctionBlocker(std::move(fb)); return true; } -bool cmForEachCommand::HandleInMode(std::vector<std::string> const& args) +namespace { +bool HandleInMode(std::vector<std::string> const& args, cmMakefile& makefile) { - std::unique_ptr<cmForEachFunctionBlocker> f( - new cmForEachFunctionBlocker(this->Makefile)); - f->Args.push_back(args[0]); + auto fb = cm::make_unique<cmForEachFunctionBlocker>(&makefile); + fb->Args.push_back(args[0]); enum Doing { @@ -195,26 +193,27 @@ bool cmForEachCommand::HandleInMode(std::vector<std::string> const& args) Doing doing = DoingNone; for (unsigned int i = 2; i < args.size(); ++i) { if (doing == DoingItems) { - f->Args.push_back(args[i]); + fb->Args.push_back(args[i]); } else if (args[i] == "LISTS") { doing = DoingLists; } else if (args[i] == "ITEMS") { doing = DoingItems; } else if (doing == DoingLists) { - const char* value = this->Makefile->GetDefinition(args[i]); + const char* value = makefile.GetDefinition(args[i]); if (value && *value) { - cmSystemTools::ExpandListArgument(value, f->Args, true); + cmExpandList(value, fb->Args, true); } } else { std::ostringstream e; e << "Unknown argument:\n" << " " << args[i] << "\n"; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + makefile.IssueMessage(MessageType::FATAL_ERROR, e.str()); return true; } } - this->Makefile->AddFunctionBlocker(f.release()); // TODO: pass unique_ptr + makefile.AddFunctionBlocker(std::move(fb)); return true; } +} diff --git a/Source/cmForEachCommand.h b/Source/cmForEachCommand.h index 5131a4f..1feb965 100644 --- a/Source/cmForEachCommand.h +++ b/Source/cmForEachCommand.h @@ -8,48 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" -#include "cmFunctionBlocker.h" -#include "cmListFileCache.h" - class cmExecutionStatus; -class cmMakefile; - -class cmForEachFunctionBlocker : public cmFunctionBlocker -{ -public: - cmForEachFunctionBlocker(cmMakefile* mf); - ~cmForEachFunctionBlocker() override; - bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf, - cmExecutionStatus&) override; - bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override; - - std::vector<std::string> Args; - std::vector<cmListFileFunction> Functions; - -private: - cmMakefile* Makefile; - int Depth; -}; /// Starts foreach() ... endforeach() block -class cmForEachCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmForEachCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - bool HandleInMode(std::vector<std::string> const& args); -}; - +bool cmForEachCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx index e8b1da8..ad377de 100644 --- a/Source/cmFortranParserImpl.cxx +++ b/Source/cmFortranParserImpl.cxx @@ -1,6 +1,8 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmFortranParser.h" + +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include <assert.h> @@ -22,9 +24,7 @@ bool cmFortranParser_s::FindIncludeFile(const char* dir, } // Check for the file in the directory containing the including // file. - std::string fullName = dir; - fullName += "/"; - fullName += includeName; + std::string fullName = cmStrCat(dir, '/', includeName); if (cmSystemTools::FileExists(fullName, true)) { fileName = fullName; return true; @@ -32,9 +32,7 @@ bool cmFortranParser_s::FindIncludeFile(const char* dir, // Search the include path for the file. for (std::string const& i : this->IncludePath) { - fullName = i; - fullName += "/"; - fullName += includeName; + fullName = cmStrCat(i, '/', includeName); if (cmSystemTools::FileExists(fullName, true)) { fileName = fullName; return true; diff --git a/Source/cmFunctionBlocker.cxx b/Source/cmFunctionBlocker.cxx new file mode 100644 index 0000000..5778a71 --- /dev/null +++ b/Source/cmFunctionBlocker.cxx @@ -0,0 +1,46 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmFunctionBlocker.h" + +#include <cassert> +#include <sstream> +#include <utility> + +#include "cmExecutionStatus.h" +#include "cmMakefile.h" +#include "cmMessageType.h" + +bool cmFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, + cmExecutionStatus& status) +{ + if (lff.Name.Lower == this->StartCommandName()) { + this->ScopeDepth++; + } else if (lff.Name.Lower == this->EndCommandName()) { + this->ScopeDepth--; + if (this->ScopeDepth == 0U) { + cmMakefile& mf = status.GetMakefile(); + auto self = mf.RemoveFunctionBlocker(); + assert(self.get() == this); + + if (!this->ArgumentsMatch(lff, mf)) { + cmListFileContext const& lfc = this->GetStartingContext(); + cmListFileContext closingContext = + cmListFileContext::FromCommandContext(lff, lfc.FilePath); + std::ostringstream e; + /* clang-format off */ + e << "A logical block opening on the line\n" + << " " << lfc << "\n" + << "closes on the line\n" + << " " << closingContext << "\n" + << "with mis-matching arguments."; + /* clang-format on */ + mf.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); + } + + return this->Replay(std::move(this->Functions), status); + } + } + + this->Functions.push_back(lff); + return true; +} diff --git a/Source/cmFunctionBlocker.h b/Source/cmFunctionBlocker.h index cd6b05d..87bdccd 100644 --- a/Source/cmFunctionBlocker.h +++ b/Source/cmFunctionBlocker.h @@ -3,6 +3,12 @@ #ifndef cmFunctionBlocker_h #define cmFunctionBlocker_h +#include "cmConfigure.h" // IWYU pragma: keep + +#include <vector> + +#include "cm_string_view.hxx" + #include "cmListFileCache.h" class cmExecutionStatus; @@ -14,17 +20,8 @@ public: /** * should a function be blocked */ - virtual bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf, - cmExecutionStatus& status) = 0; - - /** - * should this function blocker be removed, useful when one function adds a - * blocker and another must remove it - */ - virtual bool ShouldRemove(const cmListFileFunction&, cmMakefile&) - { - return false; - } + bool IsFunctionBlocked(cmListFileFunction const& lff, + cmExecutionStatus& status); virtual ~cmFunctionBlocker() = default; @@ -39,7 +36,19 @@ public: } private: + virtual cm::string_view StartCommandName() const = 0; + virtual cm::string_view EndCommandName() const = 0; + + virtual bool ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile& mf) const = 0; + + virtual bool Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& status) = 0; + +private: cmListFileContext StartingContext; + std::vector<cmListFileFunction> Functions; + unsigned int ScopeDepth = 1; }; #endif diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx index 9067a5f..9420541 100644 --- a/Source/cmFunctionCommand.cxx +++ b/Source/cmFunctionCommand.cxx @@ -3,88 +3,79 @@ #include "cmFunctionCommand.h" #include <sstream> +#include <utility> + +#include "cm_memory.hxx" +#include "cm_static_string_view.hxx" +#include "cm_string_view.hxx" #include "cmAlgorithms.h" #include "cmExecutionStatus.h" +#include "cmFunctionBlocker.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmPolicies.h" #include "cmRange.h" #include "cmState.h" +#include "cmStringAlgorithms.h" +namespace { // define the class for function commands -class cmFunctionHelperCommand : public cmCommand +class cmFunctionHelperCommand { public: /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override - { - cmFunctionHelperCommand* newC = new cmFunctionHelperCommand; - // we must copy when we clone - newC->Args = this->Args; - newC->Functions = this->Functions; - newC->Policies = this->Policies; - newC->FilePath = this->FilePath; - return newC; - } - - /** * This is called when the command is first encountered in * the CMakeLists.txt file. */ - bool InvokeInitialPass(const std::vector<cmListFileArgument>& args, - cmExecutionStatus&) override; - - bool InitialPass(std::vector<std::string> const&, - cmExecutionStatus&) override - { - return false; - } + bool operator()(std::vector<cmListFileArgument> const& args, + cmExecutionStatus& inStatus) const; std::vector<std::string> Args; std::vector<cmListFileFunction> Functions; cmPolicies::PolicyMap Policies; std::string FilePath; }; +} -bool cmFunctionHelperCommand::InvokeInitialPass( - const std::vector<cmListFileArgument>& args, cmExecutionStatus& inStatus) +bool cmFunctionHelperCommand::operator()( + std::vector<cmListFileArgument> const& args, + cmExecutionStatus& inStatus) const { + cmMakefile& makefile = inStatus.GetMakefile(); + // Expand the argument list to the function. std::vector<std::string> expandedArgs; - this->Makefile->ExpandArguments(args, expandedArgs); + makefile.ExpandArguments(args, expandedArgs); // make sure the number of arguments passed is at least the number // required by the signature if (expandedArgs.size() < this->Args.size() - 1) { - std::string errorMsg = - "Function invoked with incorrect arguments for function named: "; - errorMsg += this->Args[0]; - this->SetError(errorMsg); + std::string errorMsg = cmStrCat( + "Function invoked with incorrect arguments for function named: ", + this->Args[0]); + inStatus.SetError(errorMsg); return false; } - cmMakefile::FunctionPushPop functionScope(this->Makefile, this->FilePath, + cmMakefile::FunctionPushPop functionScope(&makefile, this->FilePath, this->Policies); // set the value of argc - std::ostringstream strStream; - strStream << expandedArgs.size(); - this->Makefile->AddDefinition("ARGC", strStream.str().c_str()); - this->Makefile->MarkVariableAsUsed("ARGC"); + makefile.AddDefinition("ARGC", std::to_string(expandedArgs.size())); + makefile.MarkVariableAsUsed("ARGC"); // set the values for ARGV0 ARGV1 ... for (unsigned int t = 0; t < expandedArgs.size(); ++t) { std::ostringstream tmpStream; tmpStream << "ARGV" << t; - this->Makefile->AddDefinition(tmpStream.str(), expandedArgs[t].c_str()); - this->Makefile->MarkVariableAsUsed(tmpStream.str()); + makefile.AddDefinition(tmpStream.str(), expandedArgs[t]); + makefile.MarkVariableAsUsed(tmpStream.str()); } // define the formal arguments for (unsigned int j = 1; j < this->Args.size(); ++j) { - this->Makefile->AddDefinition(this->Args[j], expandedArgs[j - 1].c_str()); + makefile.AddDefinition(this->Args[j], expandedArgs[j - 1]); } // define ARGV and ARGN @@ -92,17 +83,16 @@ bool cmFunctionHelperCommand::InvokeInitialPass( std::vector<std::string>::const_iterator eit = expandedArgs.begin() + (this->Args.size() - 1); std::string argnDef = cmJoin(cmMakeRange(eit, expandedArgs.end()), ";"); - this->Makefile->AddDefinition("ARGV", argvDef.c_str()); - this->Makefile->MarkVariableAsUsed("ARGV"); - this->Makefile->AddDefinition("ARGN", argnDef.c_str()); - this->Makefile->MarkVariableAsUsed("ARGN"); + makefile.AddDefinition("ARGV", argvDef); + makefile.MarkVariableAsUsed("ARGV"); + makefile.AddDefinition("ARGN", argnDef); + makefile.MarkVariableAsUsed("ARGN"); // Invoke all the functions that were collected in the block. // for each function for (cmListFileFunction const& func : this->Functions) { - cmExecutionStatus status; - if (!this->Makefile->ExecuteCommand(func, status) || - status.GetNestedError()) { + cmExecutionStatus status(makefile); + if (!makefile.ExecuteCommand(func, status) || status.GetNestedError()) { // The error message should have already included the call stack // so we do not need to report an error here. functionScope.Quiet(); @@ -118,66 +108,57 @@ bool cmFunctionHelperCommand::InvokeInitialPass( return true; } -bool cmFunctionFunctionBlocker::IsFunctionBlocked( - const cmListFileFunction& lff, cmMakefile& mf, cmExecutionStatus&) +class cmFunctionFunctionBlocker : public cmFunctionBlocker { - // record commands until we hit the ENDFUNCTION - // at the ENDFUNCTION call we shift gears and start looking for invocations - if (lff.Name.Lower == "function") { - this->Depth++; - } else if (lff.Name.Lower == "endfunction") { - // if this is the endfunction for this function then execute - if (!this->Depth) { - // create a new command and add it to cmake - cmFunctionHelperCommand* f = new cmFunctionHelperCommand(); - f->Args = this->Args; - f->Functions = this->Functions; - f->FilePath = this->GetStartingContext().FilePath; - mf.RecordPolicies(f->Policies); - mf.GetState()->AddScriptedCommand(this->Args[0], f); - // remove the function blocker now that the function is defined - mf.RemoveFunctionBlocker(this, lff); - return true; - } - // decrement for each nested function that ends - this->Depth--; - } +public: + cm::string_view StartCommandName() const override { return "function"_s; } + cm::string_view EndCommandName() const override { return "endfunction"_s; } - // if it wasn't an endfunction and we are not executing then we must be - // recording - this->Functions.push_back(lff); - return true; -} + bool ArgumentsMatch(cmListFileFunction const&, + cmMakefile& mf) const override; + + bool Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& status) override; -bool cmFunctionFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, - cmMakefile& mf) + std::vector<std::string> Args; +}; + +bool cmFunctionFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile& mf) const { - if (lff.Name.Lower == "endfunction") { - std::vector<std::string> expandedArguments; - mf.ExpandArguments(lff.Arguments, expandedArguments, - this->GetStartingContext().FilePath.c_str()); - // if the endfunction has arguments then make sure - // they match the ones in the opening function command - if ((expandedArguments.empty() || - (expandedArguments[0] == this->Args[0]))) { - return true; - } - } + std::vector<std::string> expandedArguments; + mf.ExpandArguments(lff.Arguments, expandedArguments, + this->GetStartingContext().FilePath.c_str()); + return expandedArguments.empty() || expandedArguments[0] == this->Args[0]; +} - return false; +bool cmFunctionFunctionBlocker::Replay( + std::vector<cmListFileFunction> functions, cmExecutionStatus& status) +{ + cmMakefile& mf = status.GetMakefile(); + // create a new command and add it to cmake + cmFunctionHelperCommand f; + f.Args = this->Args; + f.Functions = std::move(functions); + f.FilePath = this->GetStartingContext().FilePath; + mf.RecordPolicies(f.Policies); + mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f)); + return true; } -bool cmFunctionCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmFunctionCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } // create a function blocker - cmFunctionFunctionBlocker* f = new cmFunctionFunctionBlocker(); - cmAppend(f->Args, args); - this->Makefile->AddFunctionBlocker(f); + { + auto fb = cm::make_unique<cmFunctionFunctionBlocker>(); + cmAppend(fb->Args, args); + status.GetMakefile().AddFunctionBlocker(std::move(fb)); + } return true; } diff --git a/Source/cmFunctionCommand.h b/Source/cmFunctionCommand.h index 8b37df0..d6b549c 100644 --- a/Source/cmFunctionCommand.h +++ b/Source/cmFunctionCommand.h @@ -8,40 +8,10 @@ #include <string> #include <vector> -#include "cmCommand.h" -#include "cmFunctionBlocker.h" -#include "cmListFileCache.h" - class cmExecutionStatus; -class cmMakefile; - -class cmFunctionFunctionBlocker : public cmFunctionBlocker -{ -public: - bool IsFunctionBlocked(const cmListFileFunction&, cmMakefile& mf, - cmExecutionStatus&) override; - bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override; - - std::vector<std::string> Args; - std::vector<cmListFileFunction> Functions; - int Depth = 0; -}; /// Starts function() ... endfunction() block -class cmFunctionCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmFunctionCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmFunctionCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx index 2f47788..7475e9f 100644 --- a/Source/cmGeneratedFileStream.cxx +++ b/Source/cmGeneratedFileStream.cxx @@ -6,14 +6,14 @@ #include "cmSystemTools.h" -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) # include "cm_codecvt.hxx" # include "cm_zlib.h" #endif cmGeneratedFileStream::cmGeneratedFileStream(Encoding encoding) { -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP if (encoding != codecvt::None) { imbue(std::locale(getloc(), new codecvt(encoding))); } @@ -32,7 +32,7 @@ cmGeneratedFileStream::cmGeneratedFileStream(std::string const& name, cmSystemTools::Error("Cannot open file for write: " + this->TempName); cmSystemTools::ReportLastSystemError(""); } -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP if (encoding != codecvt::None) { imbue(std::locale(getloc(), new codecvt(encoding))); } @@ -169,7 +169,7 @@ bool cmGeneratedFileStreamBase::Close() return replaced; } -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP int cmGeneratedFileStreamBase::CompressFile(std::string const& oldname, std::string const& newname) { diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 175a26d..133a72b 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -3,7 +3,7 @@ #include "cmGeneratorExpression.h" #include "cmsys/RegularExpression.hxx" -#include <memory> // IWYU pragma: keep +#include <memory> #include <utility> #include "assert.h" @@ -13,6 +13,7 @@ #include "cmGeneratorExpressionEvaluator.h" #include "cmGeneratorExpressionLexer.h" #include "cmGeneratorExpressionParser.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmGeneratorExpression::cmGeneratorExpression(cmListFileBacktrace backtrace) @@ -294,7 +295,7 @@ void cmGeneratorExpression::Split(const std::string& input, preGenex = input.substr(startPos + 1, pos - startPos - 1); } if (!part.empty()) { - cmSystemTools::ExpandListArgument(part, output); + cmExpandList(part, output); } } pos += 2; @@ -327,7 +328,7 @@ void cmGeneratorExpression::Split(const std::string& input, lastPos = pos; } if (lastPos < input.size()) { - cmSystemTools::ExpandListArgument(input.substr(lastPos), output); + cmExpandList(input.substr(lastPos), output); } } diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index fd36c4b..ef76651 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -8,7 +8,7 @@ #include "cmListFileCache.h" #include <map> -#include <memory> // IWYU pragma: keep +#include <memory> #include <set> #include <string> #include <utility> diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 728f2a4..df2227f 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -2,12 +2,12 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGeneratorExpressionDAGChecker.h" -#include "cmAlgorithms.h" #include "cmGeneratorExpressionContext.h" #include "cmGeneratorExpressionEvaluator.h" #include "cmGeneratorTarget.h" #include "cmLocalGenerator.h" #include "cmMessageType.h" +#include "cmStringAlgorithms.h" #include "cmake.h" #include <sstream> @@ -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/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx index 326cb0e..11c2dcc 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.cxx +++ b/Source/cmGeneratorExpressionEvaluationFile.cxx @@ -3,7 +3,7 @@ #include "cmGeneratorExpressionEvaluationFile.h" #include "cmsys/FStream.hxx" -#include <memory> // IWYU pragma: keep +#include <memory> #include <sstream> #include <utility> diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h index 89a2390..06ebeac 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.h +++ b/Source/cmGeneratorExpressionEvaluationFile.h @@ -6,7 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <map> -#include <memory> // IWYU pragma: keep +#include <memory> #include <string> #include <vector> diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index a60c75c..667f4a0 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -19,10 +19,11 @@ #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" +#include "cmString.hxx" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cm_static_string_view.hxx" -#include "cm_string_view.hxx" #include "cmake.h" #include "cmsys/RegularExpression.hxx" @@ -33,7 +34,7 @@ #include <errno.h> #include <iterator> #include <map> -#include <memory> // IWYU pragma: keep +#include <memory> #include <set> #include <sstream> #include <stdlib.h> @@ -168,7 +169,7 @@ static const struct BoolNode : public cmGeneratorExpressionNode const GeneratorExpressionContent* /*content*/, cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override { - return !cmSystemTools::IsOff(parameters.front()) ? "1" : "0"; + return !cmIsOff(parameters.front()) ? "1" : "0"; } } boolNode; @@ -274,17 +275,18 @@ static const struct InListNode : public cmGeneratorExpressionNode const GeneratorExpressionContent* /*content*/, cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override { - std::vector<std::string> values, checkValues; + std::vector<std::string> values; + std::vector<std::string> checkValues; bool check = false; switch (context->LG->GetPolicyStatus(cmPolicies::CMP0085)) { case cmPolicies::WARN: if (parameters.front().empty()) { check = true; - cmSystemTools::ExpandListArgument(parameters[1], checkValues, true); + cmExpandList(parameters[1], checkValues, true); } CM_FALLTHROUGH; case cmPolicies::OLD: - cmSystemTools::ExpandListArgument(parameters[1], values); + cmExpandList(parameters[1], values); if (check && values != checkValues) { std::ostringstream e; e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0085) @@ -301,14 +303,11 @@ static const struct InListNode : public cmGeneratorExpressionNode case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::NEW: - cmSystemTools::ExpandListArgument(parameters[1], values, true); + cmExpandList(parameters[1], values, true); break; } - return std::find(values.cbegin(), values.cend(), parameters.front()) == - values.cend() - ? "0" - : "1"; + return cmContains(values, parameters.front()) ? "1" : "0"; } } inListNode; @@ -346,8 +345,9 @@ static const struct FilterNode : public cmGeneratorExpressionNode return {}; } - std::vector<std::string> values, result; - cmSystemTools::ExpandListArgument(parameters.front(), values, true); + std::vector<std::string> values; + std::vector<std::string> result; + cmExpandList(parameters.front(), values, true); std::copy_if(values.cbegin(), values.cend(), std::back_inserter(result), [&re, exclude](std::string const& input) { @@ -375,8 +375,7 @@ static const struct RemoveDuplicatesNode : public cmGeneratorExpressionNode "$<REMOVE_DUPLICATES:...> expression requires one parameter"); } - std::vector<std::string> values; - cmSystemTools::ExpandListArgument(parameters.front(), values, true); + std::vector<std::string> values = cmExpandedList(parameters.front(), true); auto valuesEnd = cmRemoveDuplicates(values); auto valuesBegin = values.cbegin(); @@ -684,10 +683,10 @@ struct CompilerIdNode : public cmGeneratorExpressionNode if (cmsysString_strcasecmp(param.c_str(), compilerId.c_str()) == 0) { switch (context->LG->GetPolicyStatus(cmPolicies::CMP0044)) { case cmPolicies::WARN: { - std::ostringstream e; - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0044); context->LG->GetCMakeInstance()->IssueMessage( - MessageType::AUTHOR_WARNING, e.str(), context->Backtrace); + MessageType::AUTHOR_WARNING, + cmPolicies::GetPolicyWarning(cmPolicies::CMP0044), + context->Backtrace); CM_FALLTHROUGH; } case cmPolicies::OLD: @@ -909,15 +908,13 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode // for this (possibly mapped) config. // Check if there is a proper config mapping for the tested config. std::vector<std::string> mappedConfigs; - std::string mapProp = "MAP_IMPORTED_CONFIG_"; - mapProp += cmSystemTools::UpperCase(context->Config); + std::string mapProp = cmStrCat( + "MAP_IMPORTED_CONFIG_", cmSystemTools::UpperCase(context->Config)); if (const char* mapValue = context->CurrentTarget->GetProperty(mapProp)) { - cmSystemTools::ExpandListArgument(cmSystemTools::UpperCase(mapValue), - mappedConfigs); - return std::find(mappedConfigs.begin(), mappedConfigs.end(), - cmSystemTools::UpperCase(parameters.front())) != - mappedConfigs.end() + cmExpandList(cmSystemTools::UpperCase(mapValue), mappedConfigs); + return cmContains(mappedConfigs, + cmSystemTools::UpperCase(parameters.front())) ? "1" : "0"; } @@ -941,8 +938,7 @@ static const struct JoinNode : public cmGeneratorExpressionNode const GeneratorExpressionContent* /*content*/, cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override { - std::vector<std::string> list; - cmSystemTools::ExpandListArgument(parameters.front(), list); + std::vector<std::string> list = cmExpandedList(parameters.front()); return cmJoin(list, parameters[1]); } } joinNode; @@ -1038,45 +1034,38 @@ static const struct CompileLanguageAndIdNode : public cmGeneratorExpressionNode } } languageAndIdNode; -#define TRANSITIVE_PROPERTY_NAME(PROPERTY) , "INTERFACE_" #PROPERTY - -static const char* targetPropertyTransitiveWhitelist[] = { - nullptr CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_NAME) -}; - -#undef TRANSITIVE_PROPERTY_NAME - -template <typename T> std::string getLinkedTargetsContent( - std::vector<T> const& libraries, cmGeneratorTarget const* target, - cmGeneratorTarget const* headTarget, cmGeneratorExpressionContext* context, - cmGeneratorExpressionDAGChecker* dagChecker, - const std::string& interfacePropertyName) -{ - std::string linkedTargetsContent; - std::string sep; - std::string depString; - for (T const& l : libraries) { - // Broken code can have a target in its own link interface. - // Don't follow such link interface entries so as not to create a - // self-referencing loop. - if (l.Target && l.Target != target) { - std::string uniqueName = - target->GetGlobalGenerator()->IndexGeneratorTargetUniquely(l.Target); - depString += sep + "$<TARGET_PROPERTY:" + std::move(uniqueName) + "," + - interfacePropertyName + ">"; - sep = ";"; - } - } - if (!depString.empty()) { - linkedTargetsContent = - cmGeneratorExpressionNode::EvaluateDependentExpression( - depString, target->GetLocalGenerator(), context, headTarget, target, - dagChecker); - } - linkedTargetsContent = - cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent); - return linkedTargetsContent; + cmGeneratorTarget const* target, std::string const& prop, + cmGeneratorExpressionContext* context, + cmGeneratorExpressionDAGChecker* dagChecker) +{ + std::string result; + if (cmLinkImplementationLibraries const* impl = + target->GetLinkImplementationLibraries(context->Config)) { + for (cmLinkImplItem const& lib : impl->Libraries) { + if (lib.Target) { + // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our + // caller's property and hand-evaluate it as if it were compiled. + // Create a context as cmCompiledGeneratorExpression::Evaluate does. + cmGeneratorExpressionContext libContext( + target->GetLocalGenerator(), context->Config, context->Quiet, target, + target, context->EvaluateForBuildsystem, lib.Backtrace, + context->Language); + std::string libResult = + lib.Target->EvaluateInterfaceProperty(prop, &libContext, dagChecker); + if (!libResult.empty()) { + if (result.empty()) { + result = std::move(libResult); + } else { + result.reserve(result.size() + 1 + libResult.size()); + result += ";"; + result += libResult; + } + } + } + } + } + return result; } static const struct TargetPropertyNode : public cmGeneratorExpressionNode @@ -1116,7 +1105,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode static cmsys::RegularExpression propertyNameValidator("^[A-Za-z0-9_]+$"); cmGeneratorTarget const* target = nullptr; - std::string targetName, propertyName; + std::string targetName; + std::string propertyName; if (parameters.size() == 2) { targetName = parameters[0]; @@ -1205,44 +1195,37 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode return target->GetLinkerLanguage(context->Config); } - cmGeneratorExpressionDAGChecker dagChecker( - context->Backtrace, target, propertyName, content, dagCheckerParent); + std::string interfacePropertyName; + bool isInterfaceProperty = false; - switch (dagChecker.Check()) { - case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: - dagChecker.ReportError(context, content->GetOriginalExpression()); - return std::string(); - case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: - // No error. We just skip cyclic references. - return std::string(); - case cmGeneratorExpressionDAGChecker::ALREADY_SEEN: - for (size_t i = 1; i < cm::size(targetPropertyTransitiveWhitelist); - ++i) { - if (targetPropertyTransitiveWhitelist[i] == propertyName) { - // No error. We're not going to find anything new here. - return std::string(); - } - } - case cmGeneratorExpressionDAGChecker::DAG: - break; - } +#define POPULATE_INTERFACE_PROPERTY_NAME(prop) \ + if (propertyName == #prop) { \ + interfacePropertyName = "INTERFACE_" #prop; \ + } else if (propertyName == "INTERFACE_" #prop) { \ + interfacePropertyName = "INTERFACE_" #prop; \ + isInterfaceProperty = true; \ + } else - std::string prop; - bool haveProp = false; - if (const char* p = target->GetProperty(propertyName)) { - prop = p; - haveProp = true; + CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(POPULATE_INTERFACE_PROPERTY_NAME) + // Note that the above macro terminates with an else + /* else */ if (cmHasLiteralPrefix(propertyName, "COMPILE_DEFINITIONS_")) { + cmPolicies::PolicyStatus polSt = + context->LG->GetPolicyStatus(cmPolicies::CMP0043); + if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) { + interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS"; + } } +#undef POPULATE_INTERFACE_PROPERTY_NAME + + bool evaluatingLinkLibraries = false; if (dagCheckerParent) { if (dagCheckerParent->EvaluatingGenexExpression() || dagCheckerParent->EvaluatingPICExpression()) { // No check required. } else if (dagCheckerParent->EvaluatingLinkLibraries()) { -#define TRANSITIVE_PROPERTY_COMPARE(PROPERTY) \ - (#PROPERTY == propertyName || "INTERFACE_" #PROPERTY == propertyName) || - if (CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME( - TRANSITIVE_PROPERTY_COMPARE) false) { // NOLINT(*) + evaluatingLinkLibraries = true; + if (!interfacePropertyName.empty()) { reportError( context, content->GetOriginalExpression(), "$<TARGET_PROPERTY:...> expression in link libraries " @@ -1250,69 +1233,47 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode "over the link libraries, creating a recursion."); return std::string(); } -#undef TRANSITIVE_PROPERTY_COMPARE - - if (!haveProp) { - return std::string(); - } } else { #define ASSERT_TRANSITIVE_PROPERTY_METHOD(METHOD) dagCheckerParent->METHOD() || - assert(CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD( ASSERT_TRANSITIVE_PROPERTY_METHOD) false); // NOLINT(clang-tidy) #undef ASSERT_TRANSITIVE_PROPERTY_METHOD } } - std::string linkedTargetsContent; - - std::string interfacePropertyName; - bool isInterfaceProperty = false; + if (isInterfaceProperty) { + return target->EvaluateInterfaceProperty(propertyName, context, + dagCheckerParent); + } -#define POPULATE_INTERFACE_PROPERTY_NAME(prop) \ - if (propertyName == #prop) { \ - interfacePropertyName = "INTERFACE_" #prop; \ - } else if (propertyName == "INTERFACE_" #prop) { \ - interfacePropertyName = "INTERFACE_" #prop; \ - isInterfaceProperty = true; \ - } else + cmGeneratorExpressionDAGChecker dagChecker( + context->Backtrace, target, propertyName, content, dagCheckerParent); - CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(POPULATE_INTERFACE_PROPERTY_NAME) - // Note that the above macro terminates with an else - /* else */ if (cmHasLiteralPrefix(propertyName, "COMPILE_DEFINITIONS_")) { - cmPolicies::PolicyStatus polSt = - context->LG->GetPolicyStatus(cmPolicies::CMP0043); - if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) { - interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS"; - } + switch (dagChecker.Check()) { + case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: + dagChecker.ReportError(context, content->GetOriginalExpression()); + return std::string(); + case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: + // No error. We just skip cyclic references. + return std::string(); + case cmGeneratorExpressionDAGChecker::ALREADY_SEEN: + // We handle transitive properties above. For non-transitive + // properties we accept repeats anyway. + case cmGeneratorExpressionDAGChecker::DAG: + break; } -#undef POPULATE_INTERFACE_PROPERTY_NAME - cmGeneratorTarget const* headTarget = - context->HeadTarget && isInterfaceProperty ? context->HeadTarget - : target; - if (isInterfaceProperty) { - if (cmLinkInterfaceLibraries const* iface = - target->GetLinkInterfaceLibraries(context->Config, headTarget, - true)) { - linkedTargetsContent = - getLinkedTargetsContent(iface->Libraries, target, headTarget, - context, &dagChecker, interfacePropertyName); - } - } else if (!interfacePropertyName.empty()) { - if (cmLinkImplementationLibraries const* impl = - target->GetLinkImplementationLibraries(context->Config)) { - linkedTargetsContent = - getLinkedTargetsContent(impl->Libraries, target, target, context, - &dagChecker, interfacePropertyName); - } + std::string result; + bool haveProp = false; + if (const char* p = target->GetProperty(propertyName)) { + result = p; + haveProp = true; + } else if (evaluatingLinkLibraries) { + return std::string(); } - if (!haveProp) { - if (target->IsImported() || - target->GetType() == cmStateEnums::INTERFACE_LIBRARY) { - return linkedTargetsContent; - } + if (!haveProp && !target->IsImported() && + target->GetType() != cmStateEnums::INTERFACE_LIBRARY) { if (target->IsLinkInterfaceDependentBoolProperty(propertyName, context->Config)) { context->HadContextSensitiveCondition = true; @@ -1345,8 +1306,6 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode context->Config); return propContent ? propContent : ""; } - - return linkedTargetsContent; } if (!target->IsImported() && dagCheckerParent && @@ -1368,15 +1327,17 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode return propContent ? propContent : ""; } } + if (!interfacePropertyName.empty()) { - std::string result = this->EvaluateDependentExpression( - prop, context->LG, context, headTarget, target, &dagChecker); + result = this->EvaluateDependentExpression(result, context->LG, context, + target, target, &dagChecker); + std::string linkedTargetsContent = getLinkedTargetsContent( + target, interfacePropertyName, context, &dagChecker); if (!linkedTargetsContent.empty()) { result += (result.empty() ? "" : ";") + linkedTargetsContent; } - return result; } - return prop; + return result; } } targetPropertyNode; @@ -1456,7 +1417,7 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode const char* imp = nullptr; std::string suffix; if (gt->Target->GetMappedConfig(context->Config, &loc, &imp, suffix)) { - cmSystemTools::ExpandListArgument(loc, objects); + cmExpandList(loc, objects); } context->HadContextSensitiveCondition = true; } else { @@ -1476,7 +1437,7 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode } for (std::string& o : objects) { - o = obj_dir + o; + o = cmStrCat(obj_dir, o); } } @@ -1534,8 +1495,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode reportError(context, content->GetOriginalExpression(), error); return std::string(); } - cmSystemTools::ExpandListArgument(featuresKnown, - availableFeatures[lang]); + cmExpandList(featuresKnown, availableFeatures[lang]); } } @@ -1547,8 +1507,7 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode const char* standardDefault = context->LG->GetMakefile()->GetDefinition( "CMAKE_" + lit.first + "_STANDARD_DEFAULT"); for (std::string const& it : lit.second) { - if (std::find(langAvailable.begin(), langAvailable.end(), it) == - langAvailable.end()) { + if (!cmContains(langAvailable, it)) { return "0"; } if (standardDefault && !*standardDefault) { @@ -1734,9 +1693,8 @@ struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag> "SHARED libraries."); return std::string(); } - std::string result = target->GetDirectory(context->Config); - result += "/"; - result += target->GetSOName(context->Config); + std::string result = cmStrCat(target->GetDirectory(context->Config), '/', + target->GetSOName(context->Config)); return result; } }; @@ -1775,9 +1733,8 @@ struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag> return std::string(); } - std::string result = target->GetPDBDirectory(context->Config); - result += "/"; - result += target->GetPDBName(context->Config); + std::string result = cmStrCat(target->GetPDBDirectory(context->Config), + '/', target->GetPDBName(context->Config)); return result; } }; @@ -2250,8 +2207,7 @@ static const struct ShellPathNode : public cmGeneratorExpressionNode const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override { - std::vector<std::string> listIn; - cmSystemTools::ExpandListArgument(parameters.front(), listIn); + std::vector<std::string> listIn = cmExpandedList(parameters.front()); if (listIn.empty()) { reportError(context, content->GetOriginalExpression(), "\"\" is not an absolute path."); diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 036a07d..3048c5f 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -7,7 +7,7 @@ #include <assert.h> #include <errno.h> #include <iterator> -#include <memory> // IWYU pragma: keep +#include <memory> #include <queue> #include <sstream> #include <stdio.h> @@ -22,7 +22,9 @@ #include "cmCustomCommandGenerator.h" #include "cmCustomCommandLines.h" #include "cmGeneratorExpression.h" +#include "cmGeneratorExpressionContext.h" #include "cmGeneratorExpressionDAGChecker.h" +#include "cmGeneratorExpressionNode.h" #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -32,10 +34,12 @@ #include "cmSourceFile.h" #include "cmSourceFileLocation.h" #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetLinkLibraryType.h" #include "cmTargetPropertyComputer.h" +#include "cm_string_view.hxx" #include "cmake.h" class cmMessenger; @@ -92,9 +96,6 @@ public: virtual bool GetHadContextSensitiveCondition() const { return false; } cmLinkImplItem const& LinkImplItem; - -private: - cmListFileBacktrace Backtrace; }; cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem; @@ -209,6 +210,62 @@ 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()); + cmExpandList(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) @@ -259,9 +316,6 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) t->GetSourceBacktraces(), this->SourceEntries, true); - this->DLLPlatform = - !this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty(); - this->PolicyMap = t->GetPolicyMap(); } @@ -468,12 +522,14 @@ std::string cmGeneratorTarget::GetFilePrefix( const std::string& config, cmStateEnums::ArtifactType artifact) const { if (this->IsImported()) { - const char* prefix = this->GetFilePrefixInternal(artifact); + const char* prefix = this->GetFilePrefixInternal(config, artifact); return prefix ? prefix : std::string(); } - std::string prefix, suffix, base; + std::string prefix; + std::string suffix; + std::string base; this->GetFullNameInternal(config, artifact, prefix, base, suffix); return prefix; } @@ -481,12 +537,14 @@ std::string cmGeneratorTarget::GetFileSuffix( const std::string& config, cmStateEnums::ArtifactType artifact) const { if (this->IsImported()) { - const char* suffix = this->GetFileSuffixInternal(artifact); + const char* suffix = this->GetFileSuffixInternal(config, artifact); return suffix ? suffix : std::string(); } - std::string prefix, suffix, base; + std::string prefix; + std::string suffix; + std::string base; this->GetFullNameInternal(config, artifact, prefix, base, suffix); return suffix; } @@ -495,8 +553,8 @@ std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const { const char* postfix = nullptr; if (!config.empty()) { - std::string configProp = cmSystemTools::UpperCase(config); - configProp += "_POSTFIX"; + std::string configProp = + cmStrCat(cmSystemTools::UpperCase(config), "_POSTFIX"); postfix = this->GetProperty(configProp); // Mac application bundles and frameworks have no postfix. if (!this->IsImported() && postfix && @@ -508,7 +566,8 @@ std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const } const char* cmGeneratorTarget::GetFilePrefixInternal( - cmStateEnums::ArtifactType artifact, const std::string& language) const + std::string const& config, cmStateEnums::ArtifactType artifact, + const std::string& language) const { // no prefix for non-main target types. if (this->GetType() != cmStateEnums::STATIC_LIBRARY && @@ -523,8 +582,7 @@ const char* cmGeneratorTarget::GetFilePrefixInternal( // Return an empty prefix for the import library if this platform // does not support import libraries. - if (isImportedLibraryArtifact && - !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) { + if (isImportedLibraryArtifact && !this->NeedImportLibraryName(config)) { return nullptr; } @@ -558,7 +616,8 @@ const char* cmGeneratorTarget::GetFilePrefixInternal( return targetPrefix; } const char* cmGeneratorTarget::GetFileSuffixInternal( - cmStateEnums::ArtifactType artifact, const std::string& language) const + std::string const& config, cmStateEnums::ArtifactType artifact, + const std::string& language) const { // no suffix for non-main target types. if (this->GetType() != cmStateEnums::STATIC_LIBRARY && @@ -573,8 +632,7 @@ const char* cmGeneratorTarget::GetFileSuffixInternal( // Return an empty suffix for the import library if this platform // does not support import libraries. - if (isImportedLibraryArtifact && - !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) { + if (isImportedLibraryArtifact && !this->NeedImportLibraryName(config)) { return nullptr; } @@ -657,20 +715,21 @@ 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")) { cmGeneratorExpression ge; - cmSystemTools::ExpandListArgument( - ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, depTgt, - dagChecker, language), - result); + cmExpandList(ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, + depTgt, dagChecker, language), + result); } if (!depTgt->IsImported() || excludeImported) { return; @@ -679,12 +738,12 @@ static void handleSystemIncludesDep( if (const char* dirs = depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) { cmGeneratorExpression ge; - cmSystemTools::ExpandListArgument( - ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, depTgt, - dagChecker, language), - result); + cmExpandList(ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, + depTgt, dagChecker, language), + result); } } +} /* clang-format off */ #define IMPLEMENT_VISIT(KIND) \ @@ -735,9 +794,8 @@ const char* cmGeneratorTarget::GetFeature(const std::string& feature, const std::string& config) const { if (!config.empty()) { - std::string featureConfig = feature; - featureConfig += "_"; - featureConfig += cmSystemTools::UpperCase(config); + std::string featureConfig = + cmStrCat(feature, '_', cmSystemTools::UpperCase(config)); if (const char* value = this->GetProperty(featureConfig)) { return value; } @@ -771,7 +829,7 @@ bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang, std::string const& config) const { const char* feature = "INTERPROCEDURAL_OPTIMIZATION"; - const bool result = cmSystemTools::IsOn(this->GetFeature(feature, config)); + const bool result = cmIsOn(this->GetFeature(feature, config)); if (!result) { // 'INTERPROCEDURAL_OPTIMIZATION' is off, no need to check policies @@ -1057,10 +1115,9 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory( std::vector<std::string> result; for (std::string const& it : this->Target->GetSystemIncludeDirectories()) { cmGeneratorExpression ge; - cmSystemTools::ExpandListArgument( - ge.Parse(it)->Evaluate(this->LocalGenerator, config, false, this, - &dagChecker, language), - result); + cmExpandList(ge.Parse(it)->Evaluate(this->LocalGenerator, config, false, + this, &dagChecker, language), + result); } std::vector<cmGeneratorTarget const*> const& deps = @@ -1087,77 +1144,204 @@ 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) +bool cmGeneratorTarget::MaybeHaveInterfaceProperty( + std::string const& prop, cmGeneratorExpressionContext* context) const +{ + std::string const key = prop + '@' + context->Config; + auto i = this->MaybeInterfacePropertyExists.find(key); + if (i == this->MaybeInterfacePropertyExists.end()) { + // Insert an entry now in case there is a cycle. + i = this->MaybeInterfacePropertyExists.emplace(key, false).first; + bool& maybeInterfaceProp = i->second; + + // If this target itself has a non-empty property value, we are done. + const char* p = this->GetProperty(prop); + maybeInterfaceProp = p && *p; + + // Otherwise, recurse to interface dependencies. + if (!maybeInterfaceProp) { + cmGeneratorTarget const* headTarget = + context->HeadTarget ? context->HeadTarget : this; + if (cmLinkInterfaceLibraries const* iface = + this->GetLinkInterfaceLibraries(context->Config, headTarget, + true)) { + if (iface->HadHeadSensitiveCondition) { + // With a different head target we may get to a library with + // this interface property. + maybeInterfaceProp = true; + } else { + // The transitive interface libraries do not depend on the + // head target, so we can follow them. + for (cmLinkItem const& lib : iface->Libraries) { + if (lib.Target && + lib.Target->MaybeHaveInterfaceProperty(prop, context)) { + maybeInterfaceProp = true; + break; + } + } + } + } + } + } + return i->second; +} + +std::string cmGeneratorTarget::EvaluateInterfaceProperty( + std::string const& prop, cmGeneratorExpressionContext* context, + cmGeneratorExpressionDAGChecker* dagCheckerParent) const +{ + std::string result; + + // If the property does not appear transitively at all, we are done. + if (!this->MaybeHaveInterfaceProperty(prop, context)) { + return result; + } + + // Evaluate $<TARGET_PROPERTY:this,prop> as if it were compiled. This is + // a subset of TargetPropertyNode::Evaluate without stringify/parse steps + // but sufficient for transitive interface properties. + cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, this, prop, + nullptr, dagCheckerParent); + switch (dagChecker.Check()) { + case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: + dagChecker.ReportError( + context, "$<TARGET_PROPERTY:" + this->GetName() + "," + prop + ">"); + return result; + case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: + // No error. We just skip cyclic references. + return result; + case cmGeneratorExpressionDAGChecker::ALREADY_SEEN: + // No error. We have already seen this transitive property. + return result; + case cmGeneratorExpressionDAGChecker::DAG: + break; + } + + cmGeneratorTarget const* headTarget = + context->HeadTarget ? context->HeadTarget : this; + + if (const char* p = this->GetProperty(prop)) { + result = cmGeneratorExpressionNode::EvaluateDependentExpression( + p, context->LG, context, headTarget, this, &dagChecker); + } + + if (cmLinkInterfaceLibraries const* iface = + this->GetLinkInterfaceLibraries(context->Config, headTarget, true)) { + for (cmLinkItem const& lib : iface->Libraries) { + // Broken code can have a target in its own link interface. + // Don't follow such link interface entries so as not to create a + // self-referencing loop. + if (lib.Target && lib.Target != this) { + // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in the + // above property and hand-evaluate it as if it were compiled. + // Create a context as cmCompiledGeneratorExpression::Evaluate does. + cmGeneratorExpressionContext libContext( + context->LG, context->Config, context->Quiet, headTarget, this, + context->EvaluateForBuildsystem, context->Backtrace, + context->Language); + std::string libResult = cmGeneratorExpression::StripEmptyListElements( + lib.Target->EvaluateInterfaceProperty(prop, &libContext, + &dagChecker)); + if (!libResult.empty()) { + if (result.empty()) { + result = std::move(libResult); + } else { + result.reserve(result.size() + 1 + libResult.size()); + result += ";"; + result += libResult; + } + } + context->HadContextSensitiveCondition = + context->HadContextSensitiveCondition || + libContext.HadContextSensitiveCondition; + context->HadHeadSensitiveCondition = + context->HadHeadSensitiveCondition || + libContext.HadHeadSensitiveCondition; + } + } + } + + return result; +} + +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( - 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); + // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our + // caller's property and hand-evaluate it as if it were compiled. + // Create a context as cmCompiledGeneratorExpression::Evaluate does. + cmGeneratorExpressionContext context( + headTarget->GetLocalGenerator(), config, false, headTarget, + headTarget, true, lib.Backtrace, lang); + cmExpandList( + lib.Target->EvaluateInterfaceProperty(prop, &context, dagChecker), + ee.Values); + ee.ContextDependent = context.HadContextSensitiveCondition; + 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); + cmExpandList(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); @@ -1186,9 +1370,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"; } @@ -1199,11 +1383,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 @@ -1220,8 +1405,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( cmStringRange sourceEntries = this->Target->GetSourceEntries(); for (std::string const& entry : sourceEntries) { - std::vector<std::string> items; - cmSystemTools::ExpandListArgument(entry, items); + std::vector<std::string> items = cmExpandedList(entry); for (std::string const& item : items) { if (cmHasLiteralPrefix(item, "$<TARGET_OBJECTS:") && item.back() == '>') { @@ -1237,12 +1421,11 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( const char* debugProp = this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); if (debugProp) { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); + cmExpandList(debugProp, debugProperties); } - bool debugSources = !this->DebugSourcesDone && - std::find(debugProperties.begin(), debugProperties.end(), "SOURCES") != - debugProperties.end(); + bool debugSources = + !this->DebugSourcesDone && cmContains(debugProperties, "SOURCES"); if (this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) { this->DebugSourcesDone = true; @@ -1251,28 +1434,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()) && @@ -1280,8 +1463,6 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( this->LinkImplementationLanguageIsContextDependent = false; } - cmDeleteAll(linkInterfaceSourcesEntries); - cmDeleteAll(linkObjectsEntries); return files; } @@ -1521,8 +1702,7 @@ std::string cmGeneratorTarget::GetCompilePDBName( // Check for a per-configuration output directory target property. std::string configUpper = cmSystemTools::UpperCase(config); - std::string configProp = "COMPILE_PDB_NAME_"; - configProp += configUpper; + std::string configProp = cmStrCat("COMPILE_PDB_NAME_", configUpper); const char* config_name = this->GetProperty(configProp); if (config_name && *config_name) { return prefix + config_name + ".pdb"; @@ -1594,9 +1774,8 @@ bool cmGeneratorTarget::NeedRelinkBeforeInstall( // Check for rpath support on this platform. std::string ll = this->GetLinkerLanguage(config); if (!ll.empty()) { - std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; - flagVar += ll; - flagVar += "_FLAG"; + std::string flagVar = + cmStrCat("CMAKE_SHARED_LIBRARY_RUNTIME_", ll, "_FLAG"); if (!this->Makefile->IsSet(flagVar)) { // There is no rpath support on this platform so nothing needs // relinking. @@ -1612,7 +1791,7 @@ bool cmGeneratorTarget::NeedRelinkBeforeInstall( // will likely change between the build tree and install tree and // this target must be relinked. bool have_rpath = - this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH(); + this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH(config); bool is_ninja = this->LocalGenerator->GetGlobalGenerator()->GetName() == "Ninja"; @@ -1674,9 +1853,8 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const // binaries. std::string ll = this->GetLinkerLanguage(config); if (!ll.empty()) { - std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; - sepVar += ll; - sepVar += "_FLAG_SEP"; + std::string sepVar = + cmStrCat("CMAKE_SHARED_LIBRARY_RUNTIME_", ll, "_FLAG_SEP"); const char* sep = this->Makefile->GetDefinition(sepVar); if (sep && *sep) { // TODO: Add ELF check to ABI detection and get rid of @@ -1793,7 +1971,7 @@ bool cmGeneratorTarget::MacOSXUseInstallNameDir() const const char* build_with_install_name = this->GetProperty("BUILD_WITH_INSTALL_NAME_DIR"); if (build_with_install_name) { - return cmSystemTools::IsOn(build_with_install_name); + return cmIsOn(build_with_install_name); } cmPolicies::PolicyStatus cmp0068 = this->GetPolicyStatusCMP0068(); @@ -1858,23 +2036,23 @@ 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 { - std::string fpath = - this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact); - fpath += "."; + std::string fpath = cmStrCat( + this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact), '.'); const char* ext = this->GetProperty("BUNDLE_EXTENSION"); if (!ext) { ext = "app"; @@ -1899,9 +2077,8 @@ bool cmGeneratorTarget::IsBundleOnApple() const std::string cmGeneratorTarget::GetCFBundleDirectory( const std::string& config, BundleDirectoryLevel level) const { - std::string fpath; - fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact); - fpath += "."; + std::string fpath = cmStrCat( + this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact), '.'); const char* ext = this->GetProperty("BUNDLE_EXTENSION"); if (!ext) { if (this->IsXCTestOnApple()) { @@ -1924,9 +2101,8 @@ std::string cmGeneratorTarget::GetCFBundleDirectory( std::string cmGeneratorTarget::GetFrameworkDirectory( const std::string& config, BundleDirectoryLevel level) const { - std::string fpath; - fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact); - fpath += "."; + std::string fpath = cmStrCat( + this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact), '.'); const char* ext = this->GetProperty("BUNDLE_EXTENSION"); if (!ext) { ext = "framework"; @@ -1983,8 +2159,7 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) { if (install_name_dir && *install_name_dir) { - dir = install_name_dir; - dir += "/"; + dir = cmStrCat(install_name_dir, '/'); } } if (!install_name_dir) { @@ -2025,8 +2200,7 @@ const std::string* cmGeneratorTarget::GetExportMacro() const if (const char* custom_export_name = this->GetProperty("DEFINE_SYMBOL")) { this->ExportMacro = custom_export_name; } else { - std::string in = this->GetName(); - in += "_EXPORTS"; + std::string in = cmStrCat(this->GetName(), "_EXPORTS"); this->ExportMacro = cmSystemTools::MakeCidentifier(in); } return &this->ExportMacro; @@ -2247,8 +2421,7 @@ std::string cmGeneratorTarget::GetMacContentDirectory( const std::string& config, cmStateEnums::ArtifactType artifact) const { // Start with the output directory for the target. - std::string fpath = this->GetDirectory(config, artifact); - fpath += "/"; + std::string fpath = cmStrCat(this->GetDirectory(config, artifact), '/'); BundleDirectoryLevel level = ContentLevel; if (this->IsFrameworkOnApple()) { // additional files with a framework go into the version specific @@ -2284,10 +2457,9 @@ cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo( } if (this->GetType() > cmStateEnums::OBJECT_LIBRARY) { - std::string msg = "cmTarget::GetCompileInfo called for "; - msg += this->GetName(); - msg += " which has type "; - msg += cmState::GetTargetTypeName(this->GetType()); + std::string msg = cmStrCat("cmTarget::GetCompileInfo called for ", + this->GetName(), " which has type ", + cmState::GetTargetTypeName(this->GetType())); this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); return nullptr; } @@ -2341,7 +2513,7 @@ void cmGeneratorTarget::ComputeModuleDefinitionInfo( info.WindowsExportAllSymbols = this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") && this->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"); -#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) +#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP) info.DefFileGenerated = info.WindowsExportAllSymbols || info.Sources.size() > 1; #else @@ -2357,7 +2529,7 @@ void cmGeneratorTarget::ComputeModuleDefinitionInfo( bool cmGeneratorTarget::IsDLLPlatform() const { - return this->DLLPlatform; + return this->Target->IsDLLPlatform(); } void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result, @@ -2372,10 +2544,9 @@ void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result, cmGeneratorExpressionDAGChecker dagChecker(this, "AUTOUIC_OPTIONS", nullptr, nullptr); - cmSystemTools::ExpandListArgument( - ge.Parse(prop)->Evaluate(this->LocalGenerator, config, false, this, - &dagChecker), - result); + cmExpandList(ge.Parse(prop)->Evaluate(this->LocalGenerator, config, false, + this, &dagChecker), + result); } void processILibs(const std::string& config, @@ -2468,7 +2639,7 @@ cmTargetTraceDependencies::cmTargetTraceDependencies(cmGeneratorTarget* target) for (cmSourceFile* sf : sources) { const std::set<cmGeneratorTarget const*> tgts = this->GlobalGenerator->GetFilenameTargetDepends(sf); - if (tgts.find(this->GeneratorTarget) != tgts.end()) { + if (cmContains(tgts, this->GeneratorTarget)) { std::ostringstream e; e << "Evaluation output file\n \"" << sf->GetFullPath() << "\"\ndepends on the sources of a target it is used in. This " @@ -2502,8 +2673,7 @@ void cmTargetTraceDependencies::Trace() // Queue dependencies added explicitly by the user. if (const char* additionalDeps = sf->GetProperty("OBJECT_DEPENDS")) { - std::vector<std::string> objDeps; - cmSystemTools::ExpandListArgument(additionalDeps, objDeps); + std::vector<std::string> objDeps = cmExpandedList(additionalDeps); for (std::string& objDep : objDeps) { if (cmSystemTools::FileIsFullPath(objDep)) { objDep = cmSystemTools::CollapseFullPath(objDep); @@ -2716,15 +2886,15 @@ void cmGeneratorTarget::GetAppleArchs(const std::string& config, { const char* archs = nullptr; if (!config.empty()) { - std::string defVarName = "OSX_ARCHITECTURES_"; - defVarName += cmSystemTools::UpperCase(config); + std::string defVarName = + cmStrCat("OSX_ARCHITECTURES_", cmSystemTools::UpperCase(config)); archs = this->GetProperty(defVarName); } if (!archs) { archs = this->GetProperty("OSX_ARCHITECTURES"); } if (archs) { - cmSystemTools::ExpandListArgument(std::string(archs), archVec); + cmExpandList(std::string(archs), archVec); } } @@ -2757,33 +2927,35 @@ std::string cmGeneratorTarget::GetCreateRuleVariable( case cmStateEnums::MODULE_LIBRARY: return "CMAKE_" + lang + "_CREATE_SHARED_MODULE"; case cmStateEnums::EXECUTABLE: + if (this->IsExecutableWithExports()) { + std::string linkExeWithExports = + "CMAKE_" + lang + "_LINK_EXECUTABLE_WITH_EXPORTS"; + if (this->Makefile->IsDefinitionSet(linkExeWithExports)) { + return linkExeWithExports; + } + } return "CMAKE_" + lang + "_LINK_EXECUTABLE"; default: break; } 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; @@ -2852,15 +3024,14 @@ static void processIncludeDirectories( } } - if (!cmSystemTools::IsOff(entryInclude)) { + if (!cmIsOff(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"; } } } @@ -2869,10 +3040,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 @@ -2887,25 +3059,22 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( const char* debugProp = this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); if (debugProp) { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); + cmExpandList(debugProp, debugProperties); } bool debugIncludes = !this->DebugIncludesDone && - std::find(debugProperties.begin(), debugProperties.end(), - "INCLUDE_DIRECTORIES") != debugProperties.end(); + cmContains(debugProperties, "INCLUDE_DIRECTORIES"); if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { 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 = @@ -2921,16 +3090,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; } @@ -2941,33 +3108,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"; @@ -2979,22 +3139,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, @@ -3021,48 +3169,29 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileOptions( const char* debugProp = this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); if (debugProp) { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); + cmExpandList(debugProp, debugProperties); } bool debugOptions = !this->DebugCompileOptionsDone && - std::find(debugProperties.begin(), debugProperties.end(), - "COMPILE_OPTIONS") != debugProperties.end(); + cmContains(debugProperties, "COMPILE_OPTIONS"); if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { this->DebugCompileOptionsDone = true; } - processCompileOptions(this, this->CompileOptionsEntries, result, - uniqueOptions, &dagChecker, config, debugOptions, - language); - - std::vector<cmGeneratorTarget::TargetPropertyEntry*> - linkInterfaceCompileOptionsEntries; + std::vector<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, language, &dagChecker, + this->CompileOptionsEntries); - AddInterfaceEntries(this, config, "INTERFACE_COMPILE_OPTIONS", - linkInterfaceCompileOptionsEntries); + AddInterfaceEntries(this, config, "INTERFACE_COMPILE_OPTIONS", language, + &dagChecker, entries); - processCompileOptions(this, linkInterfaceCompileOptionsEntries, result, - uniqueOptions, &dagChecker, config, debugOptions, - language); + processOptions(this, entries, result, uniqueOptions, debugOptions, + "compile options", OptionsParse::Shell); - 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 { @@ -3086,45 +3215,29 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileFeatures( const char* debugProp = this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); if (debugProp) { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); + cmExpandList(debugProp, debugProperties); } bool debugFeatures = !this->DebugCompileFeaturesDone && - std::find(debugProperties.begin(), debugProperties.end(), - "COMPILE_FEATURES") != debugProperties.end(); + cmContains(debugProperties, "COMPILE_FEATURES"); if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { 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 @@ -3150,25 +3263,23 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( const char* debugProp = this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); if (debugProp) { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); + cmExpandList(debugProp, debugProperties); } bool debugDefines = !this->DebugCompileDefinitionsDone && - std::find(debugProperties.begin(), debugProperties.end(), - "COMPILE_DEFINITIONS") != debugProperties.end(); + cmContains(debugProperties, "COMPILE_DEFINITIONS"); if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { 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); @@ -3176,15 +3287,16 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( if (configProp) { switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0043)) { case cmPolicies::WARN: { - std::ostringstream e; - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0043); - this->LocalGenerator->IssueMessage(MessageType::AUTHOR_WARNING, - e.str()); + this->LocalGenerator->IssueMessage( + MessageType::AUTHOR_WARNING, + cmPolicies::GetPolicyWarning(cmPolicies::CMP0043)); 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: @@ -3194,29 +3306,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 @@ -3241,38 +3336,31 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( const char* debugProp = this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); if (debugProp) { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); + cmExpandList(debugProp, debugProperties); } - bool debugOptions = !this->DebugLinkOptionsDone && - std::find(debugProperties.begin(), debugProperties.end(), - "LINK_OPTIONS") != debugProperties.end(); + bool debugOptions = + !this->DebugLinkOptionsDone && cmContains(debugProperties, "LINK_OPTIONS"); if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { this->DebugLinkOptionsDone = true; } - processLinkOptions(this, this->LinkOptionsEntries, result, uniqueOptions, - &dagChecker, config, debugOptions, language); - - std::vector<cmGeneratorTarget::TargetPropertyEntry*> - linkInterfaceLinkOptionsEntries; - - AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS", - linkInterfaceLinkOptionsEntries); + std::vector<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, language, &dagChecker, + this->LinkOptionsEntries); - processLinkOptions(this, linkInterfaceLinkOptionsEntries, result, - uniqueOptions, &dagChecker, config, debugOptions, - language); + AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS", language, + &dagChecker, entries); - cmDeleteAll(linkInterfaceLinkOptionsEntries); + processOptions(this, entries, result, uniqueOptions, debugOptions, + "link options", OptionsParse::Shell); // Last step: replace "LINKER:" prefixed elements by // actual linker wrapper const std::string wrapper(this->Makefile->GetSafeDefinition( "CMAKE_" + language + "_LINKER_WRAPPER_FLAG")); - std::vector<std::string> wrapperFlag; - cmSystemTools::ExpandListArgument(wrapper, wrapperFlag); + std::vector<std::string> wrapperFlag = cmExpandedList(wrapper); const std::string wrapperSep(this->Makefile->GetSafeDefinition( "CMAKE_" + language + "_LINKER_WRAPPER_FLAG_SEP")); bool concatFlagAndArgs = true; @@ -3300,8 +3388,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( cmSystemTools::ParseUnixCommandLine( value.c_str() + LINKER_SHELL.length(), linkerOptions); } else { - linkerOptions = - cmSystemTools::tokenize(value.substr(LINKER.length()), ","); + linkerOptions = cmTokenize(value.substr(LINKER.length()), ","); } if (linkerOptions.empty() || @@ -3371,21 +3458,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 @@ -3402,47 +3474,40 @@ 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); + std::vector<std::string> options = cmExpandedList(linkOptions); 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; @@ -3495,7 +3560,7 @@ void processLinkDirectories( MessageType::LOG, std::string("Used link directories for target ") + tgt->GetName() + ":\n" + usedDirectories, - entry->GetBacktrace()); + entry.Backtrace); } } } @@ -3526,50 +3591,29 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDirectories( const char* debugProp = this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); if (debugProp) { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); + cmExpandList(debugProp, debugProperties); } bool debugDirectories = !this->DebugLinkDirectoriesDone && - std::find(debugProperties.begin(), debugProperties.end(), - "LINK_DIRECTORIES") != debugProperties.end(); + cmContains(debugProperties, "LINK_DIRECTORIES"); if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { 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 @@ -3585,24 +3629,26 @@ 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); + std::vector<std::string> depends = cmExpandedList(linkDepends); 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; } @@ -3632,33 +3678,25 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const // Add each name. std::string f; if (!targetNames.Output.empty()) { - f = dir; - f += "/"; - f += targetNames.Output; + f = cmStrCat(dir, '/', targetNames.Output); gg->AddToManifest(f); } if (!targetNames.SharedObject.empty()) { - f = dir; - f += "/"; - f += targetNames.SharedObject; + f = cmStrCat(dir, '/', targetNames.SharedObject); gg->AddToManifest(f); } if (!targetNames.Real.empty()) { - f = dir; - f += "/"; - f += targetNames.Real; + f = cmStrCat(dir, '/', targetNames.Real); gg->AddToManifest(f); } if (!targetNames.PDB.empty()) { - f = dir; - f += "/"; - f += targetNames.PDB; + f = cmStrCat(dir, '/', targetNames.PDB); gg->AddToManifest(f); } if (!targetNames.ImportLibrary.empty()) { - f = this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact); - f += "/"; - f += targetNames.ImportLibrary; + f = + cmStrCat(this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact), + '/', targetNames.ImportLibrary); gg->AddToManifest(f); } } @@ -3698,11 +3736,10 @@ std::string cmGeneratorTarget::NormalGetFullPath( const std::string& config, cmStateEnums::ArtifactType artifact, bool realname) const { - std::string fpath = this->GetDirectory(config, artifact); - fpath += "/"; + std::string fpath = cmStrCat(this->GetDirectory(config, artifact), '/'); if (this->IsAppBundleOnApple()) { - fpath = this->BuildBundleDirectory(fpath, config, FullLevel); - fpath += "/"; + fpath = + cmStrCat(this->BuildBundleDirectory(fpath, config, FullLevel), '/'); } // Add the full name of the target. @@ -3729,8 +3766,8 @@ std::string cmGeneratorTarget::NormalGetRealName( // TODO: Split cmTarget into a class hierarchy to get compile-time // enforcement of the limited imported target API. if (this->IsImported()) { - std::string msg = "NormalGetRealName called on imported target: "; - msg += this->GetName(); + std::string msg = cmStrCat("NormalGetRealName called on imported target: ", + this->GetName()); this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); } @@ -3751,8 +3788,8 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames( // TODO: Split cmTarget into a class hierarchy to get compile-time // enforcement of the limited imported target API. if (this->IsImported()) { - std::string msg = "GetLibraryNames called on imported target: "; - msg += this->GetName(); + std::string msg = + cmStrCat("GetLibraryNames called on imported target: ", this->GetName()); this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); } @@ -3828,8 +3865,8 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetExecutableNames( // TODO: Split cmTarget into a class hierarchy to get compile-time // enforcement of the limited imported target API. if (this->IsImported()) { - std::string msg = "GetExecutableNames called on imported target: "; - msg += this->GetName(); + std::string msg = cmStrCat( + "GetExecutableNames called on imported target: ", this->GetName()); this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); } @@ -3924,8 +3961,7 @@ void cmGeneratorTarget::GetFullNameInternal( // Return an empty name for the import library if this platform // does not support import libraries. - if (isImportedLibraryArtifact && - !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) { + if (isImportedLibraryArtifact && !this->NeedImportLibraryName(config)) { outPrefix.clear(); outBase.clear(); outSuffix.clear(); @@ -3934,8 +3970,8 @@ void cmGeneratorTarget::GetFullNameInternal( // retrieve prefix and suffix std::string ll = this->GetLinkerLanguage(config); - const char* targetPrefix = this->GetFilePrefixInternal(artifact, ll); - const char* targetSuffix = this->GetFileSuffixInternal(artifact, ll); + const char* targetPrefix = this->GetFilePrefixInternal(config, artifact, ll); + const char* targetSuffix = this->GetFileSuffixInternal(config, artifact, ll); // The implib option is only allowed for shared libraries, module // libraries, and executables. @@ -3951,15 +3987,14 @@ void cmGeneratorTarget::GetFullNameInternal( // frameworks have directory prefix but no suffix std::string fw_prefix; if (this->IsFrameworkOnApple()) { - fw_prefix = this->GetFrameworkDirectory(config, ContentLevel); - fw_prefix += "/"; + fw_prefix = + cmStrCat(this->GetFrameworkDirectory(config, ContentLevel), '/'); targetPrefix = fw_prefix.c_str(); targetSuffix = nullptr; } if (this->IsCFBundleOnApple()) { - fw_prefix = this->GetCFBundleDirectory(config, FullLevel); - fw_prefix += "/"; + fw_prefix = cmStrCat(this->GetCFBundleDirectory(config, FullLevel), '/'); targetPrefix = fw_prefix.c_str(); targetSuffix = nullptr; } @@ -4121,7 +4156,7 @@ cmGeneratorTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const if (stripResources) { flags.MacFolder = ""; } - } else if (cmSystemTools::StringStartsWith(location, "Resources/")) { + } else if (cmHasLiteralPrefix(location, "Resources/")) { flags.Type = cmGeneratorTarget::SourceFileTypeDeepResource; if (stripResources) { flags.MacFolder += strlen("Resources/"); @@ -4143,8 +4178,7 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const // Process public headers to mark the source files. if (const char* files = this->GetProperty("PUBLIC_HEADER")) { - std::vector<std::string> relFiles; - cmSystemTools::ExpandListArgument(files, relFiles); + std::vector<std::string> relFiles = cmExpandedList(files); for (std::string const& relFile : relFiles) { if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) { SourceFileFlags& flags = this->SourceFlagsMap[sf]; @@ -4157,8 +4191,7 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const // Process private headers after public headers so that they take // precedence if a file is listed in both. if (const char* files = this->GetProperty("PRIVATE_HEADER")) { - std::vector<std::string> relFiles; - cmSystemTools::ExpandListArgument(files, relFiles); + std::vector<std::string> relFiles = cmExpandedList(files); for (std::string const& relFile : relFiles) { if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) { SourceFileFlags& flags = this->SourceFlagsMap[sf]; @@ -4170,8 +4203,7 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const // Mark sources listed as resources. if (const char* files = this->GetProperty("RESOURCE")) { - std::vector<std::string> relFiles; - cmSystemTools::ExpandListArgument(files, relFiles); + std::vector<std::string> relFiles = cmExpandedList(files); for (std::string const& relFile : relFiles) { if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) { SourceFileFlags& flags = this->SourceFlagsMap[sf]; @@ -4200,7 +4232,7 @@ cmGeneratorTarget::GetCompatibleInterfaces(std::string const& config) const #define CM_READ_COMPATIBLE_INTERFACE(X, x) \ if (const char* prop = li->GetProperty("COMPATIBLE_INTERFACE_" #X)) { \ std::vector<std::string> props; \ - cmSystemTools::ExpandListArgument(prop, props); \ + cmExpandList(prop, props); \ compat.Props##x.insert(props.begin(), props.end()); \ } CM_READ_COMPATIBLE_INTERFACE(BOOL, Bool) @@ -4313,10 +4345,9 @@ void checkPropertyConsistency(cmGeneratorTarget const* depender, return; } - std::vector<std::string> props; - cmSystemTools::ExpandListArgument(prop, props); - std::string pdir = cmSystemTools::GetCMakeRoot(); - pdir += "/Help/prop_tgt/"; + std::vector<std::string> props = cmExpandedList(prop); + std::string pdir = + cmStrCat(cmSystemTools::GetCMakeRoot(), "/Help/prop_tgt/"); for (std::string const& p : props) { std::string pname = cmSystemTools::HelpFileName(p); @@ -4343,8 +4374,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(), @@ -4355,9 +4387,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); @@ -4371,10 +4403,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); @@ -4391,6 +4423,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 @@ -4460,8 +4493,8 @@ void cmGeneratorTarget::CheckPropertyCompatibility( } std::sort(props.begin(), props.end()); - std::string propsString = cmJoin(cmMakeRange(props).retreat(1), ", "); - propsString += " and the " + props.back(); + std::string propsString = cmStrCat( + cmJoin(cmMakeRange(props).retreat(1), ", "), " and the ", props.back()); std::ostringstream e; e << "Property \"" << prop << "\" appears in both the " << propsString @@ -4542,7 +4575,7 @@ bool getTypedProperty<bool>(cmGeneratorTarget const* tgt, } const char* value = tgt->GetProperty(prop); - return cmSystemTools::IsOn(genexInterpreter->Evaluate(value, prop)); + return cmIsOn(genexInterpreter->Evaluate(value, prop)); } template <> @@ -4660,7 +4693,7 @@ std::pair<bool, const char*> consistentProperty(const char* lhs, switch (t) { case BoolType: { - bool same = cmSystemTools::IsOn(lhs) == cmSystemTools::IsOn(rhs); + bool same = cmIsOn(lhs) == cmIsOn(rhs); return std::make_pair(same, same ? lhs : nullptr); } case StringType: @@ -4691,7 +4724,7 @@ std::pair<bool, std::string> consistentProperty(const std::string& lhs, switch (t) { case BoolType: { - bool same = cmSystemTools::IsOn(lhs) == cmSystemTools::IsOn(rhs); + bool same = cmIsOn(lhs) == cmIsOn(rhs); return std::make_pair(same, same ? lhs : null_ptr); } case StringType: @@ -4718,9 +4751,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, PropertyType propContent = getTypedProperty<PropertyType>(tgt, p); std::vector<std::string> headPropKeys = tgt->GetPropertyKeys(); - const bool explicitlySet = - std::find(headPropKeys.begin(), headPropKeys.end(), p) != - headPropKeys.end(); + const bool explicitlySet = cmContains(headPropKeys, p); const bool impliedByUse = tgt->IsNullImpliedByLinkLibraries(p); assert((impliedByUse ^ explicitlySet) || (!impliedByUse && !explicitlySet)); @@ -4733,8 +4764,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, } bool propInitialized = explicitlySet; - std::string report = " * Target \""; - report += tgt->GetName(); + std::string report = cmStrCat(" * Target \"", tgt->GetName()); if (explicitlySet) { report += "\" has property content \""; report += valueAsString<PropertyType>(propContent); @@ -4760,8 +4790,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, std::vector<std::string> propKeys = theTarget->GetPropertyKeys(); - const bool ifaceIsSet = std::find(propKeys.begin(), propKeys.end(), - interfaceProperty) != propKeys.end(); + const bool ifaceIsSet = cmContains(propKeys, interfaceProperty); PropertyType ifacePropContent = getTypedProperty<PropertyType>( theTarget, interfaceProperty, genexInterpreter.get()); @@ -4991,9 +5020,8 @@ std::string cmGeneratorTarget::CreateFortranModuleDirectory( mod_dir = target_mod_dir; } else { // Interpret relative to the current output directory. - mod_dir = this->LocalGenerator->GetCurrentBinaryDirectory(); - mod_dir += "/"; - mod_dir += target_mod_dir; + mod_dir = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), + '/', target_mod_dir); } // Make sure the module output directory exists. @@ -5032,13 +5060,7 @@ void cmGeneratorTarget::ComputeVersionedName(std::string& vName, std::vector<std::string> cmGeneratorTarget::GetPropertyKeys() const { - cmPropertyMap const& propsObject = this->Target->GetProperties(); - std::vector<std::string> props; - props.reserve(propsObject.size()); - for (auto const& it : propsObject) { - props.push_back(it.first); - } - return props; + return this->Target->GetProperties().GetKeys(); } void cmGeneratorTarget::ReportPropertyOrigin( @@ -5049,12 +5071,11 @@ void cmGeneratorTarget::ReportPropertyOrigin( const char* debugProp = this->Target->GetMakefile()->GetDefinition( "CMAKE_DEBUG_TARGET_PROPERTIES"); if (debugProp) { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); + cmExpandList(debugProp, debugProperties); } - bool debugOrigin = !this->DebugCompatiblePropertiesDone[p] && - std::find(debugProperties.begin(), debugProperties.end(), p) != - debugProperties.end(); + bool debugOrigin = + !this->DebugCompatiblePropertiesDone[p] && cmContains(debugProperties, p); if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { this->DebugCompatiblePropertiesDone[p] = true; @@ -5063,12 +5084,9 @@ void cmGeneratorTarget::ReportPropertyOrigin( return; } - std::string areport = compatibilityType; - areport += std::string(" of property \"") + p + "\" for target \""; - areport += std::string(this->GetName()); - areport += "\" (result: \""; - areport += result; - areport += "\"):\n" + report; + std::string areport = + cmStrCat(compatibilityType, " of property \"", p, "\" for target \"", + this->GetName(), "\" (result: \"", result, "\"):\n", report); this->LocalGenerator->GetCMakeInstance()->IssueMessage(MessageType::LOG, areport); @@ -5101,10 +5119,9 @@ void cmGeneratorTarget::ExpandLinkItems( } std::vector<std::string> libs; std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); - cmSystemTools::ExpandListArgument(cge->Evaluate(this->LocalGenerator, config, - false, headTarget, this, - &dagChecker), - libs); + cmExpandList(cge->Evaluate(this->LocalGenerator, config, false, headTarget, + this, &dagChecker), + libs); this->LookupLinkItems(libs, cge->GetBacktrace(), items); hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition(); } @@ -5152,7 +5169,7 @@ void cmGeneratorTarget::ComputeLinkInterface( const std::string& config, cmOptionalLinkInterface& iface, cmGeneratorTarget const* headTarget) const { - if (iface.ExplicitLibraries) { + if (iface.Explicit) { if (this->GetType() == cmStateEnums::SHARED_LIBRARY || this->GetType() == cmStateEnums::STATIC_LIBRARY || this->GetType() == cmStateEnums::INTERFACE_LIBRARY) { @@ -5209,8 +5226,7 @@ void cmGeneratorTarget::ComputeLinkInterface( // How many repetitions are needed if this library has cyclic // dependencies? - std::string propName = "LINK_INTERFACE_MULTIPLICITY"; - propName += suffix; + std::string propName = cmStrCat("LINK_INTERFACE_MULTIPLICITY", suffix); if (const char* config_reps = this->GetProperty(propName)) { sscanf(config_reps, "%u", &iface.Multiplicity); } else if (const char* reps = @@ -5296,10 +5312,9 @@ cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo( // Only libraries and executables have well-defined output files. if (!this->HaveWellDefinedOutputFiles()) { - std::string msg = "cmGeneratorTarget::GetOutputInfo called for "; - msg += this->GetName(); - msg += " which has type "; - msg += cmState::GetTargetTypeName(this->GetType()); + std::string msg = cmStrCat("cmGeneratorTarget::GetOutputInfo called for ", + this->GetName(), " which has type ", + cmState::GetTargetTypeName(this->GetType())); this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); return nullptr; } @@ -5485,13 +5500,41 @@ bool cmGeneratorTarget::ComputePDBOutputDir(const std::string& kind, return true; } -bool cmGeneratorTarget::HaveInstallTreeRPATH() const +bool cmGeneratorTarget::HaveInstallTreeRPATH(const std::string& config) const { - const char* install_rpath = this->GetProperty("INSTALL_RPATH"); - return (install_rpath && *install_rpath) && + std::string install_rpath; + this->GetInstallRPATH(config, install_rpath); + return !install_rpath.empty() && !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH"); } +bool cmGeneratorTarget::GetBuildRPATH(const std::string& config, + std::string& rpath) const +{ + return this->GetRPATH(config, "BUILD_RPATH", rpath); +} + +bool cmGeneratorTarget::GetInstallRPATH(const std::string& config, + std::string& rpath) const +{ + return this->GetRPATH(config, "INSTALL_RPATH", rpath); +} + +bool cmGeneratorTarget::GetRPATH(const std::string& config, + const std::string& prop, + std::string& rpath) const +{ + const char* value = this->GetProperty(prop); + if (!value) { + return false; + } + + cmGeneratorExpression ge; + rpath = ge.Parse(value)->Evaluate(this->LocalGenerator, config); + + return true; +} + void cmGeneratorTarget::ComputeLinkInterfaceLibraries( const std::string& config, cmOptionalLinkInterface& iface, cmGeneratorTarget const* headTarget, bool usage_requirements_only) const @@ -5508,8 +5551,9 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( // libraries and executables that export symbols. const char* explicitLibraries = nullptr; std::string linkIfaceProp; - if (this->GetPolicyStatusCMP0022() != cmPolicies::OLD && - this->GetPolicyStatusCMP0022() != cmPolicies::WARN) { + bool const cmp0022NEW = (this->GetPolicyStatusCMP0022() != cmPolicies::OLD && + this->GetPolicyStatusCMP0022() != cmPolicies::WARN); + if (cmp0022NEW) { // CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES. linkIfaceProp = "INTERFACE_LINK_LIBRARIES"; explicitLibraries = this->GetProperty(linkIfaceProp); @@ -5519,8 +5563,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( // shared lib or executable. // Lookup the per-configuration property. - linkIfaceProp = "LINK_INTERFACE_LIBRARIES"; - linkIfaceProp += suffix; + linkIfaceProp = cmStrCat("LINK_INTERFACE_LIBRARIES", suffix); explicitLibraries = this->GetProperty(linkIfaceProp); // If not set, try the generic property. @@ -5564,15 +5607,14 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( return; } iface.Exists = true; - iface.ExplicitLibraries = explicitLibraries; + iface.Explicit = cmp0022NEW || explicitLibraries != nullptr; if (explicitLibraries) { // The interface libraries have been explicitly set. this->ExpandLinkItems(linkIfaceProp, explicitLibraries, config, headTarget, usage_requirements_only, iface.Libraries, iface.HadHeadSensitiveCondition); - } else if (this->GetPolicyStatusCMP0022() == cmPolicies::WARN || - this->GetPolicyStatusCMP0022() == cmPolicies::OLD) + } else if (!cmp0022NEW) // If CMP0022 is NEW then the plain tll signature sets the // INTERFACE_LINK_LIBRARIES, so if we get here then the project // cleared the property explicitly and we should not fall back @@ -5653,12 +5695,11 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface( if (!iface.AllDone) { iface.AllDone = true; iface.Multiplicity = info->Multiplicity; - cmSystemTools::ExpandListArgument(info->Languages, iface.Languages); + cmExpandList(info->Languages, iface.Languages); this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config, headTarget, usage_requirements_only, iface.Libraries, iface.HadHeadSensitiveCondition); - std::vector<std::string> deps; - cmSystemTools::ExpandListArgument(info->SharedDeps, deps); + std::vector<std::string> deps = cmExpandedList(info->SharedDeps); this->LookupLinkItems(deps, cmListFileBacktrace(), iface.SharedDeps); } @@ -5727,8 +5768,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) { if (!propertyLibs) { - linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES"; - linkProp += suffix; + linkProp = cmStrCat("IMPORTED_LINK_INTERFACE_LIBRARIES", suffix); propertyLibs = this->GetProperty(linkProp); } @@ -5756,8 +5796,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, if (loc) { info.Location = loc; } else { - std::string impProp = "IMPORTED_LOCATION"; - impProp += suffix; + std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix); if (const char* config_location = this->GetProperty(impProp)) { info.Location = config_location; } else if (const char* location = this->GetProperty("IMPORTED_LOCATION")) { @@ -5767,8 +5806,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Get the soname. if (this->GetType() == cmStateEnums::SHARED_LIBRARY) { - std::string soProp = "IMPORTED_SONAME"; - soProp += suffix; + std::string soProp = cmStrCat("IMPORTED_SONAME", suffix); if (const char* config_soname = this->GetProperty(soProp)) { info.SOName = config_soname; } else if (const char* soname = this->GetProperty("IMPORTED_SONAME")) { @@ -5778,13 +5816,12 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Get the "no-soname" mark. if (this->GetType() == cmStateEnums::SHARED_LIBRARY) { - std::string soProp = "IMPORTED_NO_SONAME"; - soProp += suffix; + std::string soProp = cmStrCat("IMPORTED_NO_SONAME", suffix); if (const char* config_no_soname = this->GetProperty(soProp)) { - info.NoSOName = cmSystemTools::IsOn(config_no_soname); + info.NoSOName = cmIsOn(config_no_soname); } else if (const char* no_soname = this->GetProperty("IMPORTED_NO_SONAME")) { - info.NoSOName = cmSystemTools::IsOn(no_soname); + info.NoSOName = cmIsOn(no_soname); } } @@ -5793,8 +5830,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, info.ImportLibrary = imp; } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY || this->IsExecutableWithExports()) { - std::string impProp = "IMPORTED_IMPLIB"; - impProp += suffix; + std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix); if (const char* config_implib = this->GetProperty(impProp)) { info.ImportLibrary = config_implib; } else if (const char* implib = this->GetProperty("IMPORTED_IMPLIB")) { @@ -5804,8 +5840,8 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Get the link dependencies. { - std::string linkProp = "IMPORTED_LINK_DEPENDENT_LIBRARIES"; - linkProp += suffix; + std::string linkProp = + cmStrCat("IMPORTED_LINK_DEPENDENT_LIBRARIES", suffix); if (const char* config_libs = this->GetProperty(linkProp)) { info.SharedDeps = config_libs; } else if (const char* libs = @@ -5816,8 +5852,8 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Get the link languages. if (this->LinkLanguagePropagatesToDependents()) { - std::string linkProp = "IMPORTED_LINK_INTERFACE_LANGUAGES"; - linkProp += suffix; + std::string linkProp = + cmStrCat("IMPORTED_LINK_INTERFACE_LANGUAGES", suffix); if (const char* config_libs = this->GetProperty(linkProp)) { info.Languages = config_libs; } else if (const char* libs = @@ -5838,8 +5874,8 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Get the cyclic repetition count. if (this->GetType() == cmStateEnums::STATIC_LIBRARY) { - std::string linkProp = "IMPORTED_LINK_INTERFACE_MULTIPLICITY"; - linkProp += suffix; + std::string linkProp = + cmStrCat("IMPORTED_LINK_INTERFACE_MULTIPLICITY", suffix); if (const char* config_reps = this->GetProperty(linkProp)) { sscanf(config_reps, "%u", &info.Multiplicity); } else if (const char* reps = @@ -5946,8 +5982,7 @@ void cmGeneratorTarget::GetObjectLibrariesCMP0026( // behavior of CMP0024 and CMP0026 only. cmStringRange rng = this->Target->GetSourceEntries(); for (std::string const& entry : rng) { - std::vector<std::string> files; - cmSystemTools::ExpandListArgument(entry, files); + std::vector<std::string> files = cmExpandedList(entry); for (std::string const& li : files) { if (cmHasLiteralPrefix(li, "$<TARGET_OBJECTS:") && li.back() == '>') { std::string objLibName = li.substr(17, li.size() - 18); @@ -6091,7 +6126,8 @@ bool cmGeneratorTarget::HaveBuildTreeRPATH(const std::string& config) const if (this->GetPropertyAsBool("SKIP_BUILD_RPATH")) { return false; } - if (this->GetProperty("BUILD_RPATH")) { + std::string build_rpath; + if (this->GetBuildRPATH(config, build_rpath)) { return true; } if (cmLinkImplementationLibraries const* impl = @@ -6138,8 +6174,7 @@ cmGeneratorTarget::GetLinkImplementationLibrariesInternal( bool cmGeneratorTarget::IsNullImpliedByLinkLibraries( const std::string& p) const { - return this->LinkImplicitNullProperties.find(p) != - this->LinkImplicitNullProperties.end(); + return cmContains(this->LinkImplicitNullProperties, p); } void cmGeneratorTarget::ComputeLinkImplementationLibraries( @@ -6160,7 +6195,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( std::unique_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(*le); std::string const& evaluated = cge->Evaluate(this->LocalGenerator, config, false, head, &dagChecker); - cmSystemTools::ExpandListArgument(evaluated, llibs); + cmExpandList(evaluated, llibs); if (cge->GetHadHeadSensitiveCondition()) { impl.HadHeadSensitiveCondition = true; } @@ -6317,8 +6352,8 @@ bool cmGeneratorTarget::GetImplibGNUtoMS(std::string const& config, { if (this->HasImplibGNUtoMS(config) && gnuName.size() > 6 && gnuName.substr(gnuName.size() - 6) == ".dll.a") { - out = gnuName.substr(0, gnuName.size() - 6); - out += newExt ? newExt : ".lib"; + out = cmStrCat(cm::string_view(gnuName).substr(0, gnuName.size() - 6), + newExt ? newExt : ".lib"); return true; } return false; @@ -6337,15 +6372,24 @@ bool cmGeneratorTarget::HasImportLibrary(std::string const& config) const this->IsExecutableWithExports()) && // Assemblies which have only managed code do not have // import libraries. - this->GetManagedType(config) != ManagedType::Managed); + this->GetManagedType(config) != ManagedType::Managed) || + (this->Target->IsAIX() && this->IsExecutableWithExports()); +} + +bool cmGeneratorTarget::NeedImportLibraryName(std::string const& config) const +{ + return this->HasImportLibrary(config) || + // On DLL platforms we always generate the import library name + // just in case the sources have export markup. + (this->IsDLLPlatform() && + (this->GetType() == cmStateEnums::EXECUTABLE || + this->GetType() == cmStateEnums::MODULE_LIBRARY)); } std::string cmGeneratorTarget::GetSupportDirectory() const { - std::string dir = this->LocalGenerator->GetCurrentBinaryDirectory(); - dir += "/CMakeFiles"; - dir += "/"; - dir += this->GetName(); + std::string dir = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), + "/CMakeFiles/", this->GetName()); #if defined(__VMS) dir += "_dir"; #else diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 0e0ee6a..3874738 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -14,6 +14,7 @@ #include <set> #include <stddef.h> #include <string> +#include <unordered_map> #include <utility> #include <vector> @@ -25,6 +26,9 @@ class cmMakefile; class cmSourceFile; class cmTarget; +struct cmGeneratorExpressionContext; +struct cmGeneratorExpressionDAGChecker; + class cmGeneratorTarget { public: @@ -674,7 +678,14 @@ public: class TargetPropertyEntry; - bool HaveInstallTreeRPATH() const; + std::string EvaluateInterfaceProperty( + std::string const& prop, cmGeneratorExpressionContext* context, + cmGeneratorExpressionDAGChecker* dagCheckerParent) const; + + bool HaveInstallTreeRPATH(const std::string& config) const; + + bool GetBuildRPATH(const std::string& config, std::string& rpath) const; + bool GetInstallRPATH(const std::string& config, std::string& rpath) const; /** Whether this library has \@rpath and platform supports it. */ bool HasMacOSXRpathInstallNameDir(const std::string& config) const; @@ -740,9 +751,13 @@ private: mutable std::map<std::string, bool> DebugCompatiblePropertiesDone; - const char* GetFilePrefixInternal(cmStateEnums::ArtifactType artifact, + bool NeedImportLibraryName(std::string const& config) const; + + const char* GetFilePrefixInternal(std::string const& config, + cmStateEnums::ArtifactType artifact, const std::string& language = "") const; - const char* GetFileSuffixInternal(cmStateEnums::ArtifactType artifact, + const char* GetFileSuffixInternal(std::string const& config, + cmStateEnums::ArtifactType artifact, const std::string& language = "") const; std::string GetFullNameInternal(const std::string& config, @@ -842,6 +857,10 @@ private: mutable std::vector<AllConfigSource> AllConfigSources; void ComputeAllConfigSources() const; + mutable std::unordered_map<std::string, bool> MaybeInterfacePropertyExists; + bool MaybeHaveInterfaceProperty(std::string const& prop, + cmGeneratorExpressionContext* context) const; + std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries; std::vector<TargetPropertyEntry*> CompileOptionsEntries; std::vector<TargetPropertyEntry*> CompileFeaturesEntries; @@ -906,13 +925,15 @@ private: mutable bool DebugSourcesDone; mutable bool LinkImplementationLanguageIsContextDependent; mutable bool UtilityItemsDone; - bool DLLPlatform; bool ComputePDBOutputDir(const std::string& kind, const std::string& config, std::string& out) const; ManagedType CheckManagedType(std::string const& propval) const; + bool GetRPATH(const std::string& config, const std::string& prop, + std::string& rpath) const; + public: const std::vector<const cmGeneratorTarget*>& GetLinkImplementationClosure( const std::string& config) const; diff --git a/Source/cmGetCMakePropertyCommand.cxx b/Source/cmGetCMakePropertyCommand.cxx index fc82fee..ff4e312 100644 --- a/Source/cmGetCMakePropertyCommand.cxx +++ b/Source/cmGetCMakePropertyCommand.cxx @@ -4,19 +4,18 @@ #include <set> -#include "cmAlgorithms.h" +#include "cmExecutionStatus.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmState.h" - -class cmExecutionStatus; +#include "cmStringAlgorithms.h" // cmGetCMakePropertyCommand -bool cmGetCMakePropertyCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmGetCMakePropertyCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 2) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } @@ -24,29 +23,29 @@ bool cmGetCMakePropertyCommand::InitialPass( std::string output = "NOTFOUND"; if (args[1] == "VARIABLES") { - if (const char* varsProp = this->Makefile->GetProperty("VARIABLES")) { + if (const char* varsProp = status.GetMakefile().GetProperty("VARIABLES")) { output = varsProp; } } else if (args[1] == "MACROS") { output.clear(); - if (const char* macrosProp = this->Makefile->GetProperty("MACROS")) { + if (const char* macrosProp = status.GetMakefile().GetProperty("MACROS")) { output = macrosProp; } } else if (args[1] == "COMPONENTS") { const std::set<std::string>* components = - this->Makefile->GetGlobalGenerator()->GetInstallComponents(); + status.GetMakefile().GetGlobalGenerator()->GetInstallComponents(); output = cmJoin(*components, ";"); } else { const char* prop = nullptr; if (!args[1].empty()) { - prop = this->Makefile->GetState()->GetGlobalProperty(args[1]); + prop = status.GetMakefile().GetState()->GetGlobalProperty(args[1]); } if (prop) { output = prop; } } - this->Makefile->AddDefinition(variable, output.c_str()); + status.GetMakefile().AddDefinition(variable, output); return true; } diff --git a/Source/cmGetCMakePropertyCommand.h b/Source/cmGetCMakePropertyCommand.h index 1f29c78..7a6728c 100644 --- a/Source/cmGetCMakePropertyCommand.h +++ b/Source/cmGetCMakePropertyCommand.h @@ -8,21 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -class cmGetCMakePropertyCommand : public cmCommand -{ -public: - cmCommand* Clone() override { return new cmGetCMakePropertyCommand; } - - /** - * This is called when the command is first encountered in - * the input file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmGetCMakePropertyCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx index a92eb71..d078a7a 100644 --- a/Source/cmGetDirectoryPropertyCommand.cxx +++ b/Source/cmGetDirectoryPropertyCommand.cxx @@ -2,20 +2,25 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGetDirectoryPropertyCommand.h" +#include "cmExecutionStatus.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmExecutionStatus; +namespace { +void StoreResult(cmMakefile& makefile, std::string const& variable, + const char* prop); +} // cmGetDirectoryPropertyCommand -bool cmGetDirectoryPropertyCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 2) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } @@ -24,29 +29,27 @@ bool cmGetDirectoryPropertyCommand::InitialPass( ++i; // get the directory argument if there is one - cmMakefile* dir = this->Makefile; + cmMakefile* dir = &status.GetMakefile(); if (*i == "DIRECTORY") { ++i; if (i == args.end()) { - this->SetError( + status.SetError( "DIRECTORY argument provided without subsequent arguments"); return false; } std::string sd = *i; // make sure the start dir is a full path if (!cmSystemTools::FileIsFullPath(sd)) { - sd = this->Makefile->GetCurrentSourceDirectory(); - sd += "/"; - sd += *i; + sd = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', *i); } // The local generators are associated with collapsed paths. sd = cmSystemTools::CollapseFullPath(sd); // lookup the makefile from the directory name - dir = this->Makefile->GetGlobalGenerator()->FindMakefile(sd); + dir = status.GetMakefile().GetGlobalGenerator()->FindMakefile(sd); if (!dir) { - this->SetError( + status.SetError( "DIRECTORY argument provided but requested directory not found. " "This could be because the directory argument was invalid or, " "it is valid but has not been processed yet."); @@ -61,26 +64,27 @@ bool cmGetDirectoryPropertyCommand::InitialPass( if (*i == "DEFINITION") { ++i; if (i == args.end()) { - this->SetError("A request for a variable definition was made without " - "providing the name of the variable to get."); + status.SetError("A request for a variable definition was made without " + "providing the name of the variable to get."); return false; } std::string const& output = dir->GetSafeDefinition(*i); - this->Makefile->AddDefinition(variable, output.c_str()); + status.GetMakefile().AddDefinition(variable, output); return true; } const char* prop = nullptr; if (!i->empty()) { if (*i == "DEFINITIONS") { - switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0059)) { + switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0059)) { case cmPolicies::WARN: - this->Makefile->IssueMessage( + status.GetMakefile().IssueMessage( MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0059)); CM_FALLTHROUGH; case cmPolicies::OLD: - this->StoreResult(variable, this->Makefile->GetDefineFlagsCMP0059()); + StoreResult(status.GetMakefile(), variable, + status.GetMakefile().GetDefineFlagsCMP0059()); return true; case cmPolicies::NEW: case cmPolicies::REQUIRED_ALWAYS: @@ -90,16 +94,14 @@ bool cmGetDirectoryPropertyCommand::InitialPass( } prop = dir->GetProperty(*i); } - this->StoreResult(variable, prop); + StoreResult(status.GetMakefile(), variable, prop); return true; } -void cmGetDirectoryPropertyCommand::StoreResult(std::string const& variable, - const char* prop) +namespace { +void StoreResult(cmMakefile& makefile, std::string const& variable, + const char* prop) { - if (prop) { - this->Makefile->AddDefinition(variable, prop); - return; - } - this->Makefile->AddDefinition(variable, ""); + makefile.AddDefinition(variable, prop ? prop : ""); +} } diff --git a/Source/cmGetDirectoryPropertyCommand.h b/Source/cmGetDirectoryPropertyCommand.h index 02ea056..f356ea5 100644 --- a/Source/cmGetDirectoryPropertyCommand.h +++ b/Source/cmGetDirectoryPropertyCommand.h @@ -8,24 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -class cmGetDirectoryPropertyCommand : public cmCommand -{ -public: - cmCommand* Clone() override { return new cmGetDirectoryPropertyCommand; } - - /** - * This is called when the command is first encountered in - * the input file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - void StoreResult(const std::string& variable, const char* prop); -}; +bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx index 163b4c8..7d91a75 100644 --- a/Source/cmGetFilenameComponentCommand.cxx +++ b/Source/cmGetFilenameComponentCommand.cxx @@ -2,26 +2,26 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGetFilenameComponentCommand.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmExecutionStatus; - // cmGetFilenameComponentCommand -bool cmGetFilenameComponentCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmGetFilenameComponentCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 3) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } // Check and see if the value has been stored in the cache // already, if so use that value if (args.size() >= 4 && args.back() == "CACHE") { - const char* cacheValue = this->Makefile->GetDefinition(args.front()); - if (cacheValue && !cmSystemTools::IsNOTFOUND(cacheValue)) { + const char* cacheValue = status.GetMakefile().GetDefinition(args.front()); + if (cacheValue && !cmIsNOTFOUND(cacheValue)) { return true; } } @@ -32,7 +32,7 @@ bool cmGetFilenameComponentCommand::InitialPass( // Check the registry as the target application would view it. cmSystemTools::KeyWOW64 view = cmSystemTools::KeyWOW64_32; cmSystemTools::KeyWOW64 other_view = cmSystemTools::KeyWOW64_64; - if (this->Makefile->PlatformIs64Bit()) { + if (status.GetMakefile().PlatformIs64Bit()) { view = cmSystemTools::KeyWOW64_64; other_view = cmSystemTools::KeyWOW64_32; } @@ -64,7 +64,7 @@ bool cmGetFilenameComponentCommand::InitialPass( // First assume the path to the program was specified with no // arguments and with no quoting or escaping for spaces. // Only bother doing this if there is non-whitespace. - if (!cmSystemTools::TrimWhitespace(filename).empty()) { + if (!cmTrimWhitespace(filename).empty()) { result = cmSystemTools::FindProgram(filename); } @@ -96,7 +96,7 @@ bool cmGetFilenameComponentCommand::InitialPass( // If the path given is relative, evaluate it relative to the // current source directory unless the user passes a different // base directory. - std::string baseDir = this->Makefile->GetCurrentSourceDirectory(); + std::string baseDir = status.GetMakefile().GetCurrentSourceDirectory(); for (unsigned int i = 3; i < args.size(); ++i) { if (args[i] == "BASE_DIR") { ++i; @@ -113,24 +113,24 @@ bool cmGetFilenameComponentCommand::InitialPass( } } else { std::string err = "unknown component " + args[2]; - this->SetError(err); + status.SetError(err); return false; } if (args.size() >= 4 && args.back() == "CACHE") { if (!programArgs.empty() && !storeArgs.empty()) { - this->Makefile->AddCacheDefinition( + status.GetMakefile().AddCacheDefinition( storeArgs, programArgs.c_str(), "", args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING); } - this->Makefile->AddCacheDefinition( + status.GetMakefile().AddCacheDefinition( args.front(), result.c_str(), "", args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING); } else { if (!programArgs.empty() && !storeArgs.empty()) { - this->Makefile->AddDefinition(storeArgs, programArgs.c_str()); + status.GetMakefile().AddDefinition(storeArgs, programArgs); } - this->Makefile->AddDefinition(args.front(), result.c_str()); + status.GetMakefile().AddDefinition(args.front(), result); } return true; diff --git a/Source/cmGetFilenameComponentCommand.h b/Source/cmGetFilenameComponentCommand.h index 8c26655..db5293b 100644 --- a/Source/cmGetFilenameComponentCommand.h +++ b/Source/cmGetFilenameComponentCommand.h @@ -8,30 +8,15 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmGetFilenameComponentCommand +/** * \brief Get a specific component of a filename. * * cmGetFilenameComponentCommand is a utility command used to get the path, * name, extension or name without extension of a full filename. */ -class cmGetFilenameComponentCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmGetFilenameComponentCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmGetFilenameComponentCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index 039f439..e8e87e7 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -4,6 +4,7 @@ #include <sstream> +#include "cmExecutionStatus.h" #include "cmGlobalGenerator.h" #include "cmInstalledFile.h" #include "cmListFileCache.h" @@ -14,30 +15,70 @@ #include "cmPropertyDefinition.h" #include "cmSourceFile.h" #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetPropertyComputer.h" #include "cmTest.h" #include "cmake.h" -class cmExecutionStatus; class cmMessenger; -cmGetPropertyCommand::cmGetPropertyCommand() +namespace { +enum OutType { - this->InfoType = OutValue; + OutValue, + OutDefined, + OutBriefDoc, + OutFullDoc, + OutSet +}; + +// Implementation of result storage. +bool StoreResult(OutType infoType, cmMakefile& makefile, + const std::string& variable, const char* value); + +// Implementation of each property type. +bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name, + OutType infoType, const std::string& variable, + const std::string& propertyName); +bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name, + OutType infoType, const std::string& variable, + const std::string& propertyName); +bool HandleTargetMode(cmExecutionStatus& status, const std::string& name, + OutType infoType, const std::string& variable, + const std::string& propertyName); +bool HandleSourceMode(cmExecutionStatus& status, const std::string& name, + OutType infoType, const std::string& variable, + const std::string& propertyName); +bool HandleTestMode(cmExecutionStatus& status, const std::string& name, + OutType infoType, const std::string& variable, + const std::string& propertyName); +bool HandleVariableMode(cmExecutionStatus& status, const std::string& name, + OutType infoType, const std::string& variable, + const std::string& propertyName); +bool HandleCacheMode(cmExecutionStatus& status, const std::string& name, + OutType infoType, const std::string& variable, + const std::string& propertyName); +bool HandleInstallMode(cmExecutionStatus& status, const std::string& name, + OutType infoType, const std::string& variable, + const std::string& propertyName); } -bool cmGetPropertyCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmGetPropertyCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { + OutType infoType = OutValue; if (args.size() < 3) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } // The cmake variable in which to store the result. - this->Variable = args[0]; + const std::string variable = args[0]; + + std::string name; + std::string propertyName; // Get the scope from which to get the property. cmProperty::ScopeType scope; @@ -62,7 +103,7 @@ bool cmGetPropertyCommand::InitialPass(std::vector<std::string> const& args, e << "given invalid scope " << args[1] << ". " << "Valid scopes are " << "GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, VARIABLE, CACHE, INSTALL."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } @@ -80,86 +121,92 @@ bool cmGetPropertyCommand::InitialPass(std::vector<std::string> const& args, doing = DoingProperty; } else if (args[i] == "BRIEF_DOCS") { doing = DoingNone; - this->InfoType = OutBriefDoc; + infoType = OutBriefDoc; } else if (args[i] == "FULL_DOCS") { doing = DoingNone; - this->InfoType = OutFullDoc; + infoType = OutFullDoc; } else if (args[i] == "SET") { doing = DoingNone; - this->InfoType = OutSet; + infoType = OutSet; } else if (args[i] == "DEFINED") { doing = DoingNone; - this->InfoType = OutDefined; + infoType = OutDefined; } else if (doing == DoingName) { doing = DoingNone; - this->Name = args[i]; + name = args[i]; } else if (doing == DoingProperty) { doing = DoingNone; - this->PropertyName = args[i]; + propertyName = args[i]; } else { std::ostringstream e; e << "given invalid argument \"" << args[i] << "\"."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } // Make sure a property name was found. - if (this->PropertyName.empty()) { - this->SetError("not given a PROPERTY <name> argument."); + if (propertyName.empty()) { + status.SetError("not given a PROPERTY <name> argument."); return false; } // Compute requested output. - if (this->InfoType == OutBriefDoc) { + if (infoType == OutBriefDoc) { // Lookup brief documentation. std::string output; if (cmPropertyDefinition const* def = - this->Makefile->GetState()->GetPropertyDefinition(this->PropertyName, - scope)) { + status.GetMakefile().GetState()->GetPropertyDefinition(propertyName, + scope)) { output = def->GetShortDescription(); } else { output = "NOTFOUND"; } - this->Makefile->AddDefinition(this->Variable, output.c_str()); - } else if (this->InfoType == OutFullDoc) { + status.GetMakefile().AddDefinition(variable, output); + } else if (infoType == OutFullDoc) { // Lookup full documentation. std::string output; if (cmPropertyDefinition const* def = - this->Makefile->GetState()->GetPropertyDefinition(this->PropertyName, - scope)) { + status.GetMakefile().GetState()->GetPropertyDefinition(propertyName, + scope)) { output = def->GetFullDescription(); } else { output = "NOTFOUND"; } - this->Makefile->AddDefinition(this->Variable, output.c_str()); - } else if (this->InfoType == OutDefined) { + status.GetMakefile().AddDefinition(variable, output); + } else if (infoType == OutDefined) { // Lookup if the property is defined - if (this->Makefile->GetState()->GetPropertyDefinition(this->PropertyName, - scope)) { - this->Makefile->AddDefinition(this->Variable, "1"); + if (status.GetMakefile().GetState()->GetPropertyDefinition(propertyName, + scope)) { + status.GetMakefile().AddDefinition(variable, "1"); } else { - this->Makefile->AddDefinition(this->Variable, "0"); + status.GetMakefile().AddDefinition(variable, "0"); } } else { // Dispatch property getting. switch (scope) { case cmProperty::GLOBAL: - return this->HandleGlobalMode(); + return HandleGlobalMode(status, name, infoType, variable, + propertyName); case cmProperty::DIRECTORY: - return this->HandleDirectoryMode(); + return HandleDirectoryMode(status, name, infoType, variable, + propertyName); case cmProperty::TARGET: - return this->HandleTargetMode(); + return HandleTargetMode(status, name, infoType, variable, + propertyName); case cmProperty::SOURCE_FILE: - return this->HandleSourceMode(); + return HandleSourceMode(status, name, infoType, variable, + propertyName); case cmProperty::TEST: - return this->HandleTestMode(); + return HandleTestMode(status, name, infoType, variable, propertyName); case cmProperty::VARIABLE: - return this->HandleVariableMode(); + return HandleVariableMode(status, name, infoType, variable, + propertyName); case cmProperty::CACHE: - return this->HandleCacheMode(); + return HandleCacheMode(status, name, infoType, variable, propertyName); case cmProperty::INSTALL: - return this->HandleInstallMode(); + return HandleInstallMode(status, name, infoType, variable, + propertyName); case cmProperty::CACHED_VARIABLE: break; // should never happen @@ -169,58 +216,64 @@ bool cmGetPropertyCommand::InitialPass(std::vector<std::string> const& args, return true; } -bool cmGetPropertyCommand::StoreResult(const char* value) +namespace { + +bool StoreResult(OutType infoType, cmMakefile& makefile, + const std::string& variable, const char* value) { - if (this->InfoType == OutSet) { - this->Makefile->AddDefinition(this->Variable, value ? "1" : "0"); - } else // if(this->InfoType == OutValue) + if (infoType == OutSet) { + makefile.AddDefinition(variable, value ? "1" : "0"); + } else // if(infoType == OutValue) { if (value) { - this->Makefile->AddDefinition(this->Variable, value); + makefile.AddDefinition(variable, value); } else { - this->Makefile->RemoveDefinition(this->Variable); + makefile.RemoveDefinition(variable); } } return true; } -bool cmGetPropertyCommand::HandleGlobalMode() +bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name, + OutType infoType, const std::string& variable, + const std::string& propertyName) { - if (!this->Name.empty()) { - this->SetError("given name for GLOBAL scope."); + if (!name.empty()) { + status.SetError("given name for GLOBAL scope."); return false; } // Get the property. - cmake* cm = this->Makefile->GetCMakeInstance(); - return this->StoreResult( - cm->GetState()->GetGlobalProperty(this->PropertyName)); + cmake* cm = status.GetMakefile().GetCMakeInstance(); + return StoreResult(infoType, status.GetMakefile(), variable, + cm->GetState()->GetGlobalProperty(propertyName)); } -bool cmGetPropertyCommand::HandleDirectoryMode() +bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name, + OutType infoType, const std::string& variable, + const std::string& propertyName) { // Default to the current directory. - cmMakefile* mf = this->Makefile; + cmMakefile* mf = &status.GetMakefile(); // Lookup the directory if given. - if (!this->Name.empty()) { + if (!name.empty()) { // Construct the directory name. Interpret relative paths with // respect to the current directory. - std::string dir = this->Name; + std::string dir = name; if (!cmSystemTools::FileIsFullPath(dir)) { - dir = this->Makefile->GetCurrentSourceDirectory(); - dir += "/"; - dir += this->Name; + dir = + cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', name); } // The local generators are associated with collapsed paths. dir = cmSystemTools::CollapseFullPath(dir); // Lookup the generator. - mf = this->Makefile->GetGlobalGenerator()->FindMakefile(dir); + mf = status.GetMakefile().GetGlobalGenerator()->FindMakefile(dir); if (!mf) { // Could not find the directory. - this->SetError( + status.SetError( "DIRECTORY scope provided but requested directory was not found. " "This could be because the directory argument was invalid or, " "it is valid but has not been processed yet."); @@ -228,14 +281,15 @@ bool cmGetPropertyCommand::HandleDirectoryMode() } } - if (this->PropertyName == "DEFINITIONS") { + if (propertyName == "DEFINITIONS") { switch (mf->GetPolicyStatus(cmPolicies::CMP0059)) { case cmPolicies::WARN: mf->IssueMessage(MessageType::AUTHOR_WARNING, cmPolicies::GetPolicyWarning(cmPolicies::CMP0059)); CM_FALLTHROUGH; case cmPolicies::OLD: - return this->StoreResult(mf->GetDefineFlagsCMP0059()); + return StoreResult(infoType, status.GetMakefile(), variable, + mf->GetDefineFlagsCMP0059()); case cmPolicies::NEW: case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::REQUIRED_IF_USED: @@ -244,124 +298,142 @@ bool cmGetPropertyCommand::HandleDirectoryMode() } // Get the property. - return this->StoreResult(mf->GetProperty(this->PropertyName)); + return StoreResult(infoType, status.GetMakefile(), variable, + mf->GetProperty(propertyName)); } -bool cmGetPropertyCommand::HandleTargetMode() +bool HandleTargetMode(cmExecutionStatus& status, const std::string& name, + OutType infoType, const std::string& variable, + const std::string& propertyName) { - if (this->Name.empty()) { - this->SetError("not given name for TARGET scope."); + if (name.empty()) { + status.SetError("not given name for TARGET scope."); return false; } - if (cmTarget* target = this->Makefile->FindTargetToUse(this->Name)) { - if (this->PropertyName == "ALIASED_TARGET") { - if (this->Makefile->IsAlias(this->Name)) { - return this->StoreResult(target->GetName().c_str()); + if (cmTarget* target = status.GetMakefile().FindTargetToUse(name)) { + if (propertyName == "ALIASED_TARGET") { + if (status.GetMakefile().IsAlias(name)) { + return StoreResult(infoType, status.GetMakefile(), variable, + target->GetName().c_str()); } - return this->StoreResult(nullptr); + return StoreResult(infoType, status.GetMakefile(), variable, nullptr); } const char* prop_cstr = nullptr; - cmListFileBacktrace bt = this->Makefile->GetBacktrace(); - cmMessenger* messenger = this->Makefile->GetMessenger(); + cmListFileBacktrace bt = status.GetMakefile().GetBacktrace(); + cmMessenger* messenger = status.GetMakefile().GetMessenger(); if (cmTargetPropertyComputer::PassesWhitelist( - target->GetType(), this->PropertyName, messenger, bt)) { - prop_cstr = - target->GetComputedProperty(this->PropertyName, messenger, bt); + target->GetType(), propertyName, messenger, bt)) { + prop_cstr = target->GetComputedProperty(propertyName, messenger, bt); if (!prop_cstr) { - prop_cstr = target->GetProperty(this->PropertyName); + prop_cstr = target->GetProperty(propertyName); } } - return this->StoreResult(prop_cstr); + return StoreResult(infoType, status.GetMakefile(), variable, prop_cstr); } std::ostringstream e; - e << "could not find TARGET " << this->Name + e << "could not find TARGET " << name << ". Perhaps it has not yet been created."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } -bool cmGetPropertyCommand::HandleSourceMode() +bool HandleSourceMode(cmExecutionStatus& status, const std::string& name, + OutType infoType, const std::string& variable, + const std::string& propertyName) { - if (this->Name.empty()) { - this->SetError("not given name for SOURCE scope."); + if (name.empty()) { + status.SetError("not given name for SOURCE scope."); return false; } // Get the source file. - if (cmSourceFile* sf = this->Makefile->GetOrCreateSource(this->Name)) { - return this->StoreResult(sf->GetPropertyForUser(this->PropertyName)); + if (cmSourceFile* sf = status.GetMakefile().GetOrCreateSource(name)) { + return StoreResult(infoType, status.GetMakefile(), variable, + sf->GetPropertyForUser(propertyName)); } std::ostringstream e; - e << "given SOURCE name that could not be found or created: " << this->Name; - this->SetError(e.str()); + e << "given SOURCE name that could not be found or created: " << name; + status.SetError(e.str()); return false; } -bool cmGetPropertyCommand::HandleTestMode() +bool HandleTestMode(cmExecutionStatus& status, const std::string& name, + OutType infoType, const std::string& variable, + const std::string& propertyName) { - if (this->Name.empty()) { - this->SetError("not given name for TEST scope."); + if (name.empty()) { + status.SetError("not given name for TEST scope."); return false; } // Loop over all tests looking for matching names. - if (cmTest* test = this->Makefile->GetTest(this->Name)) { - return this->StoreResult(test->GetProperty(this->PropertyName)); + if (cmTest* test = status.GetMakefile().GetTest(name)) { + return StoreResult(infoType, status.GetMakefile(), variable, + test->GetProperty(propertyName)); } // If not found it is an error. std::ostringstream e; - e << "given TEST name that does not exist: " << this->Name; - this->SetError(e.str()); + e << "given TEST name that does not exist: " << name; + status.SetError(e.str()); return false; } -bool cmGetPropertyCommand::HandleVariableMode() +bool HandleVariableMode(cmExecutionStatus& status, const std::string& name, + OutType infoType, const std::string& variable, + const std::string& propertyName) { - if (!this->Name.empty()) { - this->SetError("given name for VARIABLE scope."); + if (!name.empty()) { + status.SetError("given name for VARIABLE scope."); return false; } - return this->StoreResult(this->Makefile->GetDefinition(this->PropertyName)); + return StoreResult(infoType, status.GetMakefile(), variable, + status.GetMakefile().GetDefinition(propertyName)); } -bool cmGetPropertyCommand::HandleCacheMode() +bool HandleCacheMode(cmExecutionStatus& status, const std::string& name, + OutType infoType, const std::string& variable, + const std::string& propertyName) { - if (this->Name.empty()) { - this->SetError("not given name for CACHE scope."); + if (name.empty()) { + status.SetError("not given name for CACHE scope."); return false; } const char* value = nullptr; - if (this->Makefile->GetState()->GetCacheEntryValue(this->Name)) { - value = this->Makefile->GetState()->GetCacheEntryProperty( - this->Name, this->PropertyName); + if (status.GetMakefile().GetState()->GetCacheEntryValue(name)) { + value = status.GetMakefile().GetState()->GetCacheEntryProperty( + name, propertyName); } - this->StoreResult(value); + StoreResult(infoType, status.GetMakefile(), variable, value); return true; } -bool cmGetPropertyCommand::HandleInstallMode() +bool HandleInstallMode(cmExecutionStatus& status, const std::string& name, + OutType infoType, const std::string& variable, + const std::string& propertyName) { - if (this->Name.empty()) { - this->SetError("not given name for INSTALL scope."); + if (name.empty()) { + status.SetError("not given name for INSTALL scope."); return false; } // Get the installed file. - cmake* cm = this->Makefile->GetCMakeInstance(); + cmake* cm = status.GetMakefile().GetCMakeInstance(); if (cmInstalledFile* file = - cm->GetOrCreateInstalledFile(this->Makefile, this->Name)) { + cm->GetOrCreateInstalledFile(&status.GetMakefile(), name)) { std::string value; - bool isSet = file->GetProperty(this->PropertyName, value); + bool isSet = file->GetProperty(propertyName, value); - return this->StoreResult(isSet ? value.c_str() : nullptr); + return StoreResult(infoType, status.GetMakefile(), variable, + isSet ? value.c_str() : nullptr); } std::ostringstream e; - e << "given INSTALL name that could not be found or created: " << this->Name; - this->SetError(e.str()); + e << "given INSTALL name that could not be found or created: " << name; + status.SetError(e.str()); return false; } +} diff --git a/Source/cmGetPropertyCommand.h b/Source/cmGetPropertyCommand.h index c3f653e..cc600f4 100644 --- a/Source/cmGetPropertyCommand.h +++ b/Source/cmGetPropertyCommand.h @@ -8,50 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -class cmGetPropertyCommand : public cmCommand -{ -public: - cmGetPropertyCommand(); - - cmCommand* Clone() override { return new cmGetPropertyCommand; } - - /** - * This is called when the command is first encountered in - * the input file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - enum OutType - { - OutValue, - OutDefined, - OutBriefDoc, - OutFullDoc, - OutSet - }; - std::string Variable; - std::string Name; - std::string PropertyName; - OutType InfoType; - - // Implementation of result storage. - bool StoreResult(const char* value); - - // Implementation of each property type. - bool HandleGlobalMode(); - bool HandleDirectoryMode(); - bool HandleTargetMode(); - bool HandleSourceMode(); - bool HandleTestMode(); - bool HandleVariableMode(); - bool HandleCacheMode(); - bool HandleInstallMode(); -}; +bool cmGetPropertyCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmGetSourceFilePropertyCommand.cxx b/Source/cmGetSourceFilePropertyCommand.cxx index 75879a5..a16076d 100644 --- a/Source/cmGetSourceFilePropertyCommand.cxx +++ b/Source/cmGetSourceFilePropertyCommand.cxx @@ -25,7 +25,7 @@ bool cmGetSourceFilePropertyCommand::InitialPass( } if (sf) { if (args[2] == "LANGUAGE") { - this->Makefile->AddDefinition(var, sf->GetLanguage().c_str()); + this->Makefile->AddDefinition(var, sf->GetLanguage()); return true; } const char* prop = nullptr; diff --git a/Source/cmGetSourceFilePropertyCommand.h b/Source/cmGetSourceFilePropertyCommand.h index 43bc330..387a7f4 100644 --- a/Source/cmGetSourceFilePropertyCommand.h +++ b/Source/cmGetSourceFilePropertyCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -15,7 +17,10 @@ class cmExecutionStatus; class cmGetSourceFilePropertyCommand : public cmCommand { public: - cmCommand* Clone() override { return new cmGetSourceFilePropertyCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmGetSourceFilePropertyCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx index fc0e9c6..07aaf02 100644 --- a/Source/cmGetTargetPropertyCommand.cxx +++ b/Source/cmGetTargetPropertyCommand.cxx @@ -75,9 +75,9 @@ bool cmGetTargetPropertyCommand::InitialPass( } } if (prop_exists) { - this->Makefile->AddDefinition(var, prop.c_str()); + this->Makefile->AddDefinition(var, prop); return true; } - this->Makefile->AddDefinition(var, (var + "-NOTFOUND").c_str()); + this->Makefile->AddDefinition(var, var + "-NOTFOUND"); return true; } diff --git a/Source/cmGetTargetPropertyCommand.h b/Source/cmGetTargetPropertyCommand.h index 63ee5fd..1a53195 100644 --- a/Source/cmGetTargetPropertyCommand.h +++ b/Source/cmGetTargetPropertyCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -15,7 +17,10 @@ class cmExecutionStatus; class cmGetTargetPropertyCommand : public cmCommand { public: - cmCommand* Clone() override { return new cmGetTargetPropertyCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmGetTargetPropertyCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmGetTestPropertyCommand.h b/Source/cmGetTestPropertyCommand.h index 4a74f59..a53a7f7 100644 --- a/Source/cmGetTestPropertyCommand.h +++ b/Source/cmGetTestPropertyCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -15,7 +17,10 @@ class cmExecutionStatus; class cmGetTestPropertyCommand : public cmCommand { public: - cmCommand* Clone() override { return new cmGetTestPropertyCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmGetTestPropertyCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index b80da72..e7b20ed 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -18,13 +18,16 @@ #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include <algorithm> +#include <memory> #include <ostream> #include <set> #include <utility> +#include <vector> cmGhsMultiTargetGenerator::cmGhsMultiTargetGenerator(cmGeneratorTarget* target) : GeneratorTarget(target) @@ -72,8 +75,8 @@ void cmGhsMultiTargetGenerator::Generate() break; } case cmStateEnums::SHARED_LIBRARY: { - std::string msg = "add_library(<name> SHARED ...) not supported: "; - msg += this->Name; + std::string msg = + cmStrCat("add_library(<name> SHARED ...) not supported: ", this->Name); cmSystemTools::Message(msg); return; } @@ -84,8 +87,8 @@ void cmGhsMultiTargetGenerator::Generate() break; } case cmStateEnums::MODULE_LIBRARY: { - std::string msg = "add_library(<name> MODULE ...) not supported: "; - msg += this->Name; + std::string msg = + cmStrCat("add_library(<name> MODULE ...) not supported: ", this->Name); cmSystemTools::Message(msg); return; } @@ -120,10 +123,9 @@ void cmGhsMultiTargetGenerator::Generate() void cmGhsMultiTargetGenerator::GenerateTarget() { // Open the target file in copy-if-different mode. - std::string fproj = this->LocalGenerator->GetCurrentBinaryDirectory(); - fproj += "/"; - fproj += this->Name; - fproj += cmGlobalGhsMultiGenerator::FILE_EXTENSION; + std::string fproj = + cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/', + this->Name, cmGlobalGhsMultiGenerator::FILE_EXTENSION); cmGeneratedFileStream fout(fproj); fout.SetCopyIfDifferent(true); @@ -344,12 +346,11 @@ void cmGhsMultiTargetGenerator::WriteBuildEventsHelper( for (cmCustomCommand const& cc : ccv) { cmCustomCommandGenerator ccg(cc, this->ConfigName, this->LocalGenerator); // Open the filestream for this custom command - std::string fname = this->LocalGenerator->GetCurrentBinaryDirectory(); - fname += - "/" + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); - fname += "/" + this->Name + "_" + name; - fname += std::to_string(cmdcount++); - fname += this->CmdWindowsShell ? ".bat" : ".sh"; + std::string fname = + cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/', + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), + '/', this->Name, '_', name, cmdcount++, + this->CmdWindowsShell ? ".bat" : ".sh"); cmGeneratedFileStream f(fname); f.SetCopyIfDifferent(true); this->WriteCustomCommandsHelper(f, ccg); @@ -392,8 +393,7 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper( // Echo the custom command's comment text. const char* comment = ccg.GetComment(); if (comment && *comment) { - std::string echocmd = "echo "; - echocmd += comment; + std::string echocmd = cmStrCat("echo ", comment); cmdLines.push_back(std::move(echocmd)); } @@ -440,12 +440,12 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper( // This command was specified as a path to a file in the // current directory. Add a leading "./" so it can run // without the current directory being in the search path. - cmd = "./" + cmd; + cmd = cmStrCat("./", cmd); } cmd = this->LocalGenerator->ConvertToOutputFormat( cmd, cmOutputConverter::SHELL); if (useCall) { - cmd = "call " + cmd; + cmd = cmStrCat("call ", cmd); } ccg.AppendArguments(c, cmd); cmdLines.push_back(std::move(cmd)); @@ -465,8 +465,7 @@ void cmGhsMultiTargetGenerator::WriteSourceProperty( { const char* prop = sf->GetProperty(propName); if (prop) { - std::vector<std::string> list; - cmSystemTools::ExpandListArgument(prop, list); + std::vector<std::string> list = cmExpandedList(prop); for (auto& p : list) { fout << " " << propFlag << p << std::endl; } @@ -558,24 +557,19 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj) for (auto& sg : groupFilesList) { std::ostream* fout; bool useProjectFile = - cmSystemTools::IsOn( - this->GeneratorTarget->GetProperty("GHS_NO_SOURCE_GROUP_FILE")) || - cmSystemTools::IsOn( - this->Makefile->GetDefinition("CMAKE_GHS_NO_SOURCE_GROUP_FILE")); + cmIsOn(this->GeneratorTarget->GetProperty("GHS_NO_SOURCE_GROUP_FILE")) || + cmIsOn(this->Makefile->GetDefinition("CMAKE_GHS_NO_SOURCE_GROUP_FILE")); if (useProjectFile || sg.empty()) { fout = &fout_proj; } else { // Open the filestream in copy-if-different mode. std::string gname = sg; cmsys::SystemTools::ReplaceString(gname, "\\", "_"); - std::string lpath = - this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); - lpath += "/"; - lpath += gname; - lpath += cmGlobalGhsMultiGenerator::FILE_EXTENSION; - std::string fpath = this->LocalGenerator->GetCurrentBinaryDirectory(); - fpath += "/"; - fpath += lpath; + std::string lpath = cmStrCat( + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), '/', + gname, cmGlobalGhsMultiGenerator::FILE_EXTENSION); + std::string fpath = cmStrCat( + this->LocalGenerator->GetCurrentBinaryDirectory(), '/', lpath); cmGeneratedFileStream* f = new cmGeneratedFileStream(fpath); f->SetCopyIfDifferent(true); gfiles.push_back(f); @@ -667,14 +661,12 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj) this->LocalGenerator); // Open the filestream for this custom command - std::string fname = - this->LocalGenerator->GetCurrentBinaryDirectory(); - fname += "/" + - this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); - fname += "/" + this->Name + "_cc"; - fname += std::to_string(cmdcount++) + "_"; - fname += (sf->GetLocation()).GetName(); - fname += this->CmdWindowsShell ? ".bat" : ".sh"; + std::string fname = cmStrCat( + this->LocalGenerator->GetCurrentBinaryDirectory(), '/', + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), + '/', this->Name, "_cc", cmdcount++, '_', + (sf->GetLocation()).GetName(), + this->CmdWindowsShell ? ".bat" : ".sh"); cmGeneratedFileStream f(fname); f.SetCopyIfDifferent(true); this->WriteCustomCommandsHelper(f, ccg); @@ -737,8 +729,7 @@ bool cmGhsMultiTargetGenerator::DetermineIfIntegrityApp() { const char* p = this->GeneratorTarget->GetProperty("ghs_integrity_app"); if (p) { - return cmSystemTools::IsOn( - this->GeneratorTarget->GetProperty("ghs_integrity_app")); + return cmIsOn(this->GeneratorTarget->GetProperty("ghs_integrity_app")); } std::vector<cmSourceFile*> sources; this->GeneratorTarget->GetSourceFiles(sources, this->ConfigName); diff --git a/Source/cmGlobVerificationManager.cxx b/Source/cmGlobVerificationManager.cxx index 9fb4170..72451b2 100644 --- a/Source/cmGlobVerificationManager.cxx +++ b/Source/cmGlobVerificationManager.cxx @@ -7,6 +7,7 @@ #include "cmGeneratedFileStream.h" #include "cmListFileCache.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVersion.h" @@ -16,8 +17,7 @@ bool cmGlobVerificationManager::SaveVerificationScript(const std::string& path) return true; } - std::string scriptFile = path; - scriptFile += "/CMakeFiles"; + std::string scriptFile = cmStrCat(path, "/CMakeFiles"); std::string stampFile = scriptFile; cmSystemTools::MakeDirectory(scriptFile); scriptFile += "/VerifyGlobs.cmake"; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 9afc15a..363ad6e 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -44,7 +44,7 @@ #include "cmWorkingDirectory.h" #include "cmake.h" -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) # include "cmCryptoHash.h" # include "cmQtAutoGenGlobalInitializer.h" # include "cm_jsoncpp_value.h" @@ -92,7 +92,6 @@ cmGlobalGenerator::cmGlobalGenerator(cmake* cm) // how long to let try compiles run this->TryCompileTimeout = cmDuration::zero(); - this->ExtraGenerator = nullptr; this->CurrentConfigureMakefile = nullptr; this->TryCompileOuterMakefile = nullptr; @@ -113,10 +112,9 @@ cmGlobalGenerator::cmGlobalGenerator(cmake* cm) cmGlobalGenerator::~cmGlobalGenerator() { this->ClearGeneratorMembers(); - delete this->ExtraGenerator; } -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) Json::Value cmGlobalGenerator::GetJson() const { Json::Value generator = Json::objectValue; @@ -188,15 +186,15 @@ std::string cmGlobalGenerator::SelectMakeProgram( const std::string& inMakeProgram, const std::string& makeDefault) const { std::string makeProgram = inMakeProgram; - if (cmSystemTools::IsOff(makeProgram)) { + if (cmIsOff(makeProgram)) { const char* makeProgramCSTR = this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM"); - if (cmSystemTools::IsOff(makeProgramCSTR)) { + if (cmIsOff(makeProgramCSTR)) { makeProgram = makeDefault; } else { makeProgram = makeProgramCSTR; } - if (cmSystemTools::IsOff(makeProgram) && !makeProgram.empty()) { + if (cmIsOff(makeProgram) && !makeProgram.empty()) { makeProgram = "CMAKE_MAKE_PROGRAM-NOTFOUND"; } } @@ -207,9 +205,7 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang, cmMakefile* mf, bool optional) const { - std::string langComp = "CMAKE_"; - langComp += lang; - langComp += "_COMPILER"; + std::string langComp = cmStrCat("CMAKE_", lang, "_COMPILER"); if (!mf->GetDefinition(langComp)) { if (!optional) { @@ -302,7 +298,7 @@ bool cmGlobalGenerator::CheckTargetsForMissingSources() const if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET || target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY || target->GetType() == cmStateEnums::TargetType::UTILITY || - cmSystemTools::IsOn(target->GetProperty("ghs_integrity_app"))) { + cmIsOn(target->GetProperty("ghs_integrity_app"))) { continue; } @@ -370,8 +366,7 @@ bool cmGlobalGenerator::IsExportedTargetsFile( if (it == this->BuildExportSets.end()) { return false; } - return this->BuildExportExportSets.find(filename) == - this->BuildExportExportSets.end(); + return !cmContains(this->BuildExportExportSets, filename); } // Find the make program for the generator, required for try compiles @@ -384,14 +379,14 @@ bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf) return false; } if (!mf->GetDefinition("CMAKE_MAKE_PROGRAM") || - cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) { + cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) { std::string setMakeProgram = mf->GetModulesFile(this->FindMakeProgramFile); if (!setMakeProgram.empty()) { mf->ReadListFile(setMakeProgram); } } if (!mf->GetDefinition("CMAKE_MAKE_PROGRAM") || - cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) { + cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) { std::ostringstream err; err << "CMake was unable to find a build program corresponding to \"" << this->GetName() << "\". CMAKE_MAKE_PROGRAM is not set. You " @@ -411,9 +406,7 @@ bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf) std::string saveFile = file; cmSystemTools::GetShortPath(makeProgram, makeProgram); cmSystemTools::SplitProgramPath(makeProgram, dir, file); - makeProgram = dir; - makeProgram += "/"; - makeProgram += saveFile; + makeProgram = cmStrCat(dir, '/', saveFile); mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram.c_str(), "make program", cmStateEnums::FILEPATH); } @@ -499,7 +492,7 @@ void cmGlobalGenerator::EnableLanguage( if (lang == "NONE") { this->SetLanguageEnabled("NONE", mf); } else { - if (this->LanguagesReady.find(lang) == this->LanguagesReady.end()) { + if (!cmContains(this->LanguagesReady, lang)) { std::ostringstream e; e << "The test project needs language " << lang << " which is not enabled."; @@ -514,9 +507,9 @@ void cmGlobalGenerator::EnableLanguage( bool fatalError = false; - mf->AddDefinition("RUN_CONFIGURE", true); - std::string rootBin = this->CMakeInstance->GetHomeOutputDirectory(); - rootBin += "/CMakeFiles"; + mf->AddDefinitionBool("RUN_CONFIGURE", true); + std::string rootBin = + cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(), "/CMakeFiles"); // If the configuration files path has been set, // then we are in a try compile and need to copy the enable language @@ -524,11 +517,11 @@ void cmGlobalGenerator::EnableLanguage( if (!this->ConfiguredFilesPath.empty()) { rootBin = this->ConfiguredFilesPath; } - rootBin += "/"; + rootBin += '/'; rootBin += cmVersion::GetCMakeVersion(); // set the dir for parent files so they can be used by modules - mf->AddDefinition("CMAKE_PLATFORM_INFO_DIR", rootBin.c_str()); + mf->AddDefinition("CMAKE_PLATFORM_INFO_DIR", rootBin); if (!this->CMakeInstance->GetIsInTryCompile()) { // Keep a mark in the cache to indicate that we've initialized the @@ -588,16 +581,14 @@ void cmGlobalGenerator::EnableLanguage( windowsVersionString << osviex.dwMajorVersion << "." << osviex.dwMinorVersion << "." << osviex.dwBuildNumber; - mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION", - windowsVersionString.str().c_str()); + mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION", windowsVersionString.str()); #endif // Read the DetermineSystem file std::string systemFile = mf->GetModulesFile("CMakeDetermineSystem.cmake"); mf->ReadListFile(systemFile); // load the CMakeSystem.cmake from the binary directory // this file is configured by the CMakeDetermineSystem.cmake file - fpath = rootBin; - fpath += "/CMakeSystem.cmake"; + fpath = cmStrCat(rootBin, "/CMakeSystem.cmake"); mf->ReadListFile(fpath); } @@ -663,14 +654,9 @@ void cmGlobalGenerator::EnableLanguage( this->SetLanguageEnabled("NONE", mf); continue; } - std::string loadedLang = "CMAKE_"; - loadedLang += lang; - loadedLang += "_COMPILER_LOADED"; + std::string loadedLang = cmStrCat("CMAKE_", lang, "_COMPILER_LOADED"); if (!mf->GetDefinition(loadedLang)) { - fpath = rootBin; - fpath += "/CMake"; - fpath += lang; - fpath += "Compiler.cmake"; + fpath = cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake"); // If the existing build tree was already configured with this // version of CMake then try to load the configured file first @@ -697,9 +683,8 @@ void cmGlobalGenerator::EnableLanguage( } // if the CMake(LANG)Compiler.cmake file was not found then // load CMakeDetermine(LANG)Compiler.cmake - std::string determineCompiler = "CMakeDetermine"; - determineCompiler += lang; - determineCompiler += "Compiler.cmake"; + std::string determineCompiler = + cmStrCat("CMakeDetermine", lang, "Compiler.cmake"); std::string determineFile = mf->GetModulesFile(determineCompiler); if (!mf->ReadListFile(determineFile)) { cmSystemTools::Error("Could not find cmake module file: " + @@ -715,27 +700,19 @@ void cmGlobalGenerator::EnableLanguage( // put ${CMake_(LANG)_COMPILER_ENV_VAR}=${CMAKE_(LANG)_COMPILER // into the environment, in case user scripts want to run // configure, or sub cmakes - std::string compilerName = "CMAKE_"; - compilerName += lang; - compilerName += "_COMPILER"; - std::string compilerEnv = "CMAKE_"; - compilerEnv += lang; - compilerEnv += "_COMPILER_ENV_VAR"; + std::string compilerName = cmStrCat("CMAKE_", lang, "_COMPILER"); + std::string compilerEnv = + cmStrCat("CMAKE_", lang, "_COMPILER_ENV_VAR"); const std::string& envVar = mf->GetRequiredDefinition(compilerEnv); const std::string& envVarValue = mf->GetRequiredDefinition(compilerName); - std::string env = envVar; - env += "="; - env += envVarValue; + std::string env = cmStrCat(envVar, '=', envVarValue); cmSystemTools::PutEnv(env); } // if determineLanguage was called then load the file it // configures CMake(LANG)Compiler.cmake - fpath = rootBin; - fpath += "/CMake"; - fpath += lang; - fpath += "Compiler.cmake"; + fpath = cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake"); if (!mf->ReadListFile(fpath)) { cmSystemTools::Error("Could not find cmake module file: " + fpath); } @@ -766,16 +743,11 @@ void cmGlobalGenerator::EnableLanguage( } // Check that the compiler was found. - std::string compilerName = "CMAKE_"; - compilerName += lang; - compilerName += "_COMPILER"; - std::string compilerEnv = "CMAKE_"; - compilerEnv += lang; - compilerEnv += "_COMPILER_ENV_VAR"; + std::string compilerName = cmStrCat("CMAKE_", lang, "_COMPILER"); + std::string compilerEnv = cmStrCat("CMAKE_", lang, "_COMPILER_ENV_VAR"); std::ostringstream noCompiler; const char* compilerFile = mf->GetDefinition(compilerName); - if (!compilerFile || !*compilerFile || - cmSystemTools::IsNOTFOUND(compilerFile)) { + if (!compilerFile || !*compilerFile || cmIsNOTFOUND(compilerFile)) { /* clang-format off */ noCompiler << "No " << compilerName << " could be found.\n" @@ -806,10 +778,8 @@ void cmGlobalGenerator::EnableLanguage( if (!optional) { // The compiler was not found and it is not optional. Remove // CMake(LANG)Compiler.cmake so we try again next time CMake runs. - std::string compilerLangFile = rootBin; - compilerLangFile += "/CMake"; - compilerLangFile += lang; - compilerLangFile += "Compiler.cmake"; + std::string compilerLangFile = + cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake"); cmSystemTools::RemoveFile(compilerLangFile); if (!this->CMakeInstance->GetIsInTryCompile()) { this->PrintCompilerAdvice(noCompiler, lang, @@ -820,13 +790,10 @@ void cmGlobalGenerator::EnableLanguage( } } - std::string langLoadedVar = "CMAKE_"; - langLoadedVar += lang; - langLoadedVar += "_INFORMATION_LOADED"; + std::string langLoadedVar = + cmStrCat("CMAKE_", lang, "_INFORMATION_LOADED"); if (!mf->GetDefinition(langLoadedVar)) { - fpath = "CMake"; - fpath += lang; - fpath += "Information.cmake"; + fpath = cmStrCat("CMake", lang, "Information.cmake"); std::string informationFile = mf->GetModulesFile(fpath); if (informationFile.empty()) { cmSystemTools::Error("Could not find cmake module file: " + fpath); @@ -847,33 +814,27 @@ void cmGlobalGenerator::EnableLanguage( // If the language is untested then test it now with a try compile. if (needTestLanguage[lang]) { if (!this->CMakeInstance->GetIsInTryCompile()) { - std::string testLang = "CMakeTest"; - testLang += lang; - testLang += "Compiler.cmake"; + std::string testLang = cmStrCat("CMakeTest", lang, "Compiler.cmake"); std::string ifpath = mf->GetModulesFile(testLang); if (!mf->ReadListFile(ifpath)) { cmSystemTools::Error("Could not find cmake module file: " + testLang); } - std::string compilerWorks = "CMAKE_"; - compilerWorks += lang; - compilerWorks += "_COMPILER_WORKS"; + std::string compilerWorks = + cmStrCat("CMAKE_", lang, "_COMPILER_WORKS"); // if the compiler did not work, then remove the // CMake(LANG)Compiler.cmake file so that it will get tested the // next time cmake is run if (!mf->IsOn(compilerWorks)) { - std::string compilerLangFile = rootBin; - compilerLangFile += "/CMake"; - compilerLangFile += lang; - compilerLangFile += "Compiler.cmake"; + std::string compilerLangFile = + cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake"); cmSystemTools::RemoveFile(compilerLangFile); } } // end if in try compile } // end need test language // Store the shared library flags so that we can satisfy CMP0018 - std::string sharedLibFlagsVar = "CMAKE_SHARED_LIBRARY_"; - sharedLibFlagsVar += lang; - sharedLibFlagsVar += "_FLAGS"; + std::string sharedLibFlagsVar = + cmStrCat("CMAKE_SHARED_LIBRARY_", lang, "_FLAGS"); this->LanguageToOriginalSharedLibFlags[lang] = mf->GetSafeDefinition(sharedLibFlagsVar); @@ -884,10 +845,9 @@ void cmGlobalGenerator::EnableLanguage( // Now load files that can override any settings on the platform or for // the project First load the project compatibility file if it is in // cmake - std::string projectCompatibility = cmSystemTools::GetCMakeRoot(); - projectCompatibility += "/Modules/"; - projectCompatibility += mf->GetSafeDefinition("PROJECT_NAME"); - projectCompatibility += "Compatibility.cmake"; + std::string projectCompatibility = + cmStrCat(cmSystemTools::GetCMakeRoot(), "/Modules/", + mf->GetSafeDefinition("PROJECT_NAME"), "Compatibility.cmake"); if (cmSystemTools::FileExists(projectCompatibility)) { mf->ReadListFile(projectCompatibility); } @@ -1100,8 +1060,7 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l, { // use LanguageToLinkerPreference to detect whether this functions has // run before - if (this->LanguageToLinkerPreference.find(l) != - this->LanguageToLinkerPreference.end()) { + if (cmContains(this->LanguageToLinkerPreference, l)) { return; } @@ -1124,8 +1083,8 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l, } if (preference < 0) { - std::string msg = linkerPrefVar; - msg += " is negative, adjusting it to 0"; + std::string msg = + cmStrCat(linkerPrefVar, " is negative, adjusting it to 0"); cmSystemTools::Message(msg, "Warning"); preference = 0; } @@ -1151,8 +1110,7 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l, std::string ignoreExtensionsVar = std::string("CMAKE_") + std::string(l) + std::string("_IGNORE_EXTENSIONS"); std::string ignoreExts = mf->GetSafeDefinition(ignoreExtensionsVar); - std::vector<std::string> extensionList; - cmSystemTools::ExpandListArgument(ignoreExts, extensionList); + std::vector<std::string> extensionList = cmExpandedList(ignoreExts); for (std::string const& i : extensionList) { this->IgnoreExtensions[i] = true; } @@ -1164,8 +1122,7 @@ void cmGlobalGenerator::FillExtensionToLanguageMap(const std::string& l, std::string extensionsVar = std::string("CMAKE_") + std::string(l) + std::string("_SOURCE_FILE_EXTENSIONS"); const std::string& exts = mf->GetSafeDefinition(extensionsVar); - std::vector<std::string> extensionList; - cmSystemTools::ExpandListArgument(exts, extensionList); + std::vector<std::string> extensionList = cmExpandedList(exts); for (std::string const& i : extensionList) { this->ExtensionToLanguage[i] = l; } @@ -1280,10 +1237,8 @@ void cmGlobalGenerator::Configure() msg << "Configuring incomplete, errors occurred!"; const char* logs[] = { "CMakeOutput.log", "CMakeError.log", nullptr }; for (const char** log = logs; *log; ++log) { - std::string f = this->CMakeInstance->GetHomeOutputDirectory(); - f += "/CMakeFiles"; - f += "/"; - f += *log; + std::string f = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(), + "/CMakeFiles/", *log); if (cmSystemTools::FileExists(f)) { msg << "\nSee also \"" << f << "\"."; } @@ -1500,7 +1455,7 @@ void cmGlobalGenerator::Generate() this->WriteSummary(); - if (this->ExtraGenerator != nullptr) { + if (this->ExtraGenerator) { this->ExtraGenerator->Generate(); } @@ -1550,7 +1505,7 @@ bool cmGlobalGenerator::ComputeTargetDepends() bool cmGlobalGenerator::QtAutoGen() { -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP cmQtAutoGenGlobalInitializer initializer(this->LocalGenerators); return initializer.generate(); #else @@ -1609,8 +1564,8 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() mf->GetConfigurations(configs); for (std::string const& c : configs) { - std::string defPropName = "COMPILE_DEFINITIONS_"; - defPropName += cmSystemTools::UpperCase(c); + std::string defPropName = + cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(c)); t->AppendProperty(defPropName, mf->GetProperty(defPropName)); } } @@ -1624,9 +1579,8 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() "CMAKE_" + li + "_STANDARD_INCLUDE_DIRECTORIES"; std::string const& standardIncludesStr = mf->GetSafeDefinition(standardIncludesVar); - std::vector<std::string> standardIncludesVec; - cmSystemTools::ExpandListArgument(standardIncludesStr, - standardIncludesVec); + std::vector<std::string> standardIncludesVec = + cmExpandedList(standardIncludesStr); standardIncludesSet.insert(standardIncludesVec.begin(), standardIncludesVec.end()); } @@ -1713,17 +1667,15 @@ void cmGlobalGenerator::CheckTargetProperties() continue; } for (auto const& lib : target.second.GetOriginalLinkLibraries()) { - if (lib.first.size() > 9 && - cmSystemTools::IsNOTFOUND(lib.first.c_str())) { + if (lib.first.size() > 9 && cmIsNOTFOUND(lib.first)) { std::string varName = lib.first.substr(0, lib.first.size() - 9); if (state->GetCacheEntryPropertyAsBool(varName, "ADVANCED")) { varName += " (ADVANCED)"; } - std::string text = notFoundMap[varName]; - text += "\n linked by target \""; - text += target.second.GetName(); - text += "\" in directory "; - text += this->Makefiles[i]->GetCurrentSourceDirectory(); + std::string text = + cmStrCat(notFoundMap[varName], "\n linked by target \"", + target.second.GetName(), "\" in directory ", + this->Makefiles[i]->GetCurrentSourceDirectory()); notFoundMap[varName] = text; } } @@ -1737,17 +1689,18 @@ void cmGlobalGenerator::CheckTargetProperties() std::string incDirs = cmGeneratorExpression::Preprocess( incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions); - cmSystemTools::ExpandListArgument(incDirs, incs); + cmExpandList(incDirs, incs); for (std::string const& incDir : incs) { - if (incDir.size() > 9 && cmSystemTools::IsNOTFOUND(incDir.c_str())) { + if (incDir.size() > 9 && cmIsNOTFOUND(incDir)) { std::string varName = incDir.substr(0, incDir.size() - 9); if (state->GetCacheEntryPropertyAsBool(varName, "ADVANCED")) { varName += " (ADVANCED)"; } - std::string text = notFoundMap[varName]; - text += "\n used as include directory in directory "; - text += this->Makefiles[i]->GetCurrentSourceDirectory(); + std::string text = + cmStrCat(notFoundMap[varName], + "\n used as include directory in directory ", + this->Makefiles[i]->GetCurrentSourceDirectory()); notFoundMap[varName] = text; } } @@ -1846,8 +1799,8 @@ int cmGlobalGenerator::Build( output += "\n"; if (workdir.Failed()) { cmSystemTools::SetRunCommandHideConsole(hideconsole); - std::string err = "Failed to change directory: "; - err += std::strerror(workdir.GetLastResult()); + std::string err = cmStrCat("Failed to change directory: ", + std::strerror(workdir.GetLastResult())); cmSystemTools::Error(err); output += err; output += "\n"; @@ -1952,8 +1905,8 @@ std::string cmGlobalGenerator::GenerateCMakeBuildCommand( const std::string& native, bool ignoreErrors) { std::string makeCommand = cmSystemTools::GetCMakeCommand(); - makeCommand = cmSystemTools::ConvertToOutputPath(makeCommand); - makeCommand += " --build ."; + makeCommand = + cmStrCat(cmSystemTools::ConvertToOutputPath(makeCommand), " --build ."); if (!config.empty()) { makeCommand += " --config \""; makeCommand += config; @@ -2056,8 +2009,8 @@ void cmGlobalGenerator::SetConfiguredFilesPath(cmGlobalGenerator* gen) if (!gen->ConfiguredFilesPath.empty()) { this->ConfiguredFilesPath = gen->ConfiguredFilesPath; } else { - this->ConfiguredFilesPath = gen->CMakeInstance->GetHomeOutputDirectory(); - this->ConfiguredFilesPath += "/CMakeFiles"; + this->ConfiguredFilesPath = + cmStrCat(gen->CMakeInstance->GetHomeOutputDirectory(), "/CMakeFiles"); } } @@ -2157,7 +2110,7 @@ void cmGlobalGenerator::AddAlias(const std::string& name, bool cmGlobalGenerator::IsAlias(const std::string& name) const { - return this->AliasTargets.find(name) != this->AliasTargets.end(); + return cmContains(this->AliasTargets, name); } void cmGlobalGenerator::IndexTarget(cmTarget* t) @@ -2273,14 +2226,6 @@ bool cmGlobalGenerator::NameResolvesToFramework( return false; } -inline std::string removeQuotes(const std::string& s) -{ - if (s.front() == '\"' && s.back() == '\"') { - return s.substr(1, s.size() - 2); - } - return s; -} - bool cmGlobalGenerator::CheckCMP0037(std::string const& targetName, std::string const& reason) const { @@ -2335,8 +2280,8 @@ void cmGlobalGenerator::AddGlobalTarget_Package( std::vector<GlobalTargetInfo>& targets) { cmMakefile* mf = this->Makefiles[0]; - std::string configFile = mf->GetCurrentBinaryDirectory(); - configFile += "/CPackConfig.cmake"; + std::string configFile = + cmStrCat(mf->GetCurrentBinaryDirectory(), "/CPackConfig.cmake"); if (!cmSystemTools::FileExists(configFile)) { return; } @@ -2368,7 +2313,7 @@ void cmGlobalGenerator::AddGlobalTarget_Package( } else { const char* noPackageAll = mf->GetDefinition("CMAKE_SKIP_PACKAGE_ALL_DEPENDENCY"); - if (!noPackageAll || cmSystemTools::IsOff(noPackageAll)) { + if (!noPackageAll || cmIsOff(noPackageAll)) { gti.Depends.emplace_back(this->GetAllTargetName()); } } @@ -2384,8 +2329,8 @@ void cmGlobalGenerator::AddGlobalTarget_PackageSource( } cmMakefile* mf = this->Makefiles[0]; - std::string configFile = mf->GetCurrentBinaryDirectory(); - configFile += "/CPackSourceConfig.cmake"; + std::string configFile = + cmStrCat(mf->GetCurrentBinaryDirectory(), "/CPackSourceConfig.cmake"); if (!cmSystemTools::FileExists(configFile)) { return; } @@ -2537,7 +2482,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install( } else { const char* noall = mf->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY"); - if (!noall || cmSystemTools::IsOff(noall)) { + if (!noall || cmIsOff(noall)) { gti.Depends.emplace_back(this->GetAllTargetName()); } } @@ -2620,7 +2565,7 @@ bool cmGlobalGenerator::UseFolderProperty() const // If this property is defined, let the setter turn this on or off... // if (prop) { - return cmSystemTools::IsOn(prop); + return cmIsOn(prop); } // By default, this feature is OFF, since it is not supported in the @@ -2664,8 +2609,7 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti, std::string cmGlobalGenerator::GenerateRuleFile( std::string const& output) const { - std::string ruleFile = output; - ruleFile += ".rule"; + std::string ruleFile = cmStrCat(output, ".rule"); const char* dir = this->GetCMakeCFGIntDir(); if (dir && dir[0] == '$') { cmSystemTools::ReplaceString(ruleFile, dir, "/CMakeFiles"); @@ -2715,15 +2659,14 @@ bool cmGlobalGenerator::IsReservedTarget(std::string const& name) "clean", "edit_cache", "rebuild_cache", "ZERO_CHECK" }; - return std::find(cm::cbegin(reservedTargets), cm::cend(reservedTargets), - name) != cm::cend(reservedTargets); + return cmContains(reservedTargets, name); } void cmGlobalGenerator::SetExternalMakefileProjectGenerator( cmExternalMakefileProjectGenerator* extraGenerator) { - this->ExtraGenerator = extraGenerator; - if (this->ExtraGenerator != nullptr) { + this->ExtraGenerator.reset(extraGenerator); + if (this->ExtraGenerator) { this->ExtraGenerator->SetGlobalGenerator(this); } } @@ -2832,7 +2775,7 @@ std::set<std::string> const& cmGlobalGenerator::GetDirectoryContent( void cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs, std::string const& content) { -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) // Ignore if there are no outputs. if (outputs.empty()) { return; @@ -2862,11 +2805,9 @@ void cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs, void cmGlobalGenerator::CheckRuleHashes() { -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) std::string home = this->GetCMakeInstance()->GetHomeOutputDirectory(); - std::string pfile = home; - pfile += "/CMakeFiles"; - pfile += "/CMakeRuleHashes.txt"; + std::string pfile = cmStrCat(home, "/CMakeFiles/CMakeRuleHashes.txt"); this->CheckRuleHashes(pfile, home); this->WriteRuleHashes(pfile); #endif @@ -2942,9 +2883,8 @@ void cmGlobalGenerator::WriteRuleHashes(std::string const& pfile) void cmGlobalGenerator::WriteSummary() { // Record all target directories in a central location. - std::string fname = this->CMakeInstance->GetHomeOutputDirectory(); - fname += "/CMakeFiles"; - fname += "/TargetDirectories.txt"; + std::string fname = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(), + "/CMakeFiles/TargetDirectories.txt"); cmGeneratedFileStream fout(fname); for (cmLocalGenerator* lg : this->LocalGenerators) { @@ -2962,11 +2902,10 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target) { // Place the labels file in a per-target support directory. std::string dir = target->GetSupportDirectory(); - std::string file = dir; - file += "/Labels.txt"; + std::string file = cmStrCat(dir, "/Labels.txt"); std::string json_file = dir + "/Labels.json"; -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP // Check whether labels are enabled for this target. const char* targetLabels = target->GetProperty("LABELS"); const char* directoryLabels = @@ -2988,7 +2927,7 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target) // List the target-wide labels. All sources in the target get // these labels. if (targetLabels) { - cmSystemTools::ExpandListArgument(targetLabels, labels); + cmExpandList(targetLabels, labels); if (!labels.empty()) { fout << "# Target labels\n"; for (std::string const& l : labels) { @@ -3003,12 +2942,11 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target) std::vector<std::string> cmakeDirectoryLabelsList; if (directoryLabels) { - cmSystemTools::ExpandListArgument(directoryLabels, directoryLabelsList); + cmExpandList(directoryLabels, directoryLabelsList); } if (cmakeDirectoryLabels) { - cmSystemTools::ExpandListArgument(cmakeDirectoryLabels, - cmakeDirectoryLabelsList); + cmExpandList(cmakeDirectoryLabels, cmakeDirectoryLabelsList); } if (!directoryLabelsList.empty() || !cmakeDirectoryLabelsList.empty()) { @@ -3045,7 +2983,7 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target) if (const char* svalue = sf->GetProperty("LABELS")) { labels.clear(); Json::Value& lj_source_labels = lj_source["labels"] = Json::arrayValue; - cmSystemTools::ExpandListArgument(svalue, labels); + cmExpandList(svalue, labels); for (std::string const& label : labels) { fout << " " << label << "\n"; lj_source_labels.append(label); @@ -3132,8 +3070,8 @@ bool cmGlobalGenerator::GenerateCPackPropertiesFile() std::vector<std::string> configs; std::string config = mf->GetConfigurations(configs, false); - std::string path = this->CMakeInstance->GetHomeOutputDirectory(); - path += "/CPackProperties.cmake"; + std::string path = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(), + "/CPackProperties.cmake"); if (!cmSystemTools::FileExists(path) && installedFiles.empty()) { return true; diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index db96489..830974d 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -7,6 +7,7 @@ #include <iosfwd> #include <map> +#include <memory> #include <set> #include <string> #include <unordered_map> @@ -18,12 +19,13 @@ #include "cmDuration.h" #include "cmExportSetMap.h" #include "cmStateSnapshot.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetDepend.h" #include "cm_codecvt.hxx" -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) # include "cmFileLockPool.h" # include "cm_jsoncpp_value.h" #endif @@ -107,7 +109,7 @@ public: return codecvt::None; } -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) /** Get a JSON object describing the generator. */ virtual Json::Value GetJson() const; #endif @@ -460,7 +462,7 @@ public: const std::set<const cmGeneratorTarget*>& GetFilenameTargetDepends( cmSourceFile* sf) const; -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) cmFileLockPool& GetFileLockPool() { return FileLockPool; } #endif @@ -618,7 +620,7 @@ private: void ComputeBuildFileGenerators(); - cmExternalMakefileProjectGenerator* ExtraGenerator; + std::unique_ptr<cmExternalMakefileProjectGenerator> ExtraGenerator; // track files replaced during a Generate std::vector<std::string> FilesReplacedDuringGenerate; @@ -663,7 +665,7 @@ private: mutable std::map<cmSourceFile*, std::set<cmGeneratorTarget const*>> FilenameTargetDepends; -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) // Pool of file locks cmFileLockPool FileLockPool; #endif diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index b69dea0..0b45f4b 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalGhsMultiGenerator.h" +#include "cmAlgorithms.h" #include "cmDocumentationEntry.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" @@ -11,6 +12,7 @@ #include "cmMakefile.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVersion.h" #include "cmake.h" @@ -55,11 +57,9 @@ void cmGlobalGhsMultiGenerator::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { // Compute full path to object file directory for this target. - std::string dir; - dir += gt->LocalGenerator->GetCurrentBinaryDirectory(); - dir += "/"; - dir += gt->LocalGenerator->GetTargetDirectory(gt); - dir += "/"; + std::string dir = + cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/', + gt->LocalGenerator->GetTargetDirectory(gt), '/'); gt->ObjectDirectory = dir; } @@ -76,10 +76,9 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, } if (ts.empty()) { std::string message; - message = - "Green Hills MULTI: -T <toolset> not specified; defaulting to \""; - message += tsp; - message += "\""; + message = cmStrCat( + "Green Hills MULTI: -T <toolset> not specified; defaulting to \"", tsp, + '"'); cmSystemTools::Message(message); /* store the full toolset for later use @@ -97,12 +96,11 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, /* check if the toolset changed from last generate */ if (prevTool != nullptr && (gbuild != prevTool)) { - std::string message = "toolset build tool: "; - message += gbuild; - message += "\nDoes not match the previously used build tool: "; - message += prevTool; - message += "\nEither remove the CMakeCache.txt file and CMakeFiles " - "directory or choose a different binary directory."; + std::string message = + cmStrCat("toolset build tool: ", gbuild, + "\nDoes not match the previously used build tool: ", prevTool, + "\nEither remove the CMakeCache.txt file and CMakeFiles " + "directory or choose a different binary directory."); cmSystemTools::Error(message); return false; } @@ -111,7 +109,7 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", gbuild.c_str(), "build program to use", cmStateEnums::INTERNAL, true); - mf->AddDefinition("CMAKE_SYSTEM_VERSION", tsp.c_str()); + mf->AddDefinition("CMAKE_SYSTEM_VERSION", tsp); return true; } @@ -138,24 +136,20 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p, /* check if OS location has been updated by platform scripts */ std::string platform = mf->GetSafeDefinition("GHS_TARGET_PLATFORM"); std::string osdir = mf->GetSafeDefinition("GHS_OS_DIR"); - if (cmSystemTools::IsOff(osdir.c_str()) && - platform.find("integrity") != std::string::npos) { + if (cmIsOff(osdir) && platform.find("integrity") != std::string::npos) { if (!this->CMakeInstance->GetIsInTryCompile()) { /* required OS location is not found */ - std::string m = - "Green Hills MULTI: GHS_OS_DIR not specified; No OS found in \""; - m += mf->GetSafeDefinition("GHS_OS_ROOT"); - m += "\""; + std::string m = cmStrCat( + "Green Hills MULTI: GHS_OS_DIR not specified; No OS found in \"", + mf->GetSafeDefinition("GHS_OS_ROOT"), '"'); cmSystemTools::Message(m); } osdir = "GHS_OS_DIR-NOT-SPECIFIED"; } else if (!this->CMakeInstance->GetIsInTryCompile() && - cmSystemTools::IsOff(this->OsDir) && - !cmSystemTools::IsOff(osdir)) { + cmIsOff(this->OsDir) && !cmIsOff(osdir)) { /* OS location was updated by auto-selection */ - std::string m = "Green Hills MULTI: GHS_OS_DIR not specified; found \""; - m += osdir; - m += "\""; + std::string m = cmStrCat( + "Green Hills MULTI: GHS_OS_DIR not specified; found \"", osdir, '"'); cmSystemTools::Message(m); } this->OsDir = osdir; @@ -163,17 +157,15 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p, // Determine GHS_BSP_NAME std::string bspName = mf->GetSafeDefinition("GHS_BSP_NAME"); - if (cmSystemTools::IsOff(bspName.c_str()) && - platform.find("integrity") != std::string::npos) { + if (cmIsOff(bspName) && platform.find("integrity") != std::string::npos) { bspName = "sim" + arch; /* write back the calculate name for next time */ mf->AddCacheDefinition("GHS_BSP_NAME", bspName.c_str(), "Name of GHS target platform.", cmStateEnums::STRING, true); - std::string m = - "Green Hills MULTI: GHS_BSP_NAME not specified; defaulting to \""; - m += bspName; - m += "\""; + std::string m = cmStrCat( + "Green Hills MULTI: GHS_BSP_NAME not specified; defaulting to \"", + bspName, '"'); cmSystemTools::Message(m); } @@ -334,18 +326,18 @@ void cmGlobalGhsMultiGenerator::WriteTopLevelProject(std::ostream& fout, // Specify BSP option if supplied by user const char* bspName = this->GetCMakeInstance()->GetCacheDefinition("GHS_BSP_NAME"); - if (!cmSystemTools::IsOff(bspName)) { + if (!cmIsOff(bspName)) { fout << " -bsp " << bspName << std::endl; } // Specify OS DIR if supplied by user // -- not all platforms require this entry in the project file - if (!cmSystemTools::IsOff(this->OsDir.c_str())) { + if (!cmIsOff(this->OsDir)) { const char* osDirOption = this->GetCMakeInstance()->GetCacheDefinition("GHS_OS_DIR_OPTION"); std::replace(this->OsDir.begin(), this->OsDir.end(), '\\', '/'); fout << " "; - if (cmSystemTools::IsOff(osDirOption)) { + if (cmIsOff(osDirOption)) { fout << ""; } else { fout << osDirOption; @@ -404,8 +396,8 @@ void cmGlobalGhsMultiGenerator::WriteProjectLine( void cmGlobalGhsMultiGenerator::WriteTargets(cmLocalGenerator* root) { - std::string rootBinaryDir = root->GetCurrentBinaryDirectory(); - rootBinaryDir += "/CMakeFiles"; + std::string rootBinaryDir = + cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeFiles"); // All known targets for (cmGeneratorTarget const* target : this->ProjectTargets) { @@ -418,17 +410,17 @@ void cmGlobalGhsMultiGenerator::WriteTargets(cmLocalGenerator* root) } // create target build file - std::string name = target->GetName() + ".tgt" + FILE_EXTENSION; - std::string fname = rootBinaryDir + "/" + name; + std::string name = cmStrCat(target->GetName(), ".tgt", FILE_EXTENSION); + std::string fname = cmStrCat(rootBinaryDir, "/", name); cmGeneratedFileStream fbld(fname); fbld.SetCopyIfDifferent(true); this->WriteFileHeader(fbld); GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fbld); std::vector<cmGeneratorTarget const*> build; if (ComputeTargetBuildOrder(target, build)) { - std::string message = "The inter-target dependency graph for target [" + - target->GetName() + "] had a cycle.\n"; - cmSystemTools::Error(message); + cmSystemTools::Error( + cmStrCat("The inter-target dependency graph for target [", + target->GetName(), "] had a cycle.\n")); } else { for (auto& tgt : build) { WriteProjectLine(fbld, tgt, root, rootBinaryDir); @@ -469,7 +461,7 @@ void cmGlobalGhsMultiGenerator::WriteAllTarget( if (t->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } - if (!cmSystemTools::IsOn(t->GetProperty("EXCLUDE_FROM_ALL"))) { + if (!cmIsOn(t->GetProperty("EXCLUDE_FROM_ALL"))) { defaultTargets.push_back(t); } } @@ -480,8 +472,8 @@ void cmGlobalGhsMultiGenerator::WriteAllTarget( cmSystemTools::Error(message); } else { // determine the targets for ALL target - std::string rootBinaryDir = root->GetCurrentBinaryDirectory(); - rootBinaryDir += "/CMakeFiles"; + std::string rootBinaryDir = + cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeFiles"); for (cmGeneratorTarget const* target : build) { if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY || target->GetType() == cmStateEnums::MODULE_LIBRARY || @@ -539,11 +531,8 @@ void cmGlobalGhsMultiGenerator::OutputTopLevelProject( * with target projects. This avoid the issue where the project has * the same name as the executable target. */ - fname = root->GetCurrentBinaryDirectory(); - fname += "/"; - fname += root->GetProjectName(); - fname += ".top"; - fname += FILE_EXTENSION; + fname = cmStrCat(root->GetCurrentBinaryDirectory(), '/', + root->GetProjectName(), ".top", FILE_EXTENSION); cmGeneratedFileStream top(fname); top.SetCopyIfDifferent(true); @@ -588,16 +577,14 @@ cmGlobalGhsMultiGenerator::GenerateBuildCommand( /* if multiple top-projects are found in build directory * then prefer projectName top-project. */ - auto p = std::find(files.begin(), files.end(), proj); - if (p == files.end()) { + if (!cmContains(files, proj)) { proj = files.at(0); } } makeCommand.Add("-top", proj); if (!targetNames.empty()) { - if (std::find(targetNames.begin(), targetNames.end(), "clean") != - targetNames.end()) { + if (cmContains(targetNames, "clean")) { makeCommand.Add("-clean"); } else { for (const auto& tname : targetNames) { @@ -623,8 +610,8 @@ void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout, char const* ghsGpjMacros = this->GetCMakeInstance()->GetCacheDefinition("GHS_GPJ_MACROS"); if (nullptr != ghsGpjMacros) { - std::vector<std::string> expandedList; - cmSystemTools::ExpandListArgument(std::string(ghsGpjMacros), expandedList); + std::vector<std::string> expandedList = + cmExpandedList(std::string(ghsGpjMacros)); for (std::string const& arg : expandedList) { fout << "macro " << arg << std::endl; } @@ -646,10 +633,7 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives( this->GetCMakeInstance()->GetCacheDefinition("CMAKE_GENERATOR_PLATFORM"); const char* p = this->GetCMakeInstance()->GetCacheDefinition("GHS_TARGET_PLATFORM"); - tgt = (a ? a : ""); - tgt += "_"; - tgt += (p ? p : ""); - tgt += ".tgt"; + tgt = cmStrCat((a ? a : ""), '_', (p ? p : ""), ".tgt"); } fout << "primaryTarget=" << tgt << std::endl; diff --git a/Source/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx index 7b58389..ae9d5a7 100644 --- a/Source/cmGlobalMSYSMakefileGenerator.cxx +++ b/Source/cmGlobalMSYSMakefileGenerator.cxx @@ -24,8 +24,7 @@ cmGlobalMSYSMakefileGenerator::cmGlobalMSYSMakefileGenerator(cmake* cm) std::string cmGlobalMSYSMakefileGenerator::FindMinGW( std::string const& makeloc) { - std::string fstab = makeloc; - fstab += "/../etc/fstab"; + std::string fstab = cmStrCat(makeloc, "/../etc/fstab"); cmsys::ifstream fin(fstab.c_str()); std::string path; std::string mount; @@ -34,8 +33,7 @@ std::string cmGlobalMSYSMakefileGenerator::FindMinGW( fin >> path; fin >> mount; if (mount == "/mingw") { - mingwBin = path; - mingwBin += "/bin"; + mingwBin = cmStrCat(path, "/bin"); } } return mingwBin; @@ -69,9 +67,9 @@ void cmGlobalMSYSMakefileGenerator::EnableLanguage( rc = trc; } mf->AddDefinition("MSYS", "1"); - mf->AddDefinition("CMAKE_GENERATOR_CC", gcc.c_str()); - mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx.c_str()); - mf->AddDefinition("CMAKE_GENERATOR_RC", rc.c_str()); + mf->AddDefinition("CMAKE_GENERATOR_CC", gcc); + mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx); + mf->AddDefinition("CMAKE_GENERATOR_RC", rc); this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional); if (!mf->IsSet("CMAKE_AR") && !this->CMakeInstance->GetIsInTryCompile() && diff --git a/Source/cmGlobalMinGWMakefileGenerator.cxx b/Source/cmGlobalMinGWMakefileGenerator.cxx index e218b4b..d9fc505 100644 --- a/Source/cmGlobalMinGWMakefileGenerator.cxx +++ b/Source/cmGlobalMinGWMakefileGenerator.cxx @@ -44,9 +44,9 @@ void cmGlobalMinGWMakefileGenerator::EnableLanguage( if (!trc.empty()) { rc = trc; } - mf->AddDefinition("CMAKE_GENERATOR_CC", gcc.c_str()); - mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx.c_str()); - mf->AddDefinition("CMAKE_GENERATOR_RC", rc.c_str()); + mf->AddDefinition("CMAKE_GENERATOR_CC", gcc); + mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx); + mf->AddDefinition("CMAKE_GENERATOR_RC", rc); this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional); } diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 2d52356..062eccb 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -9,10 +9,11 @@ #include <algorithm> #include <ctype.h> #include <iterator> -#include <memory> // IWYU pragma: keep #include <sstream> #include <stdio.h> +#include "cm_memory.hxx" + #include "cmAlgorithms.h" #include "cmDocumentationEntry.h" #include "cmFortranParser.h" @@ -31,6 +32,7 @@ #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetDepend.h" @@ -381,7 +383,7 @@ void cmGlobalNinjaGenerator::WriteVariable(std::ostream& os, } // Do not add a variable if the value is empty. - std::string val = cmSystemTools::TrimWhitespace(value); + std::string val = cmTrimWhitespace(value); if (val.empty()) { return; } @@ -413,14 +415,6 @@ void cmGlobalNinjaGenerator::WriteDefault(std::ostream& os, cmGlobalNinjaGenerator::cmGlobalNinjaGenerator(cmake* cm) : cmGlobalCommonGenerator(cm) - , UsingGCCOnWindows(false) - , ComputingUnknownDependencies(false) - , PolicyCMP0058(cmPolicies::WARN) - , NinjaSupportsConsolePool(false) - , NinjaSupportsImplicitOuts(false) - , NinjaSupportsManifestRestat(false) - , NinjaSupportsMultilineDepfile(false) - , NinjaSupportsDyndeps(0) { #ifdef _WIN32 cm->GetState()->SetWindowsShell(true); @@ -534,7 +528,7 @@ bool cmGlobalNinjaGenerator::FindMakeProgram(cmMakefile* mf) cmSystemTools::SetFatalErrorOccured(); return false; } - this->NinjaVersion = cmSystemTools::TrimWhitespace(version); + this->NinjaVersion = cmTrimWhitespace(version); this->CheckNinjaFeatures(); } return true; @@ -554,14 +548,22 @@ void cmGlobalNinjaGenerator::CheckNinjaFeatures() this->NinjaSupportsMultilineDepfile = !cmSystemTools::VersionCompare( cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), RequiredNinjaVersionForMultilineDepfile().c_str()); - { + this->NinjaSupportsDyndeps = !cmSystemTools::VersionCompare( + cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), + RequiredNinjaVersionForDyndeps().c_str()); + if (!this->NinjaSupportsDyndeps) { + // The ninja version number is not new enough to have upstream support. // Our ninja branch adds ".dyndep-#" to its version number, // where '#' is a feature-specific version number. Extract it. static std::string const k_DYNDEP_ = ".dyndep-"; std::string::size_type pos = this->NinjaVersion.find(k_DYNDEP_); if (pos != std::string::npos) { const char* fv = &this->NinjaVersion[pos + k_DYNDEP_.size()]; - cmSystemTools::StringToULong(fv, &this->NinjaSupportsDyndeps); + unsigned long dyndep = 0; + cmStrToULong(fv, &dyndep); + if (dyndep == 1) { + this->NinjaSupportsDyndeps = true; + } } } } @@ -569,8 +571,7 @@ void cmGlobalNinjaGenerator::CheckNinjaFeatures() bool cmGlobalNinjaGenerator::CheckLanguages( std::vector<std::string> const& languages, cmMakefile* mf) const { - if (std::find(languages.begin(), languages.end(), "Fortran") != - languages.end()) { + if (cmContains(languages, "Fortran")) { return this->CheckFortran(mf); } return true; @@ -578,37 +579,25 @@ bool cmGlobalNinjaGenerator::CheckLanguages( bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const { - if (this->NinjaSupportsDyndeps == 1) { + if (this->NinjaSupportsDyndeps) { return true; } std::ostringstream e; - if (this->NinjaSupportsDyndeps == 0) { - /* clang-format off */ - e << - "The Ninja generator does not support Fortran using Ninja version\n" - " " + this->NinjaVersion + "\n" - "due to lack of required features. " - "Kitware has implemented the required features but as of this version " - "of CMake they have not been integrated to upstream ninja. " - "Pending integration, Kitware maintains a branch at:\n" - " https://github.com/Kitware/ninja/tree/features-for-fortran#readme\n" - "with the required features. " - "One may build ninja from that branch to get support for Fortran." - ; - /* clang-format on */ - } else { - /* clang-format off */ - e << - "The Ninja generator in this version of CMake does not support Fortran " - "using Ninja version\n" - " " + this->NinjaVersion + "\n" - "because its 'dyndep' feature version is " << - this->NinjaSupportsDyndeps << ". " - "This version of CMake is aware only of 'dyndep' feature version 1." - ; - /* clang-format on */ - } + /* clang-format off */ + e << + "The Ninja generator does not support Fortran using Ninja version\n" + " " + this->NinjaVersion + "\n" + "due to lack of required features. " + "Kitware has implemented the required features and they have been " + "merged to upstream ninja for inclusion in Ninja 1.10 and higher. " + "As of this version of CMake, Ninja 1.10 has not been released. " + "Meanwhile, Kitware maintains a branch of Ninja at:\n" + " https://github.com/Kitware/ninja/tree/features-for-fortran#readme\n" + "with the required features. " + "One may build ninja from that branch to get support for Fortran." + ; + /* clang-format on */ mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return false; @@ -638,7 +627,9 @@ void cmGlobalNinjaGenerator::EnableLanguage( (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "GNU") || (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "GNU") || (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "Clang") || - (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "Clang")))) { + (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "Clang") || + (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "QCC") || + (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "QCC")))) { this->UsingGCCOnWindows = true; } #endif @@ -713,11 +704,9 @@ void cmGlobalNinjaGenerator::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { // Compute full path to object file directory for this target. - std::string dir; - dir += gt->LocalGenerator->GetCurrentBinaryDirectory(); - dir += "/"; - dir += gt->LocalGenerator->GetTargetDirectory(gt); - dir += "/"; + std::string dir = + cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/', + gt->LocalGenerator->GetTargetDirectory(gt), '/'); gt->ObjectDirectory = dir; } @@ -727,9 +716,8 @@ bool cmGlobalNinjaGenerator::OpenBuildFileStream() { // Compute Ninja's build file path. std::string buildFilePath = - this->GetCMakeInstance()->GetHomeOutputDirectory(); - buildFilePath += "/"; - buildFilePath += cmGlobalNinjaGenerator::NINJA_BUILD_FILE; + cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/', + cmGlobalNinjaGenerator::NINJA_BUILD_FILE); // Get a stream where to generate things. if (!this->BuildFileStream) { @@ -766,9 +754,8 @@ bool cmGlobalNinjaGenerator::OpenRulesFileStream() { // Compute Ninja's build file path. std::string rulesFilePath = - this->GetCMakeInstance()->GetHomeOutputDirectory(); - rulesFilePath += "/"; - rulesFilePath += cmGlobalNinjaGenerator::NINJA_RULES_FILE; + cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/', + cmGlobalNinjaGenerator::NINJA_RULES_FILE); // Get a stream where to generate things. if (!this->RulesFileStream) { @@ -1323,13 +1310,13 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) { cmNinjaRule rule("RERUN_CMAKE"); - rule.Command = CMakeCmd(); - rule.Command += " -S"; - rule.Command += lg->ConvertToOutputFormat(lg->GetSourceDirectory(), - cmOutputConverter::SHELL); - rule.Command += " -B"; - rule.Command += lg->ConvertToOutputFormat(lg->GetBinaryDirectory(), - cmOutputConverter::SHELL); + rule.Command = + cmStrCat(CMakeCmd(), " -S", + lg->ConvertToOutputFormat(lg->GetSourceDirectory(), + cmOutputConverter::SHELL), + " -B", + lg->ConvertToOutputFormat(lg->GetBinaryDirectory(), + cmOutputConverter::SHELL)); rule.Description = "Re-running CMake..."; rule.Comment = "Rule for re-running cmake."; rule.Generator = true; @@ -1357,10 +1344,10 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) if (this->SupportsManifestRestat() && cm->DoWriteGlobVerifyTarget()) { { cmNinjaRule rule("VERIFY_GLOBS"); - rule.Command = CMakeCmd(); - rule.Command += " -P "; - rule.Command += lg->ConvertToOutputFormat(cm->GetGlobVerifyScript(), - cmOutputConverter::SHELL); + rule.Command = + cmStrCat(CMakeCmd(), " -P ", + lg->ConvertToOutputFormat(cm->GetGlobVerifyScript(), + cmOutputConverter::SHELL)); rule.Description = "Re-checking globbed directories..."; rule.Comment = "Rule for re-checking globbed directories."; rule.Generator = true; @@ -1466,9 +1453,8 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os) { cmLocalGenerator* lgr = this->LocalGenerators.at(0); std::string cleanScriptRel = "CMakeFiles/clean_additional.cmake"; - std::string cleanScriptAbs = lgr->GetBinaryDirectory(); - cleanScriptAbs += '/'; - cleanScriptAbs += cleanScriptRel; + std::string cleanScriptAbs = + cmStrCat(lgr->GetBinaryDirectory(), '/', cleanScriptRel); // Check if there are additional files to clean if (this->AdditionalCleanFiles.empty()) { @@ -1498,10 +1484,10 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os) // Write rule { cmNinjaRule rule("CLEAN_ADDITIONAL"); - rule.Command = CMakeCmd(); - rule.Command += " -P "; - rule.Command += lgr->ConvertToOutputFormat( - this->NinjaOutputPath(cleanScriptRel), cmOutputConverter::SHELL); + rule.Command = cmStrCat( + CMakeCmd(), " -P ", + lgr->ConvertToOutputFormat(this->NinjaOutputPath(cleanScriptRel), + cmOutputConverter::SHELL)); rule.Description = "Cleaning additional files..."; rule.Comment = "Rule for cleaning additional files."; WriteRule(*this->RulesFileStream, rule); @@ -1739,8 +1725,9 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg, if (arg_lang == "Fortran") { info = cmcmd_cmake_ninja_depends_fortran(arg_tdi, arg_pp); } else { - cmSystemTools::Error("-E cmake_ninja_depends does not understand the " + - arg_lang + " language"); + cmSystemTools::Error( + cmStrCat("-E cmake_ninja_depends does not understand the ", arg_lang, + " language")); return 1; } @@ -1794,8 +1781,9 @@ std::unique_ptr<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran( cmsys::ifstream tdif(arg_tdi.c_str(), std::ios::in | std::ios::binary); Json::Reader reader; if (!reader.parse(tdif, tdio, false)) { - cmSystemTools::Error("-E cmake_ninja_depends failed to parse " + - arg_tdi + reader.getFormattedErrorMessages()); + cmSystemTools::Error( + cmStrCat("-E cmake_ninja_depends failed to parse ", arg_tdi, + reader.getFormattedErrorMessages())); return nullptr; } } @@ -1874,8 +1862,9 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( cmsys::ifstream ddif(arg_ddi.c_str(), std::ios::in | std::ios::binary); Json::Reader reader; if (!reader.parse(ddif, ddio, false)) { - cmSystemTools::Error("-E cmake_ninja_dyndep failed to parse " + arg_ddi + - reader.getFormattedErrorMessages()); + cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ", + arg_ddi, + reader.getFormattedErrorMessages())); return false; } @@ -1902,14 +1891,14 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( // Populate the module map with those provided by linked targets first. for (std::string const& linked_target_dir : linked_target_dirs) { std::string const ltmn = - linked_target_dir + "/" + arg_lang + "Modules.json"; + cmStrCat(linked_target_dir, "/", arg_lang, "Modules.json"); Json::Value ltm; cmsys::ifstream ltmf(ltmn.c_str(), std::ios::in | std::ios::binary); Json::Reader reader; if (ltmf && !reader.parse(ltmf, ltm, false)) { - cmSystemTools::Error("-E cmake_ninja_dyndep failed to parse " + - linked_target_dir + - reader.getFormattedErrorMessages()); + cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ", + linked_target_dir, + reader.getFormattedErrorMessages())); return false; } if (ltm.isObject()) { @@ -2013,8 +2002,9 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, cmsys::ifstream tdif(arg_tdi.c_str(), std::ios::in | std::ios::binary); Json::Reader reader; if (!reader.parse(tdif, tdio, false)) { - cmSystemTools::Error("-E cmake_ninja_dyndep failed to parse " + arg_tdi + - reader.getFormattedErrorMessages()); + cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ", + arg_tdi, + reader.getFormattedErrorMessages())); return 1; } } diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 15dd404..db64031 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -7,7 +7,7 @@ #include <iosfwd> #include <map> -#include <memory> // IWYU pragma: keep +#include <memory> #include <set> #include <string> #include <unordered_map> @@ -322,6 +322,7 @@ public: { return "1.9"; } + static std::string RequiredNinjaVersionForDyndeps() { return "1.10"; } bool SupportsConsolePool() const; bool SupportsImplicitOuts() const; bool SupportsManifestRestat() const; @@ -402,7 +403,7 @@ private: /// The set of dependencies to add to the "all" target. cmNinjaDeps AllDependencies; - bool UsingGCCOnWindows; + bool UsingGCCOnWindows = false; /// The set of custom commands we have seen. std::set<cmCustomCommand const*> CustomCommands; @@ -412,8 +413,8 @@ private: /// Whether we are collecting known build outputs and needed /// dependencies to determine unknown dependencies. - bool ComputingUnknownDependencies; - cmPolicies::PolicyStatus PolicyCMP0058; + bool ComputingUnknownDependencies = false; + cmPolicies::PolicyStatus PolicyCMP0058 = cmPolicies::WARN; /// The combined explicit dependencies of custom build commands std::set<std::string> CombinedCustomCommandExplicitDependencies; @@ -435,11 +436,11 @@ private: std::string NinjaCommand; std::string NinjaVersion; - bool NinjaSupportsConsolePool; - bool NinjaSupportsImplicitOuts; - bool NinjaSupportsManifestRestat; - bool NinjaSupportsMultilineDepfile; - unsigned long NinjaSupportsDyndeps; + bool NinjaSupportsConsolePool = false; + bool NinjaSupportsImplicitOuts = false; + bool NinjaSupportsManifestRestat = false; + bool NinjaSupportsMultilineDepfile = false; + bool NinjaSupportsDyndeps = false; private: void InitOutputPathPrefix(); diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index aa584ad..22c304e 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -7,6 +7,8 @@ #include <sstream> #include <utility> +#include "cm_memory.hxx" + #include "cmAlgorithms.h" #include "cmDocumentationEntry.h" #include "cmGeneratedFileStream.h" @@ -20,6 +22,7 @@ #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTargetDepend.h" #include "cmake.h" @@ -105,11 +108,9 @@ void cmGlobalUnixMakefileGenerator3::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { // Compute full path to object file directory for this target. - std::string dir; - dir += gt->LocalGenerator->GetCurrentBinaryDirectory(); - dir += "/"; - dir += gt->LocalGenerator->GetTargetDirectory(gt); - dir += "/"; + std::string dir = + cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/', + gt->LocalGenerator->GetTargetDirectory(gt), '/'); gt->ObjectDirectory = dir; } @@ -144,10 +145,8 @@ void cmGlobalUnixMakefileGenerator3::Generate() pmi.second.WriteProgressVariables(total, current); } for (cmLocalGenerator* lg : this->LocalGenerators) { - std::string markFileName = lg->GetCurrentBinaryDirectory(); - markFileName += "/"; - markFileName += "/CMakeFiles"; - markFileName += "/progress.marks"; + std::string markFileName = + cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles/progress.marks"); cmGeneratedFileStream markFile(markFileName); markFile << this->CountProgressMarksInAll(lg) << "\n"; } @@ -195,9 +194,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2() // because the check-build-system step compares the makefile time to // see if the build system must be regenerated. std::string makefileName = - this->GetCMakeInstance()->GetHomeOutputDirectory(); - makefileName += "/CMakeFiles"; - makefileName += "/Makefile2"; + cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), + "/CMakeFiles/Makefile2"); cmGeneratedFileStream makefileStream(makefileName, false, this->GetMakefileEncoding()); if (!makefileStream) { @@ -255,17 +253,15 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() // because the check-build-system step compares the makefile time to // see if the build system must be regenerated. std::string cmakefileName = - this->GetCMakeInstance()->GetHomeOutputDirectory(); - cmakefileName += "/CMakeFiles"; - cmakefileName += "/Makefile.cmake"; + cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), + "/CMakeFiles/Makefile.cmake"); cmGeneratedFileStream cmakefileStream(cmakefileName); if (!cmakefileStream) { return; } std::string makefileName = - this->GetCMakeInstance()->GetHomeOutputDirectory(); - makefileName += "/Makefile"; + cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), "/Makefile"); // get a local generator for some useful methods cmLocalUnixMakefileGenerator3* lg = @@ -317,9 +313,9 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() cmakefileStream << " )\n\n"; // Build the path to the cache check file. - std::string check = this->GetCMakeInstance()->GetHomeOutputDirectory(); - check += "/CMakeFiles"; - check += "/cmake.check_cache"; + std::string check = + cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), + "/CMakeFiles/cmake.check_cache"); // Set the corresponding makefile in the cmake file. cmakefileStream << "# The corresponding makefile is:\n" @@ -349,9 +345,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() std::string tmpStr; for (cmLocalGenerator* localGen : this->LocalGenerators) { lg = static_cast<cmLocalUnixMakefileGenerator3*>(localGen); - tmpStr = lg->GetCurrentBinaryDirectory(); - tmpStr += "/CMakeFiles"; - tmpStr += "/CMakeDirectoryInformation.cmake"; + tmpStr = cmStrCat(lg->GetCurrentBinaryDirectory(), + "/CMakeFiles/CMakeDirectoryInformation.cmake"); cmakefileStream << " \"" << lg->MaybeConvertToRelativePath(binDir, tmpStr) << "\"\n"; @@ -383,8 +378,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefileLanguageRules( (tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) || (tgt->GetType() == cmStateEnums::UTILITY)) { cmGeneratorTarget* gt = tgt; - std::string tname = lg->GetRelativeTargetDirectory(gt); - tname += "/DependInfo.cmake"; + std::string tname = + cmStrCat(lg->GetRelativeTargetDirectory(gt), "/DependInfo.cmake"); cmSystemTools::ConvertToUnixSlashes(tname); cmakefileStream << " \"" << tname << "\"\n"; } @@ -399,9 +394,8 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2( std::vector<std::string> const& commands) { // Get the relative path to the subdirectory from the top. - std::string makeTarget = lg->GetCurrentBinaryDirectory(); - makeTarget += '/'; - makeTarget += pass; + std::string makeTarget = + cmStrCat(lg->GetCurrentBinaryDirectory(), '/', pass); // The directory-level rule should depend on the target-level rules // for all targets in the directory. @@ -418,9 +412,8 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2( if ((!check_all || !gtarget->GetPropertyAsBool("EXCLUDE_FROM_ALL")) && (!check_relink || gtarget->NeedRelinkBeforeInstall(lg->GetConfigName()))) { - std::string tname = lg->GetRelativeTargetDirectory(gtarget); - tname += "/"; - tname += pass; + std::string tname = + cmStrCat(lg->GetRelativeTargetDirectory(gtarget), '/', pass); depends.push_back(std::move(tname)); } } @@ -429,9 +422,8 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2( // The directory-level rule should depend on the directory-level // rules of the subdirectories. for (cmStateSnapshot const& c : lg->GetStateSnapshot().GetChildren()) { - std::string subdir = c.GetDirectory().GetCurrentBinary(); - subdir += '/'; - subdir += pass; + std::string subdir = + cmStrCat(c.GetDirectory().GetCurrentBinary(), '/', pass); depends.push_back(std::move(subdir)); } @@ -444,13 +436,9 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2( // Write the rule. std::string doc; if (lg->IsRootMakefile()) { - doc = "The main recursive \""; - doc += pass; - doc += "\" target."; + doc = cmStrCat("The main recursive \"", pass, "\" target."); } else { - doc = "Recursive \""; - doc += pass; - doc += "\" directory target."; + doc = cmStrCat("Recursive \"", pass, "\" directory target."); } lg->WriteMakeRule(ruleFileStream, doc.c_str(), makeTarget, depends, commands, true); @@ -581,8 +569,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( // Write the rule. commands.clear(); - std::string tmp = "CMakeFiles/"; - tmp += "Makefile2"; + std::string tmp = "CMakeFiles/Makefile2"; commands.push_back(lg->GetRecursiveMakeCall(tmp, name)); depends.clear(); if (regenerate) { @@ -594,14 +581,11 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( // Add a fast rule to build the target std::string localName = lg->GetRelativeTargetDirectory(gtarget); std::string makefileName; - makefileName = localName; - makefileName += "/build.make"; + makefileName = cmStrCat(localName, "/build.make"); depends.clear(); commands.clear(); - std::string makeTargetName = localName; - makeTargetName += "/build"; - localName = name; - localName += "/fast"; + std::string makeTargetName = cmStrCat(localName, "/build"); + localName = cmStrCat(name, "/fast"); commands.push_back( lg->GetRecursiveMakeCall(makefileName, makeTargetName)); lg->WriteMakeRule(ruleFileStream, "fast build rule for target.", @@ -610,10 +594,9 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( // Add a local name for the rule to relink the target before // installation. if (gtarget->NeedRelinkBeforeInstall(lg->GetConfigName())) { - makeTargetName = lg->GetRelativeTargetDirectory(gtarget); - makeTargetName += "/preinstall"; - localName = name; - localName += "/preinstall"; + makeTargetName = + cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/preinstall"); + localName = cmStrCat(name, "/preinstall"); depends.clear(); commands.clear(); commands.push_back( @@ -657,20 +640,17 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( std::string makefileName; // Add a rule to build the target by name. localName = lg->GetRelativeTargetDirectory(gtarget); - makefileName = localName; - makefileName += "/build.make"; + makefileName = cmStrCat(localName, "/build.make"); lg->WriteDivider(ruleFileStream); ruleFileStream << "# Target rules for target " << localName << "\n\n"; commands.clear(); - makeTargetName = localName; - makeTargetName += "/depend"; + makeTargetName = cmStrCat(localName, "/depend"); commands.push_back( lg->GetRecursiveMakeCall(makefileName, makeTargetName)); - makeTargetName = localName; - makeTargetName += "/build"; + makeTargetName = cmStrCat(localName, "/build"); commands.push_back( lg->GetRecursiveMakeCall(makefileName, makeTargetName)); @@ -679,8 +659,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( depends.clear(); cmLocalUnixMakefileGenerator3::EchoProgress progress; - progress.Dir = lg->GetBinaryDirectory(); - progress.Dir += "/CMakeFiles"; + progress.Dir = cmStrCat(lg->GetBinaryDirectory(), "/CMakeFiles"); { std::ostringstream progressArg; const char* sep = ""; @@ -695,7 +674,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( if (const char* tgtMsg = this->GetCMakeInstance()->GetState()->GetGlobalProperty( "TARGET_MESSAGES")) { - targetMessages = cmSystemTools::IsOn(tgtMsg); + targetMessages = cmIsOn(tgtMsg); } if (targetMessages) { @@ -723,8 +702,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( progCmd << " " << this->CountProgressMarksInTarget(gtarget, emitted); commands.push_back(progCmd.str()); } - std::string tmp = "CMakeFiles/"; - tmp += "Makefile2"; + std::string tmp = "CMakeFiles/Makefile2"; commands.push_back(lg->GetRecursiveMakeCall(tmp, localName)); { std::ostringstream progCmd; @@ -739,8 +717,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( if (regenerate) { depends.emplace_back("cmake_check_build_system"); } - localName = lg->GetRelativeTargetDirectory(gtarget); - localName += "/rule"; + localName = cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/rule"); lg->WriteMakeRule(ruleFileStream, "Build rule for subdir invocation for target.", localName, depends, commands, true); @@ -754,8 +731,8 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( // Add rules to prepare the target for installation. if (gtarget->NeedRelinkBeforeInstall(lg->GetConfigName())) { - localName = lg->GetRelativeTargetDirectory(gtarget); - localName += "/preinstall"; + localName = + cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/preinstall"); depends.clear(); commands.clear(); commands.push_back(lg->GetRecursiveMakeCall(makefileName, localName)); @@ -774,8 +751,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( // add the clean rule localName = lg->GetRelativeTargetDirectory(gtarget); - makeTargetName = localName; - makeTargetName += "/clean"; + makeTargetName = cmStrCat(localName, "/clean"); depends.clear(); commands.clear(); commands.push_back( @@ -894,9 +870,9 @@ void cmGlobalUnixMakefileGenerator3::AppendGlobalTargetDepends( } cmLocalUnixMakefileGenerator3* lg3 = static_cast<cmLocalUnixMakefileGenerator3*>(dep->GetLocalGenerator()); - std::string tgtName = - lg3->GetRelativeTargetDirectory(const_cast<cmGeneratorTarget*>(dep)); - tgtName += "/all"; + std::string tgtName = cmStrCat( + lg3->GetRelativeTargetDirectory(const_cast<cmGeneratorTarget*>(dep)), + "/all"); depends.push_back(tgtName); } } @@ -939,8 +915,7 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule( (type == cmStateEnums::UTILITY)) { std::string const& name = target->GetName(); if (emittedTargets.insert(name).second) { - path = "... "; - path += name; + path = cmStrCat("... ", name); lg->AppendEcho(commands, path); } } @@ -948,8 +923,7 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule( } } for (std::string const& o : lg->GetLocalHelp()) { - path = "... "; - path += o; + path = cmStrCat("... ", o); lg->AppendEcho(commands, path); } lg->WriteMakeRule(ruleFileStream, "Help Target", "help", no_depends, diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 55374a4..48b17c0 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -325,7 +325,7 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset( std::string const& ts, cmMakefile* mf) { - std::vector<std::string> const fields = cmSystemTools::tokenize(ts, ","); + std::vector<std::string> const fields = cmTokenize(ts, ","); std::vector<std::string>::const_iterator fi = fields.begin(); if (fi == fields.end()) { return true; @@ -445,7 +445,7 @@ bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf) this->DefaultPlatformName = "Tegra-Android"; this->DefaultPlatformToolset = "Default"; this->NsightTegraVersion = v; - mf->AddDefinition("CMAKE_VS_NsightTegra_VERSION", v.c_str()); + mf->AddDefinition("CMAKE_VS_NsightTegra_VERSION", v); } return true; @@ -659,8 +659,7 @@ bool cmGlobalVisualStudio10Generator::FindMakeProgram(cmMakefile* mf) if (!this->cmGlobalVisualStudio8Generator::FindMakeProgram(mf)) { return false; } - mf->AddDefinition("CMAKE_VS_MSBUILD_COMMAND", - this->GetMSBuildCommand().c_str()); + mf->AddDefinition("CMAKE_VS_MSBUILD_COMMAND", this->GetMSBuildCommand()); return true; } @@ -679,9 +678,9 @@ std::string cmGlobalVisualStudio10Generator::FindMSBuildCommand() std::string mskey; // Search in standard location. - mskey = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\"; - mskey += this->GetToolsVersion(); - mskey += ";MSBuildToolsPath"; + mskey = cmStrCat( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\", + this->GetToolsVersion(), ";MSBuildToolsPath"); if (cmSystemTools::ReadRegistryValue(mskey.c_str(), msbuild, cmSystemTools::KeyWOW64_32)) { cmSystemTools::ConvertToUnixSlashes(msbuild); @@ -721,8 +720,8 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) // In a try-compile we are given the outer CMakeFiles directory. wd = this->ConfiguredFilesPath; } else { - wd = this->GetCMakeInstance()->GetHomeOutputDirectory(); - wd += "/CMakeFiles"; + wd = cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), + "/CMakeFiles"); } wd += "/"; wd += cmVersion::GetCMakeVersion(); @@ -906,8 +905,7 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand( { std::string slnFile; if (!projectDir.empty()) { - slnFile = projectDir; - slnFile += "/"; + slnFile = cmStrCat(projectDir, '/'); } slnFile += projectName; slnFile += ".sln"; @@ -954,8 +952,7 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand( makeCommand.Add(std::string(projectName) + ".sln"); makeCommand.Add("/t:Clean"); } else { - std::string targetProject(tname); - targetProject += ".vcxproj"; + std::string targetProject = cmStrCat(tname, ".vcxproj"); if (targetProject.find('/') == std::string::npos) { // it might be in a subdir if (cmSlnProjectEntry const* proj = slnData.GetProjectByName(tname)) { @@ -1038,14 +1035,12 @@ std::string cmGlobalVisualStudio10Generator::GenerateRuleFile( { // The VS 10 generator needs to create the .rule files on disk. // Hide them away under the CMakeFiles directory. - std::string ruleDir = this->GetCMakeInstance()->GetHomeOutputDirectory(); - ruleDir += "/CMakeFiles"; - ruleDir += "/"; - ruleDir += cmSystemTools::ComputeStringMD5( - cmSystemTools::GetFilenamePath(output).c_str()); - std::string ruleFile = ruleDir + "/"; - ruleFile += cmSystemTools::GetFilenameName(output); - ruleFile += ".rule"; + std::string ruleDir = cmStrCat( + this->GetCMakeInstance()->GetHomeOutputDirectory(), "/CMakeFiles/", + cmSystemTools::ComputeStringMD5( + cmSystemTools::GetFilenamePath(output).c_str())); + std::string ruleFile = + cmStrCat(ruleDir, '/', cmSystemTools::GetFilenameName(output), ".rule"); return ruleFile; } diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index 6509b56..cd48474 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -182,7 +182,7 @@ void cmGlobalVisualStudio14Generator::SetWindowsTargetPlatformVersion( mf->DisplayStatus(e.str(), -1); } mf->AddDefinition("CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION", - this->WindowsTargetPlatformVersion.c_str()); + this->WindowsTargetPlatformVersion); } bool cmGlobalVisualStudio14Generator::SelectWindowsStoreToolset( diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index 8e67fad..e8e9ece 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -145,10 +145,8 @@ void cmGlobalVisualStudio71Generator::WriteProjectDepends( for (std::string const& name : depends) { std::string guid = this->GetGUID(name); if (guid.empty()) { - std::string m = "Target: "; - m += target->GetName(); - m += " depends on unknown target: "; - m += name; + std::string m = cmStrCat("Target: ", target->GetName(), + " depends on unknown target: ", name); cmSystemTools::Error(m); } fout << "\t\t{" << guid << "} = {" << guid << "}\n"; @@ -201,7 +199,7 @@ void cmGlobalVisualStudio71Generator::WriteProjectConfigurations( if (target.GetProperty("EXTERNAL_MSPROJECT")) { if (const char* m = target.GetProperty("MAP_IMPORTED_CONFIG_" + cmSystemTools::UpperCase(i))) { - cmSystemTools::ExpandListArgument(m, mapConfig); + cmExpandList(m, mapConfig); if (!mapConfig.empty()) { dstConfig = mapConfig[0].c_str(); } diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 8764ee4..26ceedd 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -8,7 +8,9 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmUuid.h" +#include "cm_string_view.hxx" #include "cmake.h" #include "cmsys/Encoding.hxx" @@ -64,8 +66,9 @@ const std::string& cmGlobalVisualStudio7Generator::GetIntelProjectVersion() // Compute the version of the Intel plugin to the VS IDE. // If the key does not exist then use a default guess. std::string intelVersion; - std::string vskey = this->GetRegistryBase(); - vskey += "\\Packages\\" CM_INTEL_PLUGIN_GUID ";ProductVersion"; + std::string vskey = + cmStrCat(this->GetRegistryBase(), + "\\Packages\\" CM_INTEL_PLUGIN_GUID ";ProductVersion"); cmSystemTools::ReadRegistryValue(vskey, intelVersion, cmSystemTools::KeyWOW64_32); unsigned int intelVersionNumber = ~0u; @@ -121,8 +124,7 @@ bool cmGlobalVisualStudio7Generator::FindMakeProgram(cmMakefile* mf) if (!this->cmGlobalVisualStudioGenerator::FindMakeProgram(mf)) { return false; } - mf->AddDefinition("CMAKE_VS_DEVENV_COMMAND", - this->GetDevEnvCommand().c_str()); + mf->AddDefinition("CMAKE_VS_DEVENV_COMMAND", this->GetDevEnvCommand()); return true; } @@ -152,8 +154,9 @@ std::string cmGlobalVisualStudio7Generator::FindDevEnvCommand() } // Search where VS15Preview places it. - vskey = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7;"; - vskey += this->GetIDEVersion(); + vskey = cmStrCat( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7;", + this->GetIDEVersion()); if (cmSystemTools::ReadRegistryValue(vskey.c_str(), vscmd, cmSystemTools::KeyWOW64_32)) { cmSystemTools::ConvertToUnixSlashes(vscmd); @@ -255,7 +258,7 @@ cmLocalGenerator* cmGlobalVisualStudio7Generator::CreateLocalGenerator( return lg; } -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) Json::Value cmGlobalVisualStudio7Generator::GetJson() const { Json::Value generator = this->cmGlobalVisualStudioGenerator::GetJson(); @@ -268,7 +271,7 @@ bool cmGlobalVisualStudio7Generator::SetSystemName(std::string const& s, cmMakefile* mf) { mf->AddDefinition("CMAKE_VS_INTEL_Fortran_PROJECT_VERSION", - this->GetIntelProjectVersion().c_str()); + this->GetIntelProjectVersion()); return this->cmGlobalVisualStudioGenerator::SetSystemName(s, mf); } @@ -293,10 +296,8 @@ void cmGlobalVisualStudio7Generator::OutputSLNFile( return; } this->CurrentProject = root->GetProjectName(); - std::string fname = root->GetCurrentBinaryDirectory(); - fname += "/"; - fname += root->GetProjectName(); - fname += ".sln"; + std::string fname = cmStrCat(root->GetCurrentBinaryDirectory(), '/', + root->GetProjectName(), ".sln"); cmGeneratedFileStream fout(fname.c_str()); fout.SetCopyIfDifferent(true); if (!fout) { @@ -433,16 +434,15 @@ void cmGlobalVisualStudio7Generator::WriteTargetDepends( void cmGlobalVisualStudio7Generator::WriteFolders(std::ostream& fout) { - const char* prefix = "CMAKE_FOLDER_GUID_"; - const std::string::size_type skip_prefix = strlen(prefix); + cm::string_view const prefix = "CMAKE_FOLDER_GUID_"; std::string guidProjectTypeFolder = "2150E333-8FDC-42A3-9474-1A3956D46DE8"; for (auto const& iter : VisualStudioFolders) { std::string fullName = iter.first; std::string guid = this->GetGUID(fullName); std::replace(fullName.begin(), fullName.end(), '/', '\\'); - if (cmSystemTools::StringStartsWith(fullName.c_str(), prefix)) { - fullName = fullName.substr(skip_prefix); + if (cmHasPrefix(fullName, prefix)) { + fullName = fullName.substr(prefix.size()); } std::string nameOnly = cmSystemTools::GetFilenameName(fullName); @@ -511,16 +511,15 @@ void cmGlobalVisualStudio7Generator::WriteSLNGlobalSections( extensibilityAddInsOverridden = true; } fout << "\tGlobalSection(" << name << ") = " << sectionType << "\n"; - std::vector<std::string> keyValuePairs; - cmSystemTools::ExpandListArgument(root->GetMakefile()->GetProperty(it), - keyValuePairs); + std::vector<std::string> keyValuePairs = + cmExpandedList(root->GetMakefile()->GetProperty(it)); for (std::string const& itPair : keyValuePairs) { const std::string::size_type posEqual = itPair.find('='); if (posEqual != std::string::npos) { const std::string key = - cmSystemTools::TrimWhitespace(itPair.substr(0, posEqual)); + cmTrimWhitespace(itPair.substr(0, posEqual)); const std::string value = - cmSystemTools::TrimWhitespace(itPair.substr(posEqual + 1)); + cmTrimWhitespace(itPair.substr(posEqual + 1)); fout << "\t\t" << key << " = " << value << "\n"; if (key == "SolutionGuid") { addGuid = false; @@ -555,12 +554,10 @@ std::string cmGlobalVisualStudio7Generator::WriteUtilityDepend( { std::vector<std::string> configs; target->Target->GetMakefile()->GetConfigurations(configs); - std::string pname = target->GetName(); - pname += "_UTILITY"; - std::string fname = target->GetLocalGenerator()->GetCurrentBinaryDirectory(); - fname += "/"; - fname += pname; - fname += ".vcproj"; + std::string pname = cmStrCat(target->GetName(), "_UTILITY"); + std::string fname = + cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/', + pname, ".vcproj"); cmGeneratedFileStream fout(fname.c_str()); fout.SetCopyIfDifferent(true); std::string guid = this->GetGUID(pname.c_str()); @@ -617,9 +614,8 @@ std::string cmGlobalVisualStudio7Generator::GetGUID(std::string const& name) return std::string(storedGUID); } // Compute a GUID that is deterministic but unique to the build tree. - std::string input = this->CMakeInstance->GetState()->GetBinaryDirectory(); - input += "|"; - input += name; + std::string input = + cmStrCat(this->CMakeInstance->GetState()->GetBinaryDirectory(), '|', name); cmUuid uuidGenerator; @@ -668,8 +664,7 @@ std::set<std::string> cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( cmGeneratorExpression ge; std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(propertyValue); - if (cmSystemTools::IsOn( - cge->Evaluate(target->GetLocalGenerator(), i))) { + if (cmIsOn(cge->Evaluate(target->GetLocalGenerator(), i))) { activeConfigs.insert(i); } } @@ -685,7 +680,7 @@ std::set<std::string> cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( for (std::string const& i : configs) { const char* propertyValue = target->GetFeature("EXCLUDE_FROM_DEFAULT_BUILD", i); - if (cmSystemTools::IsOff(propertyValue)) { + if (cmIsOff(propertyValue)) { activeConfigs.insert(i); } } diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index f004afb..9b84732 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -23,7 +23,7 @@ public: //! Create a local generator appropriate to this Global Generator cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) Json::Value GetJson() const override; #endif diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 85ddc85..b0c065f 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -26,9 +26,9 @@ std::string cmGlobalVisualStudio8Generator::FindDevEnvCommand() { // First look for VCExpress. std::string vsxcmd; - std::string vsxkey = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\"; - vsxkey += this->GetIDEVersion(); - vsxkey += ";InstallDir"; + std::string vsxkey = + cmStrCat("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\", + this->GetIDEVersion(), ";InstallDir"); if (cmSystemTools::ReadRegistryValue(vsxkey.c_str(), vsxcmd, cmSystemTools::KeyWOW64_32)) { cmSystemTools::ConvertToUnixSlashes(vsxcmd); @@ -54,8 +54,7 @@ void cmGlobalVisualStudio8Generator::EnableLanguage( void cmGlobalVisualStudio8Generator::AddPlatformDefinitions(cmMakefile* mf) { if (this->TargetsWindowsCE()) { - mf->AddDefinition("CMAKE_VS_WINCE_VERSION", - this->WindowsCEVersion.c_str()); + mf->AddDefinition("CMAKE_VS_WINCE_VERSION", this->WindowsCEVersion); } } @@ -117,20 +116,17 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() // Create a list of all stamp files for this project. std::vector<std::string> stamps; - std::string stampList = "CMakeFiles/"; - stampList += cmGlobalVisualStudio8Generator::GetGenerateStampList(); + std::string stampList = cmStrCat( + "CMakeFiles/", cmGlobalVisualStudio8Generator::GetGenerateStampList()); { std::string stampListFile = - generators[0]->GetMakefile()->GetCurrentBinaryDirectory(); - stampListFile += "/"; - stampListFile += stampList; + cmStrCat(generators[0]->GetMakefile()->GetCurrentBinaryDirectory(), '/', + stampList); std::string stampFile; cmGeneratedFileStream fout(stampListFile.c_str()); for (cmLocalGenerator const* gi : generators) { - stampFile = gi->GetMakefile()->GetCurrentBinaryDirectory(); - stampFile += "/"; - stampFile += "CMakeFiles/"; - stampFile += "generate.stamp"; + stampFile = cmStrCat(gi->GetMakefile()->GetCurrentBinaryDirectory(), + "/CMakeFiles/generate.stamp"); fout << stampFile << "\n"; stamps.push_back(stampFile); } @@ -177,11 +173,9 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() // Create a rule to re-run CMake. cmCustomCommandLine commandLine; commandLine.push_back(cmSystemTools::GetCMakeCommand()); - std::string argS = "-S"; - argS += lg->GetSourceDirectory(); + std::string argS = cmStrCat("-S", lg->GetSourceDirectory()); commandLine.push_back(argS); - std::string argB = "-B"; - argB += lg->GetBinaryDirectory(); + std::string argB = cmStrCat("-B", lg->GetBinaryDirectory()); commandLine.push_back(argB); commandLine.push_back("--check-stamp-list"); commandLine.push_back(stampList.c_str()); @@ -251,7 +245,7 @@ void cmGlobalVisualStudio8Generator::WriteProjectConfigurations( if (target.GetProperty("EXTERNAL_MSPROJECT")) { if (const char* m = target.GetProperty("MAP_IMPORTED_CONFIG_" + cmSystemTools::UpperCase(i))) { - cmSystemTools::ExpandListArgument(m, mapConfig); + cmExpandList(m, mapConfig); if (!mapConfig.empty()) { dstConfig = mapConfig[0].c_str(); } @@ -300,7 +294,7 @@ bool cmGlobalVisualStudio8Generator::DeployInhibited( cmGeneratorExpression ge; std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(propStr); std::string prop = cge->Evaluate(target.LocalGenerator, config); - rVal = cmSystemTools::IsOn(prop); + rVal = cmIsOn(prop); } return rVal; } diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index cd0355f..6e0b804 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -57,7 +57,7 @@ void cmGlobalVisualStudioGenerator::EnableLanguage( std::vector<std::string> const& lang, cmMakefile* mf, bool optional) { mf->AddDefinition("CMAKE_VS_PLATFORM_NAME_DEFAULT", - this->DefaultPlatformName.c_str()); + this->DefaultPlatformName); this->cmGlobalGenerator::EnableLanguage(lang, mf, optional); } @@ -69,7 +69,7 @@ bool cmGlobalVisualStudioGenerator::SetGeneratorPlatform(std::string const& p, } else if (this->GetPlatformName() == "Itanium") { mf->AddDefinition("CMAKE_FORCE_IA64", "TRUE"); } - mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName().c_str()); + mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName()); return this->cmGlobalGenerator::SetGeneratorPlatform(p, mf); } @@ -104,6 +104,9 @@ const char* cmGlobalVisualStudioGenerator::GetIDEVersion() const void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout) { + char utf8bom[] = { char(0xEF), char(0xBB), char(0xBF) }; + fout.write(utf8bom, 3); + switch (this->Version) { case cmGlobalVisualStudioGenerator::VS9: fout << "Microsoft Visual Studio Solution File, Format Version 10.00\n"; @@ -224,8 +227,8 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets() void cmGlobalVisualStudioGenerator::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { - std::string dir = gt->LocalGenerator->GetCurrentBinaryDirectory(); - dir += "/"; + std::string dir = + cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/'); std::string tgtDir = gt->LocalGenerator->GetTargetDirectory(gt); if (!tgtDir.empty()) { dir += tgtDir; @@ -258,8 +261,8 @@ void cmGlobalVisualStudioGenerator::ConfigureCMakeVisualStudioMacros() std::string dir = this->GetUserMacrosDirectory(); if (!dir.empty()) { - std::string src = cmSystemTools::GetCMakeRoot(); - src += "/Templates/" CMAKE_VSMACROS_FILENAME; + std::string src = cmStrCat(cmSystemTools::GetCMakeRoot(), + "/Templates/" CMAKE_VSMACROS_FILENAME); std::string dst = dir + "/CMakeMacros/" CMAKE_VSMACROS_FILENAME; @@ -306,10 +309,9 @@ void cmGlobalVisualStudioGenerator::CallVisualStudioMacro( if (vsSolutionFile) { topLevelSlnName = vsSolutionFile; } else { - topLevelSlnName = mf->GetCurrentBinaryDirectory(); - topLevelSlnName += "/"; - topLevelSlnName += this->LocalGenerators[0]->GetProjectName(); - topLevelSlnName += ".sln"; + topLevelSlnName = + cmStrCat(mf->GetCurrentBinaryDirectory(), '/', + this->LocalGenerators[0]->GetProjectName(), ".sln"); } if (m == MacroReload) { @@ -487,8 +489,8 @@ bool cmGlobalVisualStudioGenerator::FindMakeProgram(cmMakefile* mf) // Visual Studio generators know how to lookup their build tool // directly instead of needing a helper module to do it, so we // do not actually need to put CMAKE_MAKE_PROGRAM into the cache. - if (cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) { - mf->AddDefinition("CMAKE_MAKE_PROGRAM", this->GetVSMakeProgram().c_str()); + if (cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) { + mf->AddDefinition("CMAKE_MAKE_PROGRAM", this->GetVSMakeProgram()); } return true; } @@ -553,9 +555,9 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile, if (ERROR_SUCCESS == result) { // Iterate the subkeys and look for the values of interest in each subkey: wchar_t subkeyname[256]; - DWORD cch_subkeyname = sizeof(subkeyname) * sizeof(subkeyname[0]); + DWORD cch_subkeyname = cm::size(subkeyname); wchar_t keyclass[256]; - DWORD cch_keyclass = sizeof(keyclass) * sizeof(keyclass[0]); + DWORD cch_keyclass = cm::size(keyclass); FILETIME lastWriteTime; lastWriteTime.dwHighDateTime = 0; lastWriteTime.dwLowDateTime = 0; @@ -569,8 +571,8 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile, if (ERROR_SUCCESS == result) { DWORD valueType = REG_SZ; wchar_t data1[256]; - DWORD cch_data1 = sizeof(data1) * sizeof(data1[0]); - RegQueryValueExW(hsubkey, L"Path", 0, &valueType, (LPBYTE)&data1[0], + DWORD cch_data1 = sizeof(data1); + RegQueryValueExW(hsubkey, L"Path", 0, &valueType, (LPBYTE)data1, &cch_data1); DWORD data2 = 0; @@ -618,8 +620,8 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile, } ++index; - cch_subkeyname = sizeof(subkeyname) * sizeof(subkeyname[0]); - cch_keyclass = sizeof(keyclass) * sizeof(keyclass[0]); + cch_subkeyname = cm::size(subkeyname); + cch_keyclass = cm::size(keyclass); lastWriteTime.dwHighDateTime = 0; lastWriteTime.dwLowDateTime = 0; } @@ -634,9 +636,7 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile, // follow the expected naming scheme. Expected naming scheme is that // the subkeys of OtherProjects7 is 0 to n-1, so it's ok to use "n" // as the name of the next subkey. - std::ostringstream ossNext; - ossNext << index; - nextAvailableSubKeyName = ossNext.str(); + nextAvailableSubKeyName = std::to_string(index); keyname = regKeyBase + "\\RecordingProject7"; hkey = NULL; @@ -646,9 +646,8 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile, if (ERROR_SUCCESS == result) { DWORD valueType = REG_SZ; wchar_t data1[256]; - DWORD cch_data1 = sizeof(data1) * sizeof(data1[0]); - RegQueryValueExW(hkey, L"Path", 0, &valueType, (LPBYTE)&data1[0], - &cch_data1); + DWORD cch_data1 = sizeof(data1); + RegQueryValueExW(hkey, L"Path", 0, &valueType, (LPBYTE)data1, &cch_data1); DWORD data2 = 0; DWORD cch_data2 = sizeof(data2); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 7c2bcd3..a204fe0 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -5,11 +5,12 @@ #include "cmsys/RegularExpression.hxx" #include <assert.h> #include <iomanip> -#include <memory> // IWYU pragma: keep #include <sstream> #include <stdio.h> #include <string.h> +#include "cm_memory.hxx" + #include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" #include "cmCustomCommand.h" @@ -37,12 +38,12 @@ struct cmLinkImplementation; -#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(__APPLE__) +#if !defined(CMAKE_BOOTSTRAP) && defined(__APPLE__) # define HAVE_APPLICATION_SERVICES # include <ApplicationServices/ApplicationServices.h> #endif -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) # include "cmXMLParser.h" // parse the xml file storing the installed version of Xcode on @@ -187,7 +188,7 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator( if (name != GetActualName()) { return nullptr; } -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) cmXcodeVersionParser parser; std::string versionFile; { @@ -239,9 +240,8 @@ bool cmGlobalXCodeGenerator::FindMakeProgram(cmMakefile* mf) // The Xcode generator knows how to lookup its build tool // directly instead of needing a helper module to do it, so we // do not actually need to put CMAKE_MAKE_PROGRAM into the cache. - if (cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) { - mf->AddDefinition("CMAKE_MAKE_PROGRAM", - this->GetXcodeBuildCommand().c_str()); + if (cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) { + mf->AddDefinition("CMAKE_MAKE_PROGRAM", this->GetXcodeBuildCommand()); } return true; } @@ -282,8 +282,7 @@ bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts, } this->GeneratorToolset = ts; if (!this->GeneratorToolset.empty()) { - mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", - this->GeneratorToolset.c_str()); + mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", this->GeneratorToolset); } return true; } @@ -292,7 +291,7 @@ void cmGlobalXCodeGenerator::EnableLanguage( std::vector<std::string> const& lang, cmMakefile* mf, bool optional) { mf->AddDefinition("XCODE", "1"); - mf->AddDefinition("XCODE_VERSION", this->VersionString.c_str()); + mf->AddDefinition("XCODE_VERSION", this->VersionString); if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { mf->AddCacheDefinition( "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo", @@ -350,13 +349,10 @@ cmGlobalXCodeGenerator::GenerateBuildCommand( if (!projectName.empty()) { makeCommand.Add("-project"); - std::string projectArg = projectName; - projectArg += ".xcode"; - projectArg += "proj"; + std::string projectArg = cmStrCat(projectName, ".xcodeproj"); makeCommand.Add(projectArg); } - if (std::find(targetNames.begin(), targetNames.end(), "clean") != - targetNames.end()) { + if (cmContains(targetNames, "clean")) { makeCommand.Add("clean"); makeCommand.Add("-target", "ALL_BUILD"); } else { @@ -477,8 +473,8 @@ void cmGlobalXCodeGenerator::SetGenerationRoot(cmLocalGenerator* root) this->CurrentLocalGenerator->GetCurrentBinaryDirectory(), this->ProjectOutputDirectoryComponents); - this->CurrentXCodeHackMakefile = root->GetCurrentBinaryDirectory(); - this->CurrentXCodeHackMakefile += "/CMakeScripts"; + this->CurrentXCodeHackMakefile = + cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeScripts"); cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile); this->CurrentXCodeHackMakefile += "/XCODE_DEPEND_HELPER.make"; } @@ -488,8 +484,7 @@ std::string cmGlobalXCodeGenerator::PostBuildMakeTarget( { std::string target = tName; std::replace(target.begin(), target.end(), ' ', '_'); - std::string out = "PostBuild." + target; - out += "." + configName; + std::string out = cmStrCat("PostBuild.", target, '.', configName); return out; } @@ -597,8 +592,8 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile( lfiles.emplace_back(cm->GetGlobVerifyStamp()); } - this->CurrentReRunCMakeMakefile = root->GetCurrentBinaryDirectory(); - this->CurrentReRunCMakeMakefile += "/CMakeScripts"; + this->CurrentReRunCMakeMakefile = + cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeScripts"); cmSystemTools::MakeDirectory(this->CurrentReRunCMakeMakefile); this->CurrentReRunCMakeMakefile += "/ReRunCMake.make"; cmGeneratedFileStream makefileStream(this->CurrentReRunCMakeMakefile); @@ -616,10 +611,8 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile( } makefileStream << "\n"; - std::string checkCache = root->GetBinaryDirectory(); - checkCache += "/"; - checkCache += "CMakeFiles/"; - checkCache += "cmake.check_cache"; + std::string checkCache = + cmStrCat(root->GetBinaryDirectory(), "/CMakeFiles/cmake.check_cache"); if (cm->DoWriteGlobVerifyTarget()) { makefileStream << ".NOTPARALLEL:\n\n"; @@ -882,8 +875,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( const char* extraFileAttributes = sf->GetProperty("XCODE_FILE_ATTRIBUTES"); if (extraFileAttributes) { // Expand the list of attributes. - std::vector<std::string> attributes; - cmSystemTools::ExpandListArgument(extraFileAttributes, attributes); + std::vector<std::string> attributes = cmExpandedList(extraFileAttributes); // Store the attributes. for (const auto& attribute : attributes) { @@ -901,11 +893,10 @@ void cmGlobalXCodeGenerator::AddXCodeProjBuildRule( cmGeneratorTarget* target, std::vector<cmSourceFile*>& sources) const { std::string listfile = - target->GetLocalGenerator()->GetCurrentSourceDirectory(); - listfile += "/CMakeLists.txt"; + cmStrCat(target->GetLocalGenerator()->GetCurrentSourceDirectory(), + "/CMakeLists.txt"); cmSourceFile* srcCMakeLists = target->Makefile->GetOrCreateSource(listfile); - if (std::find(sources.begin(), sources.end(), srcCMakeLists) == - sources.end()) { + if (!cmContains(sources, srcCMakeLists)) { sources.push_back(srcCMakeLists); } } @@ -1399,13 +1390,9 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt) // linker language. This should convince Xcode to choose the proper // language. cmMakefile* mf = gtgt->Target->GetMakefile(); - std::string fname = gtgt->GetLocalGenerator()->GetCurrentBinaryDirectory(); - fname += "/CMakeFiles"; - fname += "/"; - fname += gtgt->GetName(); - fname += "-CMakeForceLinker"; - fname += "."; - fname += cmSystemTools::LowerCase(llang); + std::string fname = cmStrCat( + gtgt->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/CMakeFiles/", + gtgt->GetName(), "-CMakeForceLinker.", cmSystemTools::LowerCase(llang)); { cmGeneratedFileStream fout(fname); fout << "\n"; @@ -1418,10 +1405,8 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt) bool cmGlobalXCodeGenerator::IsHeaderFile(cmSourceFile* sf) { - const std::vector<std::string>& hdrExts = - this->CMakeInstance->GetHeaderExtensions(); - return (std::find(hdrExts.begin(), hdrExts.end(), sf->GetExtension()) != - hdrExts.end()); + return cmContains(this->CMakeInstance->GetHeaderExtensions(), + sf->GetExtension()); } cmXCodeObject* cmGlobalXCodeGenerator::CreateBuildPhase( @@ -1462,15 +1447,11 @@ void cmGlobalXCodeGenerator::CreateCustomCommands( cmd[0].push_back(cmSystemTools::GetCMakeCommand()); cmd[0].push_back("-E"); cmd[0].push_back("cmake_symlink_library"); - std::string str_file = "$<TARGET_FILE:"; - str_file += gtgt->GetName(); - str_file += ">"; - std::string str_so_file = "$<TARGET_SONAME_FILE:"; - str_so_file += gtgt->GetName(); - str_so_file += ">"; - std::string str_link_file = "$<TARGET_LINKER_FILE:"; - str_link_file += gtgt->GetName(); - str_link_file += ">"; + std::string str_file = cmStrCat("$<TARGET_FILE:", gtgt->GetName(), '>'); + std::string str_so_file = + cmStrCat("$<TARGET_SONAME_FILE:", gtgt->GetName(), '>'); + std::string str_link_file = + cmStrCat("$<TARGET_LINKER_FILE:", gtgt->GetName(), '>'); cmd[0].push_back(str_file); cmd[0].push_back(str_so_file); cmd[0].push_back(str_link_file); @@ -1637,15 +1618,11 @@ void cmGlobalXCodeGenerator::AddCommandsToBuildPhase( cmXCodeObject* buildphase, cmGeneratorTarget* target, std::vector<cmCustomCommand> const& commands, const char* name) { - std::string dir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory(); - dir += "/CMakeScripts"; + std::string dir = cmStrCat( + this->CurrentLocalGenerator->GetCurrentBinaryDirectory(), "/CMakeScripts"); cmSystemTools::MakeDirectory(dir); - std::string makefile = dir; - makefile += "/"; - makefile += target->GetName(); - makefile += "_"; - makefile += name; - makefile += ".make"; + std::string makefile = + cmStrCat(dir, '/', target->GetName(), '_', name, ".make"); for (const auto& currentConfig : this->CurrentConfigurationTypes) { this->CreateCustomRulesMakefile(makefile.c_str(), target, commands, @@ -1654,12 +1631,10 @@ void cmGlobalXCodeGenerator::AddCommandsToBuildPhase( std::string cdir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory(); cdir = this->ConvertToRelativeForMake(cdir); - std::string makecmd = "make -C "; - makecmd += cdir; - makecmd += " -f "; - makecmd += this->ConvertToRelativeForMake((makefile + "$CONFIGURATION")); - makecmd += " OBJDIR=$(basename \"$OBJECT_FILE_DIR_normal\")"; - makecmd += " all"; + std::string makecmd = + cmStrCat("make -C ", cdir, " -f ", + this->ConvertToRelativeForMake((makefile + "$CONFIGURATION")), + " OBJDIR=$(basename \"$OBJECT_FILE_DIR_normal\") all"); buildphase->AddAttribute("shellScript", this->CreateString(makecmd)); buildphase->AddAttribute("showEnvVarsInLog", this->CreateString("0")); } @@ -1668,8 +1643,7 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile( const char* makefileBasename, cmGeneratorTarget* target, std::vector<cmCustomCommand> const& commands, const std::string& configName) { - std::string makefileName = makefileBasename; - makefileName += configName; + std::string makefileName = cmStrCat(makefileBasename, configName); cmGeneratedFileStream makefileStream(makefileName); if (!makefileStream) { return; @@ -1732,9 +1706,10 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile( makefileStream << "\n"; if (const char* comment = ccg.GetComment()) { - std::string echo_cmd = "echo "; - echo_cmd += (this->CurrentLocalGenerator->EscapeForShell( - comment, ccg.GetCC().GetEscapeAllowMakeVars())); + std::string echo_cmd = + cmStrCat("echo ", + (this->CurrentLocalGenerator->EscapeForShell( + comment, ccg.GetCC().GetEscapeAllowMakeVars()))); makefileStream << "\t" << echo_cmd << "\n"; } @@ -1775,8 +1750,7 @@ void cmGlobalXCodeGenerator::AddPositionIndependentLinkAttribute( } buildSettings->AddAttribute( - "LD_NO_PIE", - this->CreateString(cmSystemTools::IsOn(PICValue) ? "NO" : "YES")); + "LD_NO_PIE", this->CreateString(cmIsOn(PICValue) ? "NO" : "YES")); } void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, @@ -1883,8 +1857,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, targetLinkFlags); } if (!configName.empty()) { - std::string linkFlagsVar = "LINK_FLAGS_"; - linkFlagsVar += cmSystemTools::UpperCase(configName); + std::string linkFlagsVar = + cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(configName)); if (const char* linkFlags = gtgt->GetProperty(linkFlagsVar)) { this->CurrentLocalGenerator->AppendFlags(extraLinkOptions, linkFlags); } @@ -2136,8 +2110,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, for (auto& include : includes) { if (this->NameResolvesToFramework(include)) { - std::string frameworkDir = include; - frameworkDir += "/../"; + std::string frameworkDir = cmStrCat(include, "/../"); frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir); if (emitted.insert(frameworkDir).second) { std::string incpath = this->XCodeEscapePath(frameworkDir); @@ -2483,20 +2456,16 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget( std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target, cmGeneratorTarget* gtgt) { - std::vector<std::string> const configVector = - cmSystemTools::ExpandedListArgument( - this->CurrentMakefile->GetRequiredDefinition( - "CMAKE_CONFIGURATION_TYPES")); + std::vector<std::string> const configVector = cmExpandedList( + this->CurrentMakefile->GetRequiredDefinition("CMAKE_CONFIGURATION_TYPES")); cmXCodeObject* configlist = this->CreateObject(cmXCodeObject::XCConfigurationList); cmXCodeObject* buildConfigurations = this->CreateObject(cmXCodeObject::OBJECT_LIST); configlist->AddAttribute("buildConfigurations", buildConfigurations); - std::string comment = "Build configuration list for "; - comment += cmXCodeObject::PBXTypeNames[target->GetIsA()]; - comment += " \""; - comment += gtgt->GetName(); - comment += "\""; + std::string comment = cmStrCat("Build configuration list for ", + cmXCodeObject::PBXTypeNames[target->GetIsA()], + " \"", gtgt->GetName(), '"'); configlist->SetComment(comment); target->AddAttribute("buildConfigurationList", this->CreateObjectReference(configlist)); @@ -2624,9 +2593,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeTarget( } std::string fullName; if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY) { - fullName = "lib"; - fullName += gtgt->GetName(); - fullName += ".a"; + fullName = cmStrCat("lib", gtgt->GetName(), ".a"); } else { fullName = gtgt->GetFullName(defConfig); } @@ -2663,8 +2630,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget( std::string cmGlobalXCodeGenerator::GetOrCreateId(const std::string& name, const std::string& id) { - std::string guidStoreName = name; - guidStoreName += "_GUID_CMAKE"; + std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE"); const char* storedGUID = this->CMakeInstance->GetCacheDefinition(guidStoreName); @@ -2719,9 +2685,7 @@ void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject* settings, if (!attr) { settings->AddAttribute(attribute, this->CreateString(value)); } else { - std::string oldValue = attr->GetString(); - oldValue += " "; - oldValue += value; + std::string oldValue = cmStrCat(attr->GetString(), ' ', value); attr->SetString(oldValue); } } @@ -2886,8 +2850,8 @@ bool cmGlobalXCodeGenerator::CreateGroups( // Add CMakeLists.txt file for user convenience. { std::string listfile = - gtgt->GetLocalGenerator()->GetCurrentSourceDirectory(); - listfile += "/CMakeLists.txt"; + cmStrCat(gtgt->GetLocalGenerator()->GetCurrentSourceDirectory(), + "/CMakeLists.txt"); cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(listfile); addSourceToGroup(sf->GetFullPath()); } @@ -2929,12 +2893,10 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup( std::string target; const std::string targetFolder = gtgt->GetEffectiveFolderName(); if (!targetFolder.empty()) { - target = targetFolder; - target += "/"; + target = cmStrCat(targetFolder, '/'); } target += gtgt->GetName(); - s = target + "/"; - s += sg->GetFullName(); + s = cmStrCat(target, '/', sg->GetFullName()); std::map<std::string, cmXCodeObject*>::iterator it = this->GroupNameMap.find(s); if (it != this->GroupNameMap.end()) { @@ -2946,8 +2908,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup( if (it != this->TargetGroup.end()) { tgroup = it->second; } else { - std::vector<std::string> tgt_folders = - cmSystemTools::tokenize(target, "/"); + std::vector<std::string> tgt_folders = cmTokenize(target, "/"); std::string curr_tgt_folder; for (std::vector<std::string>::size_type i = 0; i < tgt_folders.size(); i++) { @@ -2979,10 +2940,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup( // It's a recursive folder structure, let's find the real parent group if (sg->GetFullName() != sg->GetName()) { - std::string curr_folder = target; - curr_folder += "/"; - for (auto const& folder : - cmSystemTools::tokenize(sg->GetFullName(), "\\")) { + std::string curr_folder = cmStrCat(target, '/'); + for (auto const& folder : cmTokenize(sg->GetFullName(), "\\")) { curr_folder += folder; std::map<std::string, cmXCodeObject*>::iterator i_folder = this->GroupNameMap.find(curr_folder); @@ -2994,7 +2953,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup( } else { tgroup = i_folder->second; } - curr_folder = curr_folder + "\\"; + curr_folder += "\\"; } return tgroup; } @@ -3046,8 +3005,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( this->RootObject = this->CreateObject(cmXCodeObject::PBXProject); this->RootObject->SetComment("Project object"); - std::string project_id = "PROJECT_"; - project_id += root->GetProjectName(); + std::string project_id = cmStrCat("PROJECT_", root->GetProjectName()); this->RootObject->SetId( this->GetOrCreateId(project_id, this->RootObject->GetId())); @@ -3098,10 +3056,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( } configlist->AddAttribute("buildConfigurations", buildConfigurations); - std::string comment = "Build configuration list for PBXProject"; - comment += " \""; - comment += this->CurrentProject; - comment += "\""; + std::string comment = cmStrCat("Build configuration list for PBXProject \"", + this->CurrentProject, '"'); configlist->SetComment(comment); configlist->AddAttribute("defaultConfigurationIsVisible", this->CreateString("0")); @@ -3150,8 +3106,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( this->CreateString(swiftVersion)); } - std::string symroot = root->GetCurrentBinaryDirectory(); - symroot += "/build"; + std::string symroot = cmStrCat(root->GetCurrentBinaryDirectory(), "/build"); buildSettings->AddAttribute("SYMROOT", this->CreateString(symroot)); for (auto& config : configs) { @@ -3208,15 +3163,9 @@ std::string cmGlobalXCodeGenerator::GetObjectsDirectory( const std::string& projName, const std::string& configName, const cmGeneratorTarget* t, const std::string& variant) const { - std::string dir = t->GetLocalGenerator()->GetCurrentBinaryDirectory(); - dir += "/"; - dir += projName; - dir += ".build/"; - dir += configName; - dir += "/"; - dir += t->GetName(); - dir += ".build/"; - dir += variant; + std::string dir = cmStrCat( + t->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/', projName, + ".build/", configName, '/', t->GetName(), ".build/", variant); return dir; } @@ -3226,8 +3175,7 @@ void cmGlobalXCodeGenerator::ComputeArchitectures(cmMakefile* mf) const char* osxArch = mf->GetDefinition("CMAKE_OSX_ARCHITECTURES"); const char* sysroot = mf->GetDefinition("CMAKE_OSX_SYSROOT"); if (osxArch && sysroot) { - cmSystemTools::ExpandListArgument(std::string(osxArch), - this->Architectures); + cmExpandList(std::string(osxArch), this->Architectures); } if (this->Architectures.empty()) { @@ -3342,12 +3290,10 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( for (auto objLib : objlibs) { const std::string objLibName = objLib->GetName(); - std::string d = + std::string d = cmStrCat( this->GetObjectsDirectory(this->CurrentProject, configName, objLib, - OBJECT_LIBRARY_ARTIFACT_DIR); - d += "lib"; - d += objLibName; - d += ".a"; + OBJECT_LIBRARY_ARTIFACT_DIR), + "lib", objLibName, ".a"); std::string dependency = this->ConvertToRelativeForMake(d); makefileStream << "\\\n\t" << dependency; @@ -3364,10 +3310,8 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( std::string universal = this->GetObjectsDirectory( this->CurrentProject, configName, gt, "$(OBJDIR)/"); for (const auto& architecture : this->Architectures) { - std::string universalFile = universal; - universalFile += architecture; - universalFile += "/"; - universalFile += gt->GetFullName(configName); + std::string universalFile = cmStrCat(universal, architecture, '/', + gt->GetFullName(configName)); makefileStream << "\t/bin/rm -f " << this->ConvertToRelativeForMake(universalFile) << "\n"; @@ -3395,10 +3339,8 @@ void cmGlobalXCodeGenerator::OutputXCodeProject( if (!this->CreateXCodeObjects(root, generators)) { return; } - std::string xcodeDir = root->GetCurrentBinaryDirectory(); - xcodeDir += "/"; - xcodeDir += root->GetProjectName(); - xcodeDir += ".xcodeproj"; + std::string xcodeDir = cmStrCat(root->GetCurrentBinaryDirectory(), '/', + root->GetProjectName(), ".xcodeproj"); cmSystemTools::MakeDirectory(xcodeDir); std::string xcodeProjFile = xcodeDir + "/project.pbxproj"; cmGeneratedFileStream fout(xcodeProjFile); @@ -3472,12 +3414,12 @@ bool cmGlobalXCodeGenerator::OutputXCodeSharedSchemes( void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings( const std::string& xcProjDir, bool hasGeneratedSchemes) { - std::string xcodeSharedDataDir = xcProjDir; - xcodeSharedDataDir += "/project.xcworkspace/xcshareddata"; + std::string xcodeSharedDataDir = + cmStrCat(xcProjDir, "/project.xcworkspace/xcshareddata"); cmSystemTools::MakeDirectory(xcodeSharedDataDir); - std::string workspaceSettingsFile = xcodeSharedDataDir; - workspaceSettingsFile += "/WorkspaceSettings.xcsettings"; + std::string workspaceSettingsFile = + cmStrCat(xcodeSharedDataDir, "/WorkspaceSettings.xcsettings"); cmGeneratedFileStream fout(workspaceSettingsFile); fout.SetCopyIfDifferent(true); @@ -3583,9 +3525,7 @@ std::string cmGlobalXCodeGenerator::RelativeToBinary(const std::string& p) std::string cmGlobalXCodeGenerator::XCodeEscapePath(const std::string& p) { if (p.find(' ') != std::string::npos) { - std::string t = "\""; - t += p; - t += "\""; + std::string t = cmStrCat('"', p, '"'); return t; } return p; @@ -3607,9 +3547,7 @@ std::string cmGlobalXCodeGenerator::LookupFlags( const std::string& varNameSuffix, const std::string& default_flags) { if (!varNameLang.empty()) { - std::string varName = varNamePrefix; - varName += varNameLang; - varName += varNameSuffix; + std::string varName = cmStrCat(varNamePrefix, varNameLang, varNameSuffix); if (const char* varValue = this->CurrentMakefile->GetDefinition(varName)) { if (*varValue) { return varValue; @@ -3629,8 +3567,7 @@ void cmGlobalXCodeGenerator::AppendDefines(BuildObjectListOrString& defs, } // Expand the list of definitions. - std::vector<std::string> defines; - cmSystemTools::ExpandListArgument(defines_list, defines); + std::vector<std::string> defines = cmExpandedList(defines_list); // Store the definitions in the string. this->AppendDefines(defs, defines, dflag); @@ -3644,8 +3581,7 @@ void cmGlobalXCodeGenerator::AppendDefines( std::string def; for (auto const& define : defines) { // Start with -D if requested. - def = dflag ? "-D" : ""; - def += define; + def = cmStrCat(dflag ? "-D" : "", define); // Append the flag with needed escapes. std::string tmp; @@ -3706,11 +3642,9 @@ void cmGlobalXCodeGenerator::AppendFlag(std::string& flags, std::string cmGlobalXCodeGenerator::ComputeInfoPListLocation( cmGeneratorTarget* target) { - std::string plist = target->GetLocalGenerator()->GetCurrentBinaryDirectory(); - plist += "/CMakeFiles"; - plist += "/"; - plist += target->GetName(); - plist += ".dir/Info.plist"; + std::string plist = + cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), + "/CMakeFiles/", target->GetName(), ".dir/Info.plist"); return plist; } @@ -3744,7 +3678,7 @@ bool cmGlobalXCodeGenerator::UseEffectivePlatformName(cmMakefile* mf) const return mf->PlatformIsAppleEmbedded(); } - return cmSystemTools::IsOn(epnValue); + return cmIsOn(epnValue); } bool cmGlobalXCodeGenerator::ShouldStripResourcePath(cmMakefile*) const @@ -3757,10 +3691,10 @@ void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { std::string configName = this->GetCMakeCFGIntDir(); - std::string dir = this->GetObjectsDirectory( - "$(PROJECT_NAME)", configName, gt, "$(OBJECT_FILE_DIR_normal:base)/"); - dir += this->ObjectDirArch; - dir += "/"; + std::string dir = + cmStrCat(this->GetObjectsDirectory("$(PROJECT_NAME)", configName, gt, + "$(OBJECT_FILE_DIR_normal:base)/"), + this->ObjectDirArch, '/'); gt->ObjectDirectory = dir; } diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index a75d8a9..9b58f61 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -4,7 +4,7 @@ #include <cstddef> #include <iostream> -#include <memory> // IWYU pragma: keep +#include <memory> #include <sstream> #include <utility> @@ -15,6 +15,7 @@ #include "cmMakefile.h" #include "cmState.h" #include "cmStateSnapshot.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmake.h" @@ -73,7 +74,8 @@ std::map<std::string, LinkLibraryScopeType> getScopedLinkLibrariesFromTarget( { char sep = ';'; std::map<std::string, LinkLibraryScopeType> tokens; - size_t start = 0, end = 0; + size_t start = 0; + size_t end = 0; const char* pInterfaceLinkLibraries = Target->GetProperty("INTERFACE_LINK_LIBRARIES"); @@ -233,9 +235,8 @@ void cmGraphVizWriter::ReadSettings( this->TargetsToIgnoreRegex.clear(); if (!ignoreTargetsRegexes.empty()) { - std::vector<std::string> ignoreTargetsRegExVector; - cmSystemTools::ExpandListArgument(ignoreTargetsRegexes, - ignoreTargetsRegExVector); + std::vector<std::string> ignoreTargetsRegExVector = + cmExpandedList(ignoreTargetsRegexes); for (std::string const& currentRegexString : ignoreTargetsRegExVector) { cmsys::RegularExpression currentRegex; if (!currentRegex.compile(currentRegexString)) { @@ -266,10 +267,8 @@ void cmGraphVizWriter::WriteTargetDependersFiles(const std::string& fileName) continue; } - std::string currentFilename = fileName; - currentFilename += "."; - currentFilename += ptr.first; - currentFilename += ".dependers"; + std::string currentFilename = + cmStrCat(fileName, '.', ptr.first, ".dependers"); cmGeneratedFileStream str(currentFilename); if (!str) { @@ -311,9 +310,7 @@ void cmGraphVizWriter::WritePerTargetFiles(const std::string& fileName) std::set<std::string> insertedConnections; std::set<std::string> insertedNodes; - std::string currentFilename = fileName; - currentFilename += "."; - currentFilename += ptr.first; + std::string currentFilename = cmStrCat(fileName, '.', ptr.first); cmGeneratedFileStream str(currentFilename); if (!str) { return; @@ -401,9 +398,7 @@ void cmGraphVizWriter::WriteConnections( continue; } - std::string connectionName = myNodeName; - connectionName += "-"; - connectionName += libNameIt->second; + std::string connectionName = cmStrCat(myNodeName, '-', libNameIt->second); if (insertedConnections.find(connectionName) == insertedConnections.end()) { insertedConnections.insert(connectionName); @@ -463,9 +458,8 @@ void cmGraphVizWriter::WriteDependerConnections( this->TargetNamesNodes.find(tptr.first); if (dependerNodeNameIt != this->TargetNamesNodes.end()) { - std::string connectionName = dependerNodeNameIt->second; - connectionName += "-"; - connectionName += myNodeName; + std::string connectionName = + cmStrCat(dependerNodeNameIt->second, '-', myNodeName); if (insertedConnections.find(connectionName) == insertedConnections.end()) { diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx index 7b992d7..e80aa8e 100644 --- a/Source/cmIDEOptions.cxx +++ b/Source/cmIDEOptions.cxx @@ -8,7 +8,7 @@ #include "cmAlgorithms.h" #include "cmIDEFlagTable.h" -#include "cmSystemTools.h" +#include "cmStringAlgorithms.h" cmIDEOptions::cmIDEOptions() { @@ -166,7 +166,7 @@ void cmIDEOptions::AddDefines(std::string const& defines) { if (!defines.empty()) { // Expand the list of definitions. - cmSystemTools::ExpandListArgument(defines, this->Defines); + cmExpandList(defines, this->Defines); } } void cmIDEOptions::AddDefines(const std::vector<std::string>& defines) @@ -188,7 +188,7 @@ void cmIDEOptions::AddIncludes(std::string const& includes) { if (!includes.empty()) { // Expand the list of includes. - cmSystemTools::ExpandListArgument(includes, this->Includes); + cmExpandList(includes, this->Includes); } } void cmIDEOptions::AddIncludes(const std::vector<std::string>& includes) diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index d1f8f58..f719041 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -2,16 +2,24 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmIfCommand.h" +#include "cm_memory.hxx" +#include "cm_static_string_view.hxx" +#include "cm_string_view.hxx" + #include "cmConditionEvaluator.h" #include "cmExecutionStatus.h" #include "cmExpandedCommandArgument.h" +#include "cmFunctionBlocker.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmOutputConverter.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" -#include <memory> // IWYU pragma: keep +#include <string> +#include <utility> static std::string cmIfCommandError( std::vector<cmExpandedCommandArgument> const& args) @@ -25,192 +33,178 @@ static std::string cmIfCommandError( return err; } -//========================================================================= -bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, - cmMakefile& mf, - cmExecutionStatus& inStatus) +class cmIfFunctionBlocker : public cmFunctionBlocker +{ +public: + cm::string_view StartCommandName() const override { return "if"_s; } + cm::string_view EndCommandName() const override { return "endif"_s; } + + bool ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile&) const override; + + bool Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& inStatus) override; + + std::vector<cmListFileArgument> Args; + bool IsBlocking; + bool HasRun = false; + bool ElseSeen = false; +}; + +bool cmIfFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile&) const { - // we start by recording all the functions - if (lff.Name.Lower == "if") { - this->ScopeDepth++; - } else if (lff.Name.Lower == "endif") { - this->ScopeDepth--; - // if this is the endif for this if statement, then start executing - if (!this->ScopeDepth) { - // Remove the function blocker for this scope or bail. - std::unique_ptr<cmFunctionBlocker> fb( - mf.RemoveFunctionBlocker(this, lff)); - if (!fb) { - return false; + return lff.Arguments.empty() || lff.Arguments == this->Args; +} + +bool cmIfFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& inStatus) +{ + cmMakefile& mf = inStatus.GetMakefile(); + // execute the functions for the true parts of the if statement + int scopeDepth = 0; + for (cmListFileFunction const& func : functions) { + // keep track of scope depth + if (func.Name.Lower == "if") { + scopeDepth++; + } + if (func.Name.Lower == "endif") { + scopeDepth--; + } + // watch for our state change + if (scopeDepth == 0 && func.Name.Lower == "else") { + + if (this->ElseSeen) { + cmListFileBacktrace bt = mf.GetBacktrace(func); + mf.GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + "A duplicate ELSE command was found inside an IF block.", bt); + cmSystemTools::SetFatalErrorOccured(); + return true; } - // execute the functions for the true parts of the if statement - cmExecutionStatus status; - int scopeDepth = 0; - for (cmListFileFunction const& func : this->Functions) { - // keep track of scope depth - if (func.Name.Lower == "if") { - scopeDepth++; - } - if (func.Name.Lower == "endif") { - scopeDepth--; + this->IsBlocking = this->HasRun; + this->HasRun = true; + this->ElseSeen = true; + + // if trace is enabled, print a (trivially) evaluated "else" + // statement + if (!this->IsBlocking && mf.GetCMakeInstance()->GetTrace()) { + mf.PrintCommandTrace(func); + } + } else if (scopeDepth == 0 && func.Name.Lower == "elseif") { + if (this->ElseSeen) { + cmListFileBacktrace bt = mf.GetBacktrace(func); + mf.GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + "An ELSEIF command was found after an ELSE command.", bt); + cmSystemTools::SetFatalErrorOccured(); + return true; + } + + if (this->HasRun) { + this->IsBlocking = true; + } else { + // if trace is enabled, print the evaluated "elseif" statement + if (mf.GetCMakeInstance()->GetTrace()) { + mf.PrintCommandTrace(func); } - // watch for our state change - if (scopeDepth == 0 && func.Name.Lower == "else") { - - if (this->ElseSeen) { - cmListFileBacktrace bt = mf.GetBacktrace(func); - mf.GetCMakeInstance()->IssueMessage( - MessageType::FATAL_ERROR, - "A duplicate ELSE command was found inside an IF block.", bt); - cmSystemTools::SetFatalErrorOccured(); - return true; - } - this->IsBlocking = this->HasRun; - this->HasRun = true; - this->ElseSeen = true; + std::string errorString; - // if trace is enabled, print a (trivially) evaluated "else" - // statement - if (!this->IsBlocking && mf.GetCMakeInstance()->GetTrace()) { - mf.PrintCommandTrace(func); - } - } else if (scopeDepth == 0 && func.Name.Lower == "elseif") { - if (this->ElseSeen) { - cmListFileBacktrace bt = mf.GetBacktrace(func); - mf.GetCMakeInstance()->IssueMessage( - MessageType::FATAL_ERROR, - "An ELSEIF command was found after an ELSE command.", bt); + std::vector<cmExpandedCommandArgument> expandedArguments; + mf.ExpandArguments(func.Arguments, expandedArguments); + + MessageType messType; + + cmListFileContext conditionContext = + cmListFileContext::FromCommandContext( + func, this->GetStartingContext().FilePath); + + cmConditionEvaluator conditionEvaluator(mf, conditionContext, + mf.GetBacktrace(func)); + + bool isTrue = + conditionEvaluator.IsTrue(expandedArguments, errorString, messType); + + if (!errorString.empty()) { + std::string err = + cmStrCat(cmIfCommandError(expandedArguments), errorString); + cmListFileBacktrace bt = mf.GetBacktrace(func); + mf.GetCMakeInstance()->IssueMessage(messType, err, bt); + if (messType == MessageType::FATAL_ERROR) { cmSystemTools::SetFatalErrorOccured(); return true; } - - if (this->HasRun) { - this->IsBlocking = true; - } else { - // if trace is enabled, print the evaluated "elseif" statement - if (mf.GetCMakeInstance()->GetTrace()) { - mf.PrintCommandTrace(func); - } - - std::string errorString; - - std::vector<cmExpandedCommandArgument> expandedArguments; - mf.ExpandArguments(func.Arguments, expandedArguments); - - MessageType messType; - - cmListFileContext conditionContext = - cmListFileContext::FromCommandContext( - func, this->GetStartingContext().FilePath); - - cmConditionEvaluator conditionEvaluator(mf, conditionContext, - mf.GetBacktrace(func)); - - bool isTrue = conditionEvaluator.IsTrue(expandedArguments, - errorString, messType); - - if (!errorString.empty()) { - std::string err = cmIfCommandError(expandedArguments); - err += errorString; - cmListFileBacktrace bt = mf.GetBacktrace(func); - mf.GetCMakeInstance()->IssueMessage(messType, err, bt); - if (messType == MessageType::FATAL_ERROR) { - cmSystemTools::SetFatalErrorOccured(); - return true; - } - } - - if (isTrue) { - this->IsBlocking = false; - this->HasRun = true; - } - } } - // should we execute? - else if (!this->IsBlocking) { - status.Clear(); - mf.ExecuteCommand(func, status); - if (status.GetReturnInvoked()) { - inStatus.SetReturnInvoked(); - return true; - } - if (status.GetBreakInvoked()) { - inStatus.SetBreakInvoked(); - return true; - } - if (status.GetContinueInvoked()) { - inStatus.SetContinueInvoked(); - return true; - } + if (isTrue) { + this->IsBlocking = false; + this->HasRun = true; } } - return true; } - } - - // record the command - this->Functions.push_back(lff); - // always return true - return true; -} - -//========================================================================= -bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, - cmMakefile&) -{ - if (lff.Name.Lower == "endif") { - // if the endif has arguments, then make sure - // they match the arguments of the matching if - if (lff.Arguments.empty() || lff.Arguments == this->Args) { - return true; + // should we execute? + else if (!this->IsBlocking) { + cmExecutionStatus status(mf); + mf.ExecuteCommand(func, status); + if (status.GetReturnInvoked()) { + inStatus.SetReturnInvoked(); + return true; + } + if (status.GetBreakInvoked()) { + inStatus.SetBreakInvoked(); + return true; + } + if (status.GetContinueInvoked()) { + inStatus.SetContinueInvoked(); + return true; + } } } - - return false; + return true; } //========================================================================= -bool cmIfCommand::InvokeInitialPass( - const std::vector<cmListFileArgument>& args, cmExecutionStatus&) +bool cmIfCommand(std::vector<cmListFileArgument> const& args, + cmExecutionStatus& inStatus) { + cmMakefile& makefile = inStatus.GetMakefile(); std::string errorString; std::vector<cmExpandedCommandArgument> expandedArguments; - this->Makefile->ExpandArguments(args, expandedArguments); + makefile.ExpandArguments(args, expandedArguments); MessageType status; cmConditionEvaluator conditionEvaluator( - *(this->Makefile), this->Makefile->GetExecutionContext(), - this->Makefile->GetBacktrace()); + makefile, makefile.GetExecutionContext(), makefile.GetBacktrace()); bool isTrue = conditionEvaluator.IsTrue(expandedArguments, errorString, status); if (!errorString.empty()) { - std::string err = "if " + cmIfCommandError(expandedArguments); - err += errorString; + std::string err = + cmStrCat("if ", cmIfCommandError(expandedArguments), errorString); if (status == MessageType::FATAL_ERROR) { - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, err); + makefile.IssueMessage(MessageType::FATAL_ERROR, err); cmSystemTools::SetFatalErrorOccured(); return true; } - this->Makefile->IssueMessage(status, err); + makefile.IssueMessage(status, err); } - cmIfFunctionBlocker* f = new cmIfFunctionBlocker(); - // if is isn't true block the commands - f->ScopeDepth = 1; - f->IsBlocking = !isTrue; - if (isTrue) { - f->HasRun = true; + { + auto fb = cm::make_unique<cmIfFunctionBlocker>(); + // if is isn't true block the commands + fb->IsBlocking = !isTrue; + if (isTrue) { + fb->HasRun = true; + } + fb->Args = args; + makefile.AddFunctionBlocker(std::move(fb)); } - f->Args = args; - this->Makefile->AddFunctionBlocker(f); return true; } diff --git a/Source/cmIfCommand.h b/Source/cmIfCommand.h index d34ed02..820ffa4 100644 --- a/Source/cmIfCommand.h +++ b/Source/cmIfCommand.h @@ -5,61 +5,13 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <string> #include <vector> -#include "cmCommand.h" -#include "cmFunctionBlocker.h" -#include "cmListFileCache.h" - class cmExecutionStatus; -class cmExpandedCommandArgument; -class cmMakefile; - -class cmIfFunctionBlocker : public cmFunctionBlocker -{ -public: - bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf, - cmExecutionStatus&) override; - bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override; - - std::vector<cmListFileArgument> Args; - std::vector<cmListFileFunction> Functions; - bool IsBlocking; - bool HasRun = false; - bool ElseSeen = false; - unsigned int ScopeDepth = 0; -}; +struct cmListFileArgument; /// Starts an if block -class cmIfCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmIfCommand; } - - /** - * This overrides the default InvokeInitialPass implementation. - * It records the arguments before expansion. - */ - bool InvokeInitialPass(const std::vector<cmListFileArgument>& args, - cmExecutionStatus&) override; - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const&, - cmExecutionStatus&) override - { - return false; - } - - // Filter the given variable definition based on policy CMP0054. - static const char* GetDefinitionIfUnquoted( - const cmMakefile* mf, cmExpandedCommandArgument const& argument); -}; +bool cmIfCommand(std::vector<cmListFileArgument> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx index 0d608bb..14264f4 100644 --- a/Source/cmIncludeCommand.cxx +++ b/Source/cmIncludeCommand.cxx @@ -4,21 +4,21 @@ #include <sstream> +#include "cmExecutionStatus.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmExecutionStatus; - // cmIncludeCommand -bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmIncludeCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty() || args.size() > 4) { - this->SetError("called with wrong number of arguments. " - "include() only takes one file."); + status.SetError("called with wrong number of arguments. " + "include() only takes one file."); return false; } bool optional = false; @@ -29,20 +29,20 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args, for (unsigned int i = 1; i < args.size(); i++) { if (args[i] == "OPTIONAL") { if (optional) { - this->SetError("called with invalid arguments: OPTIONAL used twice"); + status.SetError("called with invalid arguments: OPTIONAL used twice"); return false; } optional = true; } else if (args[i] == "RESULT_VARIABLE") { if (!resultVarName.empty()) { - this->SetError("called with invalid arguments: " - "only one result variable allowed"); + status.SetError("called with invalid arguments: " + "only one result variable allowed"); return false; } if (++i < args.size()) { resultVarName = args[i]; } else { - this->SetError("called with no value for RESULT_VARIABLE."); + status.SetError("called with no value for RESULT_VARIABLE."); return false; } } else if (args[i] == "NO_POLICY_SCOPE") { @@ -50,39 +50,39 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args, } else if (i > 1) // compat.: in previous cmake versions the second // parameter was ignored if it wasn't "OPTIONAL" { - std::string errorText = "called with invalid argument: "; - errorText += args[i]; - this->SetError(errorText); + std::string errorText = + cmStrCat("called with invalid argument: ", args[i]); + status.SetError(errorText); return false; } } if (fname.empty()) { - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, - "include() given empty file name (ignored)."); + status.GetMakefile().IssueMessage( + MessageType::AUTHOR_WARNING, + "include() given empty file name (ignored)."); return true; } if (!cmSystemTools::FileIsFullPath(fname)) { // Not a path. Maybe module. - std::string module = fname; - module += ".cmake"; - std::string mfile = this->Makefile->GetModulesFile(module); + std::string module = cmStrCat(fname, ".cmake"); + std::string mfile = status.GetMakefile().GetModulesFile(module); if (!mfile.empty()) { fname = mfile; } } std::string fname_abs = cmSystemTools::CollapseFullPath( - fname, this->Makefile->GetCurrentSourceDirectory()); + fname, status.GetMakefile().GetCurrentSourceDirectory()); - cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); + cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator(); if (gg->IsExportedTargetsFile(fname_abs)) { const char* modal = nullptr; std::ostringstream e; MessageType messageType = MessageType::AUTHOR_WARNING; - switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0024)) { + switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0024)) { case cmPolicies::WARN: e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0024) << "\n"; modal = "should"; @@ -102,7 +102,7 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args, << " not be used as the argument to the " "include() command. Use ALIAS targets instead to refer to targets " "by alternative names.\n"; - this->Makefile->IssueMessage(messageType, e.str()); + status.GetMakefile().IssueMessage(messageType, e.str()); if (messageType == MessageType::FATAL_ERROR) { return false; } @@ -112,27 +112,28 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args, } std::string listFile = cmSystemTools::CollapseFullPath( - fname, this->Makefile->GetCurrentSourceDirectory()); + fname, status.GetMakefile().GetCurrentSourceDirectory()); if (optional && !cmSystemTools::FileExists(listFile)) { if (!resultVarName.empty()) { - this->Makefile->AddDefinition(resultVarName, "NOTFOUND"); + status.GetMakefile().AddDefinition(resultVarName, "NOTFOUND"); } return true; } - bool readit = this->Makefile->ReadDependentFile(listFile, noPolicyScope); + bool readit = + status.GetMakefile().ReadDependentFile(listFile, noPolicyScope); // add the location of the included file if a result variable was given if (!resultVarName.empty()) { - this->Makefile->AddDefinition(resultVarName, - readit ? fname_abs.c_str() : "NOTFOUND"); + status.GetMakefile().AddDefinition( + resultVarName, readit ? fname_abs.c_str() : "NOTFOUND"); } if (!optional && !readit && !cmSystemTools::GetFatalErrorOccured()) { - std::string m = "could not find load file:\n" - " "; - m += fname; - this->SetError(m); + std::string m = cmStrCat("could not find load file:\n" + " ", + fname); + status.SetError(m); return false; } return true; diff --git a/Source/cmIncludeCommand.h b/Source/cmIncludeCommand.h index 3b843b2..b0dd779 100644 --- a/Source/cmIncludeCommand.h +++ b/Source/cmIncludeCommand.h @@ -8,30 +8,15 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmIncludeCommand +/** * \brief cmIncludeCommand defines a list of distant * files that can be "included" in the current list file. * In almost every sense, this is identical to a C/C++ * #include command. Arguments are first expended as usual. */ -class cmIncludeCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmIncludeCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmIncludeCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx index 62e2abd..876bd95 100644 --- a/Source/cmIncludeDirectoryCommand.cxx +++ b/Source/cmIncludeDirectoryCommand.cxx @@ -9,6 +9,7 @@ #include "cmAlgorithms.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmExecutionStatus; @@ -116,14 +117,13 @@ void cmIncludeDirectoryCommand::NormalizeInclude(std::string& inc) return; } - if (!cmSystemTools::IsOff(inc)) { + if (!cmIsOff(inc)) { cmSystemTools::ConvertToUnixSlashes(inc); if (!cmSystemTools::FileIsFullPath(inc)) { if (!cmGeneratorExpression::StartsWithGeneratorExpression(inc)) { - std::string tmp = this->Makefile->GetCurrentSourceDirectory(); - tmp += "/"; - tmp += inc; + std::string tmp = + cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', inc); inc = tmp; } } diff --git a/Source/cmIncludeDirectoryCommand.h b/Source/cmIncludeDirectoryCommand.h index 01d98db..4df94eb 100644 --- a/Source/cmIncludeDirectoryCommand.h +++ b/Source/cmIncludeDirectoryCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -24,7 +26,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmIncludeDirectoryCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmIncludeDirectoryCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmIncludeExternalMSProjectCommand.h b/Source/cmIncludeExternalMSProjectCommand.h index 945acdc..9f76576 100644 --- a/Source/cmIncludeExternalMSProjectCommand.h +++ b/Source/cmIncludeExternalMSProjectCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -25,7 +27,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmIncludeExternalMSProjectCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmIncludeExternalMSProjectCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmIncludeGuardCommand.cxx b/Source/cmIncludeGuardCommand.cxx index 505b07c..ccb4496 100644 --- a/Source/cmIncludeGuardCommand.cxx +++ b/Source/cmIncludeGuardCommand.cxx @@ -21,7 +21,7 @@ enum IncludeGuardScope std::string GetIncludeGuardVariableName(std::string const& filePath) { std::string result = "__INCGUARD_"; -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP result += cmSystemTools::ComputeStringMD5(filePath); #else result += cmSystemTools::MakeCidentifier(filePath); @@ -50,11 +50,11 @@ bool CheckIncludeGuardIsSet(cmMakefile* mf, std::string const& includeGuardVar) } // anonymous namespace // cmIncludeGuardCommand -bool cmIncludeGuardCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) +bool cmIncludeGuardCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() > 1) { - this->SetError( + status.SetError( "given an invalid number of arguments. The command takes at " "most 1 argument."); return false; @@ -69,15 +69,15 @@ bool cmIncludeGuardCommand::InitialPass(std::vector<std::string> const& args, } else if (arg == "GLOBAL") { scope = GLOBAL; } else { - this->SetError("given an invalid scope: " + arg); + status.SetError("given an invalid scope: " + arg); return false; } } std::string includeGuardVar = GetIncludeGuardVariableName( - this->Makefile->GetDefinition("CMAKE_CURRENT_LIST_FILE")); + status.GetMakefile().GetDefinition("CMAKE_CURRENT_LIST_FILE")); - cmMakefile* const mf = this->Makefile; + cmMakefile* const mf = &status.GetMakefile(); switch (scope) { case VARIABLE: @@ -85,7 +85,7 @@ bool cmIncludeGuardCommand::InitialPass(std::vector<std::string> const& args, status.SetReturnInvoked(); return true; } - mf->AddDefinition(includeGuardVar, true); + mf->AddDefinitionBool(includeGuardVar, true); break; case DIRECTORY: if (CheckIncludeGuardIsSet(mf, includeGuardVar)) { diff --git a/Source/cmIncludeGuardCommand.h b/Source/cmIncludeGuardCommand.h index eaad9b8..b86b760 100644 --- a/Source/cmIncludeGuardCommand.h +++ b/Source/cmIncludeGuardCommand.h @@ -8,30 +8,15 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmIncludeGuardCommand +/** * \brief cmIncludeGuardCommand identical to C++ #pragma_once command * Can work in 3 modes: GLOBAL (works on global properties), * DIRECTORY(use directory property), VARIABLE(unnamed overload without * arguments) define an ordinary variable to be used as include guard checker */ -class cmIncludeGuardCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmIncludeGuardCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmIncludeGuardCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmIncludeRegularExpressionCommand.h b/Source/cmIncludeRegularExpressionCommand.h index 8da991d..1723c8b 100644 --- a/Source/cmIncludeRegularExpressionCommand.h +++ b/Source/cmIncludeRegularExpressionCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -24,7 +26,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmIncludeRegularExpressionCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmIncludeRegularExpressionCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index c9e6923..9a78c49 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -9,7 +9,6 @@ #include <stddef.h> #include <utility> -#include "cmAlgorithms.h" #include "cmArgumentParser.h" #include "cmExportSet.h" #include "cmExportSetMap.h" @@ -27,6 +26,7 @@ #include "cmMessageType.h" #include "cmPolicies.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetExport.h" @@ -137,8 +137,7 @@ bool cmInstallCommand::InitialPass(std::vector<std::string> const& args, } // Unknown mode. - std::string e = "called with unknown mode "; - e += args[0]; + std::string e = cmStrCat("called with unknown mode ", args[0]); this->SetError(e); return false; } @@ -188,9 +187,8 @@ bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args) doing_script = false; std::string script = arg; if (!cmSystemTools::FileIsFullPath(script)) { - script = this->Makefile->GetCurrentSourceDirectory(); - script += "/"; - script += arg; + script = + cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', arg); } if (cmSystemTools::FileIsDirectory(script)) { this->SetError("given a directory as value of SCRIPT argument."); @@ -370,10 +368,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) !objectArgs.GetType().empty() || !frameworkArgs.GetType().empty() || !bundleArgs.GetType().empty() || !privateHeaderArgs.GetType().empty() || !publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty()) { - std::ostringstream e; - e << "TARGETS given TYPE option. The TYPE option may only be specified in " - " install(FILES) and install(DIRECTORIES)."; - this->SetError(e.str()); + this->SetError( + "TARGETS given TYPE option. The TYPE option may only be specified in " + " install(FILES) and install(DIRECTORIES)."); return false; } @@ -391,10 +388,6 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) return true; } - // Check whether this is a DLL platform. - bool dll_platform = - !this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty(); - for (std::string const& tgt : targetList) { if (this->Makefile->IsAlias(tgt)) { @@ -474,7 +467,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // Shared libraries are handled differently on DLL and non-DLL // platforms. All windows platforms are DLL platforms including // cygwin. Currently no other platform is a DLL platform. - if (dll_platform) { + if (target.IsDLLPlatform()) { // When in namelink only mode skip all libraries on Windows. if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) { continue; @@ -643,7 +636,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // On DLL platforms an executable may also have an import // library. Install it to the archive destination if it // exists. - if (dll_platform && !archiveArgs.GetDestination().empty() && + if ((target.IsDLLPlatform() || target.IsAIX()) && + !archiveArgs.GetDestination().empty() && target.IsExecutableWithExports()) { // The import library uses the ARCHIVE properties. archiveGenerator = CreateInstallTargetGenerator( @@ -675,8 +669,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) if (createInstallGeneratorsForTargetFileSets && !namelinkOnly) { const char* files = target.GetProperty("PRIVATE_HEADER"); if ((files) && (*files)) { - std::vector<std::string> relFiles; - cmSystemTools::ExpandListArgument(files, relFiles); + std::vector<std::string> relFiles = cmExpandedList(files); std::vector<std::string> absFiles; if (!this->MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles)) { return false; @@ -690,8 +683,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) files = target.GetProperty("PUBLIC_HEADER"); if ((files) && (*files)) { - std::vector<std::string> relFiles; - cmSystemTools::ExpandListArgument(files, relFiles); + std::vector<std::string> relFiles = cmExpandedList(files); std::vector<std::string> absFiles; if (!this->MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles)) { return false; @@ -705,8 +697,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) files = target.GetProperty("RESOURCE"); if ((files) && (*files)) { - std::vector<std::string> relFiles; - cmSystemTools::ExpandListArgument(files, relFiles); + std::vector<std::string> relFiles = cmExpandedList(files); std::vector<std::string> absFiles; if (!this->MakeFilesFullPath("RESOURCE", relFiles, absFiles)) { return false; @@ -1126,9 +1117,8 @@ bool cmInstallCommand::HandleDirectoryMode( std::string dir = args[i]; std::string::size_type gpos = cmGeneratorExpression::Find(dir); if (gpos != 0 && !cmSystemTools::FileIsFullPath(dir)) { - dir = this->Makefile->GetCurrentSourceDirectory(); - dir += "/"; - dir += args[i]; + dir = + cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', args[i]); } // Make sure the name is a directory. @@ -1271,7 +1261,7 @@ bool cmInstallCommand::HandleDirectoryMode( bool cmInstallCommand::HandleExportAndroidMKMode( std::vector<std::string> const& args) { -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP // This is the EXPORT mode. cmInstallCommandArguments ica(this->DefaultComponentName); @@ -1427,8 +1417,7 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) // Construct the file name. if (fname.empty()) { - fname = exp; - fname += ".cmake"; + fname = cmStrCat(exp, ".cmake"); if (fname.find_first_of(":/\\") != std::string::npos) { std::ostringstream e; @@ -1485,9 +1474,8 @@ bool cmInstallCommand::MakeFilesFullPath( std::string file = relFile; std::string::size_type gpos = cmGeneratorExpression::Find(file); if (gpos != 0 && !cmSystemTools::FileIsFullPath(file)) { - file = this->Makefile->GetCurrentSourceDirectory(); - file += "/"; - file += relFile; + file = + cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', relFile); } // Make sure the file is not a directory. diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h index 202c438..28bf443 100644 --- a/Source/cmInstallCommand.h +++ b/Source/cmInstallCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -25,7 +27,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmInstallCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmInstallCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx index 14288f6..1d8210c 100644 --- a/Source/cmInstallDirectoryGenerator.cxx +++ b/Source/cmInstallDirectoryGenerator.cxx @@ -6,9 +6,10 @@ #include "cmInstallType.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" -#include <memory> // IWYU pragma: keep +#include <memory> cmInstallDirectoryGenerator::cmInstallDirectoryGenerator( std::vector<std::string> const& dirs, const char* dest, @@ -66,15 +67,14 @@ void cmInstallDirectoryGenerator::GenerateScriptForConfig( cmGeneratorExpression ge; for (std::string const& d : this->Directories) { std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(d); - cmSystemTools::ExpandListArgument( - cge->Evaluate(this->LocalGenerator, config), dirs); + cmExpandList(cge->Evaluate(this->LocalGenerator, config), dirs); } // Make sure all dirs have absolute paths. cmMakefile const& mf = *this->LocalGenerator->GetMakefile(); for (std::string& d : dirs) { if (!cmSystemTools::FileIsFullPath(d)) { - d = mf.GetCurrentSourceDirectory() + "/" + d; + d = cmStrCat(mf.GetCurrentSourceDirectory(), "/", d); } } diff --git a/Source/cmInstallExportAndroidMKGenerator.cxx b/Source/cmInstallExportAndroidMKGenerator.cxx index 55d3685..e8de029 100644 --- a/Source/cmInstallExportAndroidMKGenerator.cxx +++ b/Source/cmInstallExportAndroidMKGenerator.cxx @@ -53,9 +53,7 @@ void cmInstallExportAndroidMKGenerator::GenerateScript(std::ostream& os) cmSystemTools::MakeDirectory(this->TempDir.c_str()); // Construct a temporary location for the file. - this->MainImportFile = this->TempDir; - this->MainImportFile += "/"; - this->MainImportFile += this->FileName; + this->MainImportFile = cmStrCat(this->TempDir, '/', this->FileName); // Generate the import file for this export set. this->EFGen->SetExportFile(this->MainImportFile.c_str()); @@ -103,11 +101,10 @@ void cmInstallExportAndroidMKGenerator::GenerateScriptActions( std::ostream& os, Indent const& indent) { // Remove old per-configuration export files if the main changes. - std::string installedDir = "$ENV{DESTDIR}"; - installedDir += this->ConvertToAbsoluteDestination(this->Destination); - installedDir += "/"; - std::string installedFile = installedDir; - installedFile += this->FileName; + std::string installedDir = + cmStrCat("$ENV{DESTDIR}", + this->ConvertToAbsoluteDestination(this->Destination), '/'); + std::string installedFile = cmStrCat(installedDir, this->FileName); os << indent << "if(EXISTS \"" << installedFile << "\")\n"; Indent indentN = indent.Next(); Indent indentNN = indentN.Next(); diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index f5bedab..0b3617b 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -7,13 +7,14 @@ #include <sstream> #include <utility> -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP # include "cmExportInstallAndroidMKGenerator.h" #endif #include "cmExportInstallFileGenerator.h" #include "cmExportSet.h" #include "cmInstallType.h" #include "cmLocalGenerator.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmInstallExportGenerator::cmInstallExportGenerator( @@ -31,7 +32,7 @@ cmInstallExportGenerator::cmInstallExportGenerator( , LocalGenerator(nullptr) { if (android) { -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP this->EFGen = new cmExportInstallAndroidMKGenerator(this); #endif } else { @@ -56,9 +57,8 @@ void cmInstallExportGenerator::ComputeTempDir() { // Choose a temporary directory in which to generate the import // files to be installed. - this->TempDir = this->LocalGenerator->GetCurrentBinaryDirectory(); - this->TempDir += "/CMakeFiles"; - this->TempDir += "/Export"; + this->TempDir = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), + "/CMakeFiles/Export"); if (this->Destination.empty()) { return; } @@ -136,9 +136,7 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os) cmSystemTools::MakeDirectory(this->TempDir); // Construct a temporary location for the file. - this->MainImportFile = this->TempDir; - this->MainImportFile += "/"; - this->MainImportFile += this->FileName; + this->MainImportFile = cmStrCat(this->TempDir, '/', this->FileName); // Generate the import file for this export set. this->EFGen->SetExportFile(this->MainImportFile.c_str()); @@ -186,11 +184,10 @@ void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os, Indent indent) { // Remove old per-configuration export files if the main changes. - std::string installedDir = "$ENV{DESTDIR}"; - installedDir += this->ConvertToAbsoluteDestination(this->Destination); - installedDir += "/"; - std::string installedFile = installedDir; - installedFile += this->FileName; + std::string installedDir = + cmStrCat("$ENV{DESTDIR}", + this->ConvertToAbsoluteDestination(this->Destination), '/'); + std::string installedFile = cmStrCat(installedDir, this->FileName); os << indent << "if(EXISTS \"" << installedFile << "\")\n"; Indent indentN = indent.Next(); Indent indentNN = indentN.Next(); @@ -218,3 +215,8 @@ void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os, false, this->FilePermissions.c_str(), nullptr, nullptr, nullptr, indent); } + +std::string cmInstallExportGenerator::GetDestinationFile() const +{ + return this->Destination + '/' + this->FileName; +} diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h index c4d252c..e680066 100644 --- a/Source/cmInstallExportGenerator.h +++ b/Source/cmInstallExportGenerator.h @@ -41,6 +41,7 @@ public: const std::string& GetNamespace() const { return this->Namespace; } std::string const& GetDestination() const { return this->Destination; } + std::string GetDestinationFile() const; protected: void GenerateScript(std::ostream& os) override; diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx index efbcb67..11687a8 100644 --- a/Source/cmInstallFilesCommand.cxx +++ b/Source/cmInstallFilesCommand.cxx @@ -2,18 +2,24 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallFilesCommand.h" -#include "cmAlgorithms.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmInstallFilesGenerator.h" #include "cmInstallGenerator.h" #include "cmMakefile.h" #include "cmRange.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmExecutionStatus; -// cmExecutableCommand +static std::string FindInstallSource(cmMakefile& makefile, const char* name); +static void CreateInstallGenerator(cmMakefile& makefile, + std::string const& dest, + std::vector<std::string> const& files); +static void FinalAction(cmMakefile& makefile, std::string const& dest, + std::vector<std::string> const& args); + bool cmInstallFilesCommand::InitialPass(std::vector<std::string> const& args, cmExecutionStatus&) { @@ -25,18 +31,20 @@ bool cmInstallFilesCommand::InitialPass(std::vector<std::string> const& args, // Enable the install target. this->Makefile->GetGlobalGenerator()->EnableInstallTarget(); - this->Destination = args[0]; + std::string const& dest = args[0]; if ((args.size() > 1) && (args[1] == "FILES")) { - this->IsFilesForm = true; + std::vector<std::string> files; for (std::string const& arg : cmMakeRange(args).advance(2)) { // Find the source location for each file listed. - this->Files.push_back(this->FindInstallSource(arg.c_str())); + files.push_back(FindInstallSource(*this->Makefile, arg.c_str())); } - this->CreateInstallGenerator(); + CreateInstallGenerator(*this->Makefile, dest, files); } else { - this->IsFilesForm = false; - cmAppend(this->FinalArgs, args.begin() + 1, args.end()); + std::vector<std::string> finalArgs(args.begin() + 1, args.end()); + this->Makefile->AddFinalAction([dest, finalArgs](cmMakefile& makefile) { + FinalAction(makefile, dest, finalArgs); + }); } this->Makefile->GetGlobalGenerator()->AddInstallComponent( @@ -45,23 +53,20 @@ bool cmInstallFilesCommand::InitialPass(std::vector<std::string> const& args, return true; } -void cmInstallFilesCommand::FinalPass() +static void FinalAction(cmMakefile& makefile, std::string const& dest, + std::vector<std::string> const& args) { - // No final pass for "FILES" form of arguments. - if (this->IsFilesForm) { - return; - } - std::string testf; - std::string const& ext = this->FinalArgs[0]; + std::string const& ext = args[0]; + std::vector<std::string> installFiles; // two different options - if (this->FinalArgs.size() > 1) { + if (args.size() > 1) { // now put the files into the list - std::vector<std::string>::iterator s = this->FinalArgs.begin(); + std::vector<std::string>::const_iterator s = args.begin(); ++s; // for each argument, get the files - for (; s != this->FinalArgs.end(); ++s) { + for (; s != args.end(); ++s) { // replace any variables std::string const& temps = *s; if (!cmSystemTools::GetFilenamePath(temps).empty()) { @@ -72,30 +77,31 @@ void cmInstallFilesCommand::FinalPass() } // add to the result - this->Files.push_back(this->FindInstallSource(testf.c_str())); + installFiles.push_back(FindInstallSource(makefile, testf.c_str())); } } else // reg exp list { std::vector<std::string> files; - std::string const& regex = this->FinalArgs[0]; - cmSystemTools::Glob(this->Makefile->GetCurrentSourceDirectory(), regex, - files); + std::string const& regex = args[0]; + cmSystemTools::Glob(makefile.GetCurrentSourceDirectory(), regex, files); std::vector<std::string>::iterator s = files.begin(); // for each argument, get the files for (; s != files.end(); ++s) { - this->Files.push_back(this->FindInstallSource(s->c_str())); + installFiles.push_back(FindInstallSource(makefile, s->c_str())); } } - this->CreateInstallGenerator(); + CreateInstallGenerator(makefile, dest, installFiles); } -void cmInstallFilesCommand::CreateInstallGenerator() const +static void CreateInstallGenerator(cmMakefile& makefile, + std::string const& dest, + std::vector<std::string> const& files) { // Construct the destination. This command always installs under // the prefix. We skip the leading slash given by the user. - std::string destination = this->Destination.substr(1); + std::string destination = dest.substr(1); cmSystemTools::ConvertToUnixSlashes(destination); if (destination.empty()) { destination = "."; @@ -106,12 +112,12 @@ void cmInstallFilesCommand::CreateInstallGenerator() const const char* no_rename = ""; bool no_exclude_from_all = false; std::string no_component = - this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"); + makefile.GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"); std::vector<std::string> no_configurations; cmInstallGenerator::MessageLevel message = - cmInstallGenerator::SelectMessageLevel(this->Makefile); - this->Makefile->AddInstallGenerator(new cmInstallFilesGenerator( - this->Files, destination.c_str(), false, no_permissions, no_configurations, + cmInstallGenerator::SelectMessageLevel(&makefile); + makefile.AddInstallGenerator(new cmInstallFilesGenerator( + files, destination.c_str(), false, no_permissions, no_configurations, no_component.c_str(), message, no_exclude_from_all, no_rename)); } @@ -121,7 +127,7 @@ void cmInstallFilesCommand::CreateInstallGenerator() const * present in the build tree. If a full path is given, it is just * returned. */ -std::string cmInstallFilesCommand::FindInstallSource(const char* name) const +static std::string FindInstallSource(cmMakefile& makefile, const char* name) { if (cmSystemTools::FileIsFullPath(name) || cmGeneratorExpression::Find(name) == 0) { @@ -130,12 +136,8 @@ std::string cmInstallFilesCommand::FindInstallSource(const char* name) const } // This is a relative path. - std::string tb = this->Makefile->GetCurrentBinaryDirectory(); - tb += "/"; - tb += name; - std::string ts = this->Makefile->GetCurrentSourceDirectory(); - ts += "/"; - ts += name; + std::string tb = cmStrCat(makefile.GetCurrentBinaryDirectory(), '/', name); + std::string ts = cmStrCat(makefile.GetCurrentSourceDirectory(), '/', name); if (cmSystemTools::FileExists(tb)) { // The file exists in the binary tree. Use it. diff --git a/Source/cmInstallFilesCommand.h b/Source/cmInstallFilesCommand.h index a52f45e..f9b84fd 100644 --- a/Source/cmInstallFilesCommand.h +++ b/Source/cmInstallFilesCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -24,7 +26,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmInstallFilesCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmInstallFilesCommand>(); + } /** * This is called when the command is first encountered in @@ -32,25 +37,6 @@ public: */ bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; - - /** - * This is called at the end after all the information - * specified by the command is accumulated. Most commands do - * not implement this method. At this point, reading and - * writing to the cache can be done. - */ - void FinalPass() override; - bool HasFinalPass() const override { return !this->IsFilesForm; } - -protected: - void CreateInstallGenerator() const; - std::string FindInstallSource(const char* name) const; - -private: - std::vector<std::string> FinalArgs; - bool IsFilesForm = false; - std::string Destination; - std::vector<std::string> Files; }; #endif diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx index 2ed9f73..c4048d4 100644 --- a/Source/cmInstallFilesGenerator.cxx +++ b/Source/cmInstallFilesGenerator.cxx @@ -4,9 +4,9 @@ #include "cmGeneratorExpression.h" #include "cmInstallType.h" -#include "cmSystemTools.h" +#include "cmStringAlgorithms.h" -#include <memory> // IWYU pragma: keep +#include <memory> class cmLocalGenerator; @@ -85,8 +85,7 @@ void cmInstallFilesGenerator::GenerateScriptForConfig( cmGeneratorExpression ge; for (std::string const& f : this->Files) { std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(f); - cmSystemTools::ExpandListArgument( - cge->Evaluate(this->LocalGenerator, config), files); + cmExpandList(cge->Evaluate(this->LocalGenerator, config), files); } this->AddFilesInstallRule(os, config, indent, files); } diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx index a58f875..3eca0e0 100644 --- a/Source/cmInstallProgramsCommand.cxx +++ b/Source/cmInstallProgramsCommand.cxx @@ -2,16 +2,20 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallProgramsCommand.h" -#include "cmAlgorithms.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmInstallFilesGenerator.h" #include "cmInstallGenerator.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmExecutionStatus; +static void FinalAction(cmMakefile& makefile, std::string const& dest, + std::vector<std::string> const& args); +static std::string FindInstallSource(cmMakefile& makefile, const char* name); + // cmExecutableCommand bool cmInstallProgramsCommand::InitialPass( std::vector<std::string> const& args, cmExecutionStatus&) @@ -24,51 +28,55 @@ bool cmInstallProgramsCommand::InitialPass( // Enable the install target. this->Makefile->GetGlobalGenerator()->EnableInstallTarget(); - this->Destination = args[0]; - - cmAppend(this->FinalArgs, args.begin() + 1, args.end()); - this->Makefile->GetGlobalGenerator()->AddInstallComponent( this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME")); + std::string const& dest = args[0]; + std::vector<std::string> const finalArgs(args.begin() + 1, args.end()); + this->Makefile->AddFinalAction([dest, finalArgs](cmMakefile& makefile) { + FinalAction(makefile, dest, finalArgs); + }); return true; } -void cmInstallProgramsCommand::FinalPass() +static void FinalAction(cmMakefile& makefile, std::string const& dest, + std::vector<std::string> const& args) { bool files_mode = false; - if (!this->FinalArgs.empty() && this->FinalArgs[0] == "FILES") { + if (!args.empty() && args[0] == "FILES") { files_mode = true; } + std::vector<std::string> files; + // two different options - if (this->FinalArgs.size() > 1 || files_mode) { + if (args.size() > 1 || files_mode) { // for each argument, get the programs - std::vector<std::string>::iterator s = this->FinalArgs.begin(); + std::vector<std::string>::const_iterator s = args.begin(); if (files_mode) { // Skip the FILES argument in files mode. ++s; } - for (; s != this->FinalArgs.end(); ++s) { + for (; s != args.end(); ++s) { // add to the result - this->Files.push_back(this->FindInstallSource(s->c_str())); + files.push_back(FindInstallSource(makefile, s->c_str())); } } else // reg exp list { std::vector<std::string> programs; - cmSystemTools::Glob(this->Makefile->GetCurrentSourceDirectory(), - this->FinalArgs[0], programs); + cmSystemTools::Glob(makefile.GetCurrentSourceDirectory(), args[0], + programs); std::vector<std::string>::iterator s = programs.begin(); // for each argument, get the programs for (; s != programs.end(); ++s) { - this->Files.push_back(this->FindInstallSource(s->c_str())); + files.push_back(FindInstallSource(makefile, s->c_str())); } } // Construct the destination. This command always installs under // the prefix. We skip the leading slash given by the user. - std::string destination = this->Destination.substr(1); + std::string destination = dest.substr(1); cmSystemTools::ConvertToUnixSlashes(destination); if (destination.empty()) { destination = "."; @@ -79,12 +87,12 @@ void cmInstallProgramsCommand::FinalPass() const char* no_rename = ""; bool no_exclude_from_all = false; std::string no_component = - this->Makefile->GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"); + makefile.GetSafeDefinition("CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"); std::vector<std::string> no_configurations; cmInstallGenerator::MessageLevel message = - cmInstallGenerator::SelectMessageLevel(this->Makefile); - this->Makefile->AddInstallGenerator(new cmInstallFilesGenerator( - this->Files, destination.c_str(), true, no_permissions, no_configurations, + cmInstallGenerator::SelectMessageLevel(&makefile); + makefile.AddInstallGenerator(new cmInstallFilesGenerator( + files, destination.c_str(), true, no_permissions, no_configurations, no_component.c_str(), message, no_exclude_from_all, no_rename)); } @@ -94,7 +102,7 @@ void cmInstallProgramsCommand::FinalPass() * present in the build tree. If a full path is given, it is just * returned. */ -std::string cmInstallProgramsCommand::FindInstallSource(const char* name) const +static std::string FindInstallSource(cmMakefile& makefile, const char* name) { if (cmSystemTools::FileIsFullPath(name) || cmGeneratorExpression::Find(name) == 0) { @@ -103,12 +111,8 @@ std::string cmInstallProgramsCommand::FindInstallSource(const char* name) const } // This is a relative path. - std::string tb = this->Makefile->GetCurrentBinaryDirectory(); - tb += "/"; - tb += name; - std::string ts = this->Makefile->GetCurrentSourceDirectory(); - ts += "/"; - ts += name; + std::string tb = cmStrCat(makefile.GetCurrentBinaryDirectory(), '/', name); + std::string ts = cmStrCat(makefile.GetCurrentSourceDirectory(), '/', name); if (cmSystemTools::FileExists(tb)) { // The file exists in the binary tree. Use it. diff --git a/Source/cmInstallProgramsCommand.h b/Source/cmInstallProgramsCommand.h index 5c705eb..ccd621d 100644 --- a/Source/cmInstallProgramsCommand.h +++ b/Source/cmInstallProgramsCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -24,7 +26,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmInstallProgramsCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmInstallProgramsCommand>(); + } /** * This is called when the command is first encountered in @@ -32,24 +37,6 @@ public: */ bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; - - /** - * This is called at the end after all the information - * specified by the command is accumulated. Most commands do - * not implement this method. At this point, reading and - * writing to the cache can be done. - */ - void FinalPass() override; - - bool HasFinalPass() const override { return true; } - -protected: - std::string FindInstallSource(const char* name) const; - -private: - std::vector<std::string> FinalArgs; - std::string Destination; - std::vector<std::string> Files; }; #endif diff --git a/Source/cmInstallScriptGenerator.cxx b/Source/cmInstallScriptGenerator.cxx index 5832d27..b7b7817 100644 --- a/Source/cmInstallScriptGenerator.cxx +++ b/Source/cmInstallScriptGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallScriptGenerator.h" +#include <memory> #include <ostream> #include <vector> diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 7c5a55b..7bbef35 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -4,6 +4,7 @@ #include <assert.h> #include <map> +#include <memory> #include <set> #include <sstream> #include <utility> @@ -16,7 +17,10 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmOutputConverter.h" +#include "cmPolicies.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmake.h" @@ -83,20 +87,18 @@ void cmInstallTargetGenerator::GenerateScriptForConfig( std::string fromDirConfig; if (this->Target->NeedRelinkBeforeInstall(config)) { fromDirConfig = - this->Target->GetLocalGenerator()->GetCurrentBinaryDirectory(); - fromDirConfig += "/CMakeFiles"; - fromDirConfig += "/CMakeRelink.dir/"; + cmStrCat(this->Target->GetLocalGenerator()->GetCurrentBinaryDirectory(), + "/CMakeFiles/CMakeRelink.dir/"); } else { cmStateEnums::ArtifactType artifact = this->ImportLibrary ? cmStateEnums::ImportLibraryArtifact : cmStateEnums::RuntimeBinaryArtifact; - fromDirConfig = this->Target->GetDirectory(config, artifact); - fromDirConfig += "/"; + fromDirConfig = + cmStrCat(this->Target->GetDirectory(config, artifact), '/'); } - std::string toDir = - this->ConvertToAbsoluteDestination(this->GetDestination(config)); - toDir += "/"; + std::string toDir = cmStrCat( + this->ConvertToAbsoluteDestination(this->GetDestination(config)), '/'); // Compute the list of files to install for this target. std::vector<std::string> filesFrom; @@ -366,7 +368,7 @@ void cmInstallTargetGenerator::GetInstallObjectNames( { this->Target->GetTargetObjectNames(config, objects); for (std::string& o : objects) { - o = computeInstallObjectDir(this->Target, config) + "/" + o; + o = cmStrCat(computeInstallObjectDir(this->Target, config), "/", o); } } @@ -590,8 +592,8 @@ void cmInstallTargetGenerator::AddInstallNamePatchRule( // on the installed file. if (for_build != for_install) { // Prepare to refer to the install-tree install_name. - new_id = for_install; - new_id += this->GetInstallFilename(this->Target, config, NameSO); + new_id = cmStrCat( + for_install, this->GetInstallFilename(this->Target, config, NameSO)); } } @@ -632,17 +634,34 @@ void cmInstallTargetGenerator::AddRPathCheckRule( return; } - // Get the install RPATH from the link information. - std::string newRpath = cli->GetChrpathString(); - // Write a rule to remove the installed file if its rpath is not the // new rpath. This is needed for existing build/install trees when // the installed rpath changes but the file is not rebuilt. - /* clang-format off */ os << indent << "file(RPATH_CHECK\n" - << indent << " FILE \"" << toDestDirPath << "\"\n" - << indent << " RPATH \"" << newRpath << "\")\n"; - /* clang-format on */ + << indent << " FILE \"" << toDestDirPath << "\"\n"; + + // CMP0095: ``RPATH`` entries are properly escaped in the intermediary + // CMake install script. + switch (this->Target->GetPolicyStatusCMP0095()) { + case cmPolicies::WARN: + // No author warning needed here, we warn later in + // cmInstallTargetGenerator::AddChrpathPatchRule(). + CM_FALLTHROUGH; + case cmPolicies::OLD: { + // Get the install RPATH from the link information. + std::string newRpath = cli->GetChrpathString(); + os << indent << " RPATH \"" << newRpath << "\")\n"; + break; + } + default: { + // Get the install RPATH from the link information and + // escape any CMake syntax in the install RPATH. + std::string escapedNewRpath = + cmOutputConverter::EscapeForCMake(cli->GetChrpathString()); + os << indent << " RPATH " << escapedNewRpath << ")\n"; + break; + } + } } void cmInstallTargetGenerator::AddChrpathPatchRule( @@ -668,7 +687,8 @@ void cmInstallTargetGenerator::AddChrpathPatchRule( std::string installNameTool = mf->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL"); - std::vector<std::string> oldRuntimeDirs, newRuntimeDirs; + std::vector<std::string> oldRuntimeDirs; + std::vector<std::string> newRuntimeDirs; cli->GetRPath(oldRuntimeDirs, false); cli->GetRPath(newRuntimeDirs, true); @@ -731,11 +751,34 @@ void cmInstallTargetGenerator::AddChrpathPatchRule( return; } + // Escape any CMake syntax in the RPATHs. + std::string escapedOldRpath = cmOutputConverter::EscapeForCMake(oldRpath); + std::string escapedNewRpath = cmOutputConverter::EscapeForCMake(newRpath); + // Write a rule to run chrpath to set the install-tree RPATH os << indent << "file(RPATH_CHANGE\n" << indent << " FILE \"" << toDestDirPath << "\"\n" - << indent << " OLD_RPATH \"" << oldRpath << "\"\n" - << indent << " NEW_RPATH \"" << newRpath << "\")\n"; + << indent << " OLD_RPATH " << escapedOldRpath << "\n"; + + // CMP0095: ``RPATH`` entries are properly escaped in the intermediary + // CMake install script. + switch (this->Target->GetPolicyStatusCMP0095()) { + case cmPolicies::WARN: + this->IssueCMP0095Warning(newRpath); + CM_FALLTHROUGH; + case cmPolicies::OLD: + os << indent << " NEW_RPATH \"" << newRpath << "\""; + break; + default: + os << indent << " NEW_RPATH " << escapedNewRpath; + break; + } + + if (this->Target->GetPropertyAsBool("INSTALL_REMOVE_ENVIRONMENT_RPATH")) { + os << "\n" << indent << " INSTALL_REMOVE_ENVIRONMENT_RPATH)\n"; + } else { + os << indent << ")\n"; + } } } @@ -838,3 +881,26 @@ void cmInstallTargetGenerator::AddUniversalInstallRule( << "\"" << this->Target->Target->GetName() << "\" " << "\"" << toDestDirPath << "\")\n"; } + +void cmInstallTargetGenerator::IssueCMP0095Warning( + const std::string& unescapedRpath) +{ + // Reduce warning noise to cases where used RPATHs may actually be affected + // by CMP0095. This filter is meant to skip warnings in cases when + // non-curly-braces syntax (e.g. $ORIGIN) or no keyword is used which has + // worked already before CMP0095. We intend to issue a warning in all cases + // with curly-braces syntax, even if the workaround of double-escaping is in + // place, since we deprecate the need for it with CMP0095. + const bool potentially_affected(unescapedRpath.find("${") != + std::string::npos); + + if (potentially_affected) { + std::ostringstream w; + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0095) << "\n"; + w << "RPATH entries for target '" << this->Target->GetName() << "' " + << "will not be escaped in the intermediary " + << "cmake_install.cmake script."; + this->Target->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( + MessageType::AUTHOR_WARNING, w.str(), this->GetBacktrace()); + } +} diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index ed3ab52..9ccad63 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -104,6 +104,7 @@ protected: const std::string& toDestDirPath); void AddUniversalInstallRule(std::ostream& os, Indent indent, const std::string& toDestDirPath); + void IssueCMP0095Warning(const std::string& unescapedRpath); std::string TargetName; cmGeneratorTarget* Target; diff --git a/Source/cmInstallTargetsCommand.h b/Source/cmInstallTargetsCommand.h index 9950fb7..55e69ba 100644 --- a/Source/cmInstallTargetsCommand.h +++ b/Source/cmInstallTargetsCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -25,7 +27,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmInstallTargetsCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmInstallTargetsCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx index 537b4ec..1e6c385 100644 --- a/Source/cmInstalledFile.cxx +++ b/Source/cmInstalledFile.cxx @@ -5,7 +5,7 @@ #include "cmAlgorithms.h" #include "cmListFileCache.h" #include "cmMakefile.h" -#include "cmSystemTools.h" +#include "cmStringAlgorithms.h" #include <utility> @@ -97,7 +97,7 @@ bool cmInstalledFile::GetPropertyAsBool(const std::string& prop) const { std::string value; bool isSet = this->GetProperty(prop, value); - return isSet && cmSystemTools::IsOn(value); + return isSet && cmIsOn(value); } void cmInstalledFile::GetPropertyAsList(const std::string& prop, @@ -107,5 +107,5 @@ void cmInstalledFile::GetPropertyAsList(const std::string& prop, this->GetProperty(prop, value); list.clear(); - cmSystemTools::ExpandListArgument(value, list); + cmExpandList(value, list); } diff --git a/Source/cmInstalledFile.h b/Source/cmInstalledFile.h index b7d602e..eb827be 100644 --- a/Source/cmInstalledFile.h +++ b/Source/cmInstalledFile.h @@ -8,7 +8,7 @@ #include "cmGeneratorExpression.h" #include <map> -#include <memory> // IWYU pragma: keep +#include <memory> #include <string> #include <vector> diff --git a/Source/cmJsonObjects.cxx b/Source/cmJsonObjects.cxx index 636a8e1..b8eed13 100644 --- a/Source/cmJsonObjects.cxx +++ b/Source/cmJsonObjects.cxx @@ -14,13 +14,13 @@ #include "cmLinkLineComputer.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmProperty.h" #include "cmPropertyMap.h" #include "cmSourceFile.h" #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTest.h" @@ -32,6 +32,7 @@ #include <functional> #include <limits> #include <map> +#include <memory> #include <set> #include <string> #include <unordered_map> @@ -363,12 +364,12 @@ static Json::Value DumpCTestInfo(cmLocalGenerator* lg, cmTest* testInfo, // Build up the list of properties that may have been specified Json::Value properties = Json::arrayValue; - for (auto& prop : testInfo->GetProperties()) { + for (auto& prop : testInfo->GetProperties().GetList()) { Json::Value entry = Json::objectValue; entry[kKEY_KEY] = prop.first; // Remove config variables from the value too. - auto cge_value = ge.Parse(prop.second.GetValue()); + auto cge_value = ge.Parse(prop.second); const std::string& processed_value = cge_value->Evaluate(lg, config); entry[kVALUE_KEY] = processed_value; properties.append(entry); @@ -500,9 +501,9 @@ static Json::Value DumpTarget(cmGeneratorTarget* target, if (!dest.empty() && cmSystemTools::FileIsFullPath(dest)) { installPath = dest; } else { - std::string installPrefix = - target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); - installPath = installPrefix + '/' + dest; + installPath = cmStrCat( + target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"), '/', + dest); } installPaths.append(installPath); @@ -516,9 +517,11 @@ static Json::Value DumpTarget(cmGeneratorTarget* target, Json::Value artifacts = Json::arrayValue; artifacts.append( target->GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact)); - if (target->IsDLLPlatform()) { + if (target->HasImportLibrary(config)) { artifacts.append( target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact)); + } + if (target->IsDLLPlatform()) { const cmGeneratorTarget::OutputInfo* output = target->GetOutputInfo(config); if (output && !output->PdbDir.empty()) { @@ -539,19 +542,19 @@ static Json::Value DumpTarget(cmGeneratorTarget* target, lg->GetTargetFlags(&linkLineComputer, config, linkLibs, linkLanguageFlags, linkFlags, frameworkPath, linkPath, target); - linkLibs = cmSystemTools::TrimWhitespace(linkLibs); - linkFlags = cmSystemTools::TrimWhitespace(linkFlags); - linkLanguageFlags = cmSystemTools::TrimWhitespace(linkLanguageFlags); - frameworkPath = cmSystemTools::TrimWhitespace(frameworkPath); - linkPath = cmSystemTools::TrimWhitespace(linkPath); + linkLibs = cmTrimWhitespace(linkLibs); + linkFlags = cmTrimWhitespace(linkFlags); + linkLanguageFlags = cmTrimWhitespace(linkLanguageFlags); + frameworkPath = cmTrimWhitespace(frameworkPath); + linkPath = cmTrimWhitespace(linkPath); - if (!cmSystemTools::TrimWhitespace(linkLibs).empty()) { + if (!cmTrimWhitespace(linkLibs).empty()) { result[kLINK_LIBRARIES_KEY] = linkLibs; } - if (!cmSystemTools::TrimWhitespace(linkFlags).empty()) { + if (!cmTrimWhitespace(linkFlags).empty()) { result[kLINK_FLAGS_KEY] = linkFlags; } - if (!cmSystemTools::TrimWhitespace(linkLanguageFlags).empty()) { + if (!cmTrimWhitespace(linkLanguageFlags).empty()) { result[kLINK_LANGUAGE_FLAGS_KEY] = linkLanguageFlags; } if (!frameworkPath.empty()) { diff --git a/Source/cmLDConfigLDConfigTool.cxx b/Source/cmLDConfigLDConfigTool.cxx new file mode 100644 index 0000000..b68dbbd --- /dev/null +++ b/Source/cmLDConfigLDConfigTool.cxx @@ -0,0 +1,70 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmLDConfigLDConfigTool.h" +#include "cmMakefile.h" +#include "cmRuntimeDependencyArchive.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" +#include "cmUVProcessChain.h" + +#include "cmsys/RegularExpression.hxx" + +#include <istream> +#include <string> +#include <vector> + +cmLDConfigLDConfigTool::cmLDConfigLDConfigTool( + cmRuntimeDependencyArchive* archive) + : cmLDConfigTool(archive) +{ +} + +bool cmLDConfigLDConfigTool::GetLDConfigPaths(std::vector<std::string>& paths) +{ + std::string ldConfigPath = + this->Archive->GetMakefile()->GetSafeDefinition("CMAKE_LDCONFIG_COMMAND"); + if (ldConfigPath.empty()) { + ldConfigPath = cmSystemTools::FindProgram( + "ldconfig", { "/sbin", "/usr/sbin", "/usr/local/sbin" }); + if (ldConfigPath.empty()) { + this->Archive->SetError("Could not find ldconfig"); + return false; + } + } + + std::vector<std::string> ldConfigCommand = cmExpandedList(ldConfigPath); + ldConfigCommand.emplace_back("-v"); + ldConfigCommand.emplace_back("-N"); // Don't rebuild the cache. + ldConfigCommand.emplace_back("-X"); // Don't update links. + + cmUVProcessChainBuilder builder; + builder.SetBuiltinStream(cmUVProcessChainBuilder::Stream_OUTPUT) + .AddCommand(ldConfigCommand); + auto process = builder.Start(); + if (!process.Valid()) { + this->Archive->SetError("Failed to start ldconfig process"); + return false; + } + + std::string line; + static const cmsys::RegularExpression regex("^([^\t:]*):"); + while (std::getline(*process.OutputStream(), line)) { + cmsys::RegularExpressionMatch match; + if (regex.find(line.c_str(), match)) { + paths.push_back(match.match(1)); + } + } + + if (!process.Wait()) { + this->Archive->SetError("Failed to wait on ldconfig process"); + return false; + } + auto status = process.GetStatus(); + if (!status[0] || status[0]->ExitStatus != 0) { + this->Archive->SetError("Failed to run ldconfig"); + return false; + } + + return true; +} diff --git a/Source/cmLDConfigLDConfigTool.h b/Source/cmLDConfigLDConfigTool.h new file mode 100644 index 0000000..d945a9b --- /dev/null +++ b/Source/cmLDConfigLDConfigTool.h @@ -0,0 +1,22 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#ifndef cmLDConfigLDConfigTool_h +#define cmLDConfigLDConfigTool_h + +#include "cmLDConfigTool.h" + +#include <string> +#include <vector> + +class cmRuntimeDependencyArchive; + +class cmLDConfigLDConfigTool : public cmLDConfigTool +{ +public: + cmLDConfigLDConfigTool(cmRuntimeDependencyArchive* archive); + + bool GetLDConfigPaths(std::vector<std::string>& paths) override; +}; + +#endif diff --git a/Source/cmLDConfigTool.cxx b/Source/cmLDConfigTool.cxx new file mode 100644 index 0000000..8d5d563 --- /dev/null +++ b/Source/cmLDConfigTool.cxx @@ -0,0 +1,9 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmLDConfigTool.h" + +cmLDConfigTool::cmLDConfigTool(cmRuntimeDependencyArchive* archive) + : Archive(archive) +{ +} diff --git a/Source/cmLDConfigTool.h b/Source/cmLDConfigTool.h new file mode 100644 index 0000000..c816562 --- /dev/null +++ b/Source/cmLDConfigTool.h @@ -0,0 +1,24 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#ifndef cmLDConfigTool_h +#define cmLDConfigTool_h + +#include <string> +#include <vector> + +class cmRuntimeDependencyArchive; + +class cmLDConfigTool +{ +public: + cmLDConfigTool(cmRuntimeDependencyArchive* archive); + virtual ~cmLDConfigTool() = default; + + virtual bool GetLDConfigPaths(std::vector<std::string>& paths) = 0; + +protected: + cmRuntimeDependencyArchive* Archive; +}; + +#endif diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx index 7850977..57b69c8 100644 --- a/Source/cmLinkDirectoriesCommand.cxx +++ b/Source/cmLinkDirectoriesCommand.cxx @@ -4,11 +4,11 @@ #include <sstream> -#include "cmAlgorithms.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmExecutionStatus; @@ -75,9 +75,8 @@ void cmLinkDirectoriesCommand::AddLinkDir( break; } if (convertToAbsolute) { - std::string tmp = this->Makefile->GetCurrentSourceDirectory(); - tmp += "/"; - tmp += unixPath; + std::string tmp = + cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', unixPath); unixPath = tmp; } } diff --git a/Source/cmLinkDirectoriesCommand.h b/Source/cmLinkDirectoriesCommand.h index ae4fb7f..1a439de 100644 --- a/Source/cmLinkDirectoriesCommand.h +++ b/Source/cmLinkDirectoriesCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -26,7 +28,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmLinkDirectoriesCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmLinkDirectoriesCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h index 5b635b5..2d9378b 100644 --- a/Source/cmLinkItem.h +++ b/Source/cmLinkItem.h @@ -5,12 +5,12 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <algorithm> #include <map> #include <ostream> #include <string> #include <vector> +#include "cmAlgorithms.h" #include "cmListFileCache.h" #include "cmSystemTools.h" #include "cmTargetLinkLibraryType.h" @@ -58,6 +58,9 @@ struct cmLinkInterfaceLibraries { // Libraries listed in the interface. std::vector<cmLinkItem> Libraries; + + // Whether the list depends on a genex referencing the head target. + bool HadHeadSensitiveCondition = false; }; struct cmLinkInterface : public cmLinkInterfaceLibraries @@ -84,8 +87,7 @@ struct cmOptionalLinkInterface : public cmLinkInterface bool LibrariesDone = false; bool AllDone = false; bool Exists = false; - bool HadHeadSensitiveCondition = false; - const char* ExplicitLibraries = nullptr; + bool Explicit = false; }; struct cmHeadToLinkInterfaceMap @@ -118,8 +120,7 @@ inline cmTargetLinkLibraryType CMP0003_ComputeLinkType( // Check if any entry in the list matches this configuration. std::string configUpper = cmSystemTools::UpperCase(config); - if (std::find(debugConfigs.begin(), debugConfigs.end(), configUpper) != - debugConfigs.end()) { + if (cmContains(debugConfigs, configUpper)) { return DEBUG_LibraryType; } // The current configuration is not a debug configuration. diff --git a/Source/cmLinkLibrariesCommand.h b/Source/cmLinkLibrariesCommand.h index af25fba..484ab0a 100644 --- a/Source/cmLinkLibrariesCommand.h +++ b/Source/cmLinkLibrariesCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -25,7 +27,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmLinkLibrariesCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmLinkLibrariesCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index 469faca..5e3c790 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -11,6 +11,7 @@ #include "cmOutputConverter.h" #include "cmStateDirectory.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmLinkLineComputer::cmLinkLineComputer(cmOutputConverter* outputConverter, @@ -63,6 +64,7 @@ std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli) continue; } if (item.IsPath) { + linkLibs += cli.GetLibLinkFileFlag(); linkLibs += this->ConvertToOutputFormat(this->ConvertToLinkReference(item.Value)); } else { @@ -110,21 +112,21 @@ std::string cmLinkLineComputer::ComputeLinkPath( if (target->GetType() == cmStateEnums::STATIC_LIBRARY || target->GetType() == cmStateEnums::SHARED_LIBRARY) { cmStateEnums::ArtifactType type = cmStateEnums::RuntimeBinaryArtifact; - if (target->GetType() == cmStateEnums::SHARED_LIBRARY && - target->IsDLLPlatform()) { + if (target->HasImportLibrary(cli.GetConfig())) { type = cmStateEnums::ImportLibraryArtifact; } - linkPath += " " + libPathFlag + - item.Target->GetDirectory(cli.GetConfig(), type) + - libPathTerminator + " "; + linkPath += cmStrCat(" ", libPathFlag, + item.Target->GetDirectory(cli.GetConfig(), type), + libPathTerminator, " "); } } } for (std::string const& libDir : cli.GetDirectories()) { - linkPath += " " + libPathFlag + this->ConvertToOutputForExisting(libDir) + - libPathTerminator + " "; + linkPath += + cmStrCat(" ", libPathFlag, this->ConvertToOutputForExisting(libDir), + libPathTerminator, " "); } return linkPath; diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx index 8d2add6..96af388 100644 --- a/Source/cmLinkLineDeviceComputer.cxx +++ b/Source/cmLinkLineDeviceComputer.cxx @@ -3,21 +3,20 @@ #include "cmLinkLineDeviceComputer.h" -#include <algorithm> #include <set> #include <sstream> #include <utility> -#include <vector> #include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" +#include "cmMakefile.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" -#include "cmSystemTools.h" +#include "cmStringAlgorithms.h" class cmOutputConverter; @@ -156,16 +155,20 @@ bool requireDeviceLinking(cmGeneratorTarget& target, cmLocalGenerator& lg, return false; } + if (!lg.GetMakefile()->IsOn("CMAKE_CUDA_COMPILER_HAS_DEVICE_LINK_PHASE")) { + return false; + } + if (const char* resolveDeviceSymbols = target.GetProperty("CUDA_RESOLVE_DEVICE_SYMBOLS")) { // If CUDA_RESOLVE_DEVICE_SYMBOLS has been explicitly set we need // to honor the value no matter what it is. - return cmSystemTools::IsOn(resolveDeviceSymbols); + return cmIsOn(resolveDeviceSymbols); } if (const char* separableCompilation = target.GetProperty("CUDA_SEPARABLE_COMPILATION")) { - if (cmSystemTools::IsOn(separableCompilation)) { + if (cmIsOn(separableCompilation)) { bool doDeviceLinking = false; switch (target.GetType()) { case cmStateEnums::SHARED_LIBRARY: @@ -182,14 +185,10 @@ bool requireDeviceLinking(cmGeneratorTarget& target, cmLocalGenerator& lg, // Determine if we have any dependencies that require // us to do a device link step - const std::string cuda_lang("CUDA"); cmGeneratorTarget::LinkClosure const* closure = target.GetLinkClosure(config); - bool closureHasCUDA = - (std::find(closure->Languages.begin(), closure->Languages.end(), - cuda_lang) != closure->Languages.end()); - if (closureHasCUDA) { + if (cmContains(closure->Languages, "CUDA")) { cmComputeLinkInformation* pcli = target.GetLinkInformation(config); if (pcli) { cmLinkLineDeviceComputer deviceLinkComputer( diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index 1b01ea2..91dea58 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -13,89 +13,35 @@ #include <stdio.h> #include <stdlib.h> // required for atoi #include <utility> +#include <vector> + +#include "cm_memory.hxx" +#include "cm_static_string_view.hxx" #include "cmAlgorithms.h" +#include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" #include "cmRange.h" +#include "cmStringAlgorithms.h" #include "cmStringReplaceHelper.h" +#include "cmSubcommandTable.h" #include "cmSystemTools.h" -class cmExecutionStatus; - -bool cmListCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) -{ - if (args.size() < 2) { - this->SetError("must be called with at least two arguments."); - return false; - } - - const std::string& subCommand = args[0]; - if (subCommand == "LENGTH") { - return this->HandleLengthCommand(args); - } - if (subCommand == "GET") { - return this->HandleGetCommand(args); - } - if (subCommand == "APPEND") { - return this->HandleAppendCommand(args); - } - if (subCommand == "PREPEND") { - return this->HandlePrependCommand(args); - } - if (subCommand == "POP_BACK") { - return this->HandlePopBackCommand(args); - } - if (subCommand == "POP_FRONT") { - return this->HandlePopFrontCommand(args); - } - if (subCommand == "FIND") { - return this->HandleFindCommand(args); - } - if (subCommand == "INSERT") { - return this->HandleInsertCommand(args); - } - if (subCommand == "JOIN") { - return this->HandleJoinCommand(args); - } - if (subCommand == "REMOVE_AT") { - return this->HandleRemoveAtCommand(args); - } - if (subCommand == "REMOVE_ITEM") { - return this->HandleRemoveItemCommand(args); - } - if (subCommand == "REMOVE_DUPLICATES") { - return this->HandleRemoveDuplicatesCommand(args); - } - if (subCommand == "TRANSFORM") { - return this->HandleTransformCommand(args); - } - if (subCommand == "SORT") { - return this->HandleSortCommand(args); - } - if (subCommand == "SUBLIST") { - return this->HandleSublistCommand(args); - } - if (subCommand == "REVERSE") { - return this->HandleReverseCommand(args); - } - if (subCommand == "FILTER") { - return this->HandleFilterCommand(args); - } +namespace { - std::string e = "does not recognize sub-command " + subCommand; - this->SetError(e); - return false; -} +bool FilterRegex(std::vector<std::string> const& args, bool includeMatches, + std::string const& listName, + std::vector<std::string>& varArgsExpanded, + cmExecutionStatus& status); -bool cmListCommand::GetListString(std::string& listString, - const std::string& var) +bool GetListString(std::string& listString, const std::string& var, + const cmMakefile& makefile) { // get the old value - const char* cacheValue = this->Makefile->GetDefinition(var); + const char* cacheValue = makefile.GetDefinition(var); if (!cacheValue) { return false; } @@ -103,11 +49,11 @@ bool cmListCommand::GetListString(std::string& listString, return true; } -bool cmListCommand::GetList(std::vector<std::string>& list, - const std::string& var) +bool GetList(std::vector<std::string>& list, const std::string& var, + const cmMakefile& makefile) { std::string listString; - if (!this->GetListString(listString, var)) { + if (!GetListString(listString, var, makefile)) { return false; } // if the size of the list @@ -115,25 +61,24 @@ bool cmListCommand::GetList(std::vector<std::string>& list, return true; } // expand the variable into a list - cmSystemTools::ExpandListArgument(listString, list, true); + cmExpandList(listString, list, true); // if no empty elements then just return - if (std::find(list.begin(), list.end(), std::string()) == list.end()) { + if (!cmContains(list, std::string())) { return true; } // if we have empty elements we need to check policy CMP0007 - switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0007)) { + switch (makefile.GetPolicyStatus(cmPolicies::CMP0007)) { case cmPolicies::WARN: { // Default is to warn and use old behavior // OLD behavior is to allow compatibility, so recall // ExpandListArgument without the true which will remove // empty values list.clear(); - cmSystemTools::ExpandListArgument(listString, list); - std::string warn = cmPolicies::GetPolicyWarning(cmPolicies::CMP0007); - warn += " List has value = ["; - warn += listString; - warn += "]."; - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, warn); + cmExpandList(listString, list); + std::string warn = + cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0007), + " List has value = [", listString, "]."); + makefile.IssueMessage(MessageType::AUTHOR_WARNING, warn); return true; } case cmPolicies::OLD: @@ -141,13 +86,13 @@ bool cmListCommand::GetList(std::vector<std::string>& list, // ExpandListArgument without the true which will remove // empty values list.clear(); - cmSystemTools::ExpandListArgument(listString, list); + cmExpandList(listString, list); return true; case cmPolicies::NEW: return true; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: - this->Makefile->IssueMessage( + makefile.IssueMessage( MessageType::FATAL_ERROR, cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0007)); return false; @@ -155,10 +100,11 @@ bool cmListCommand::GetList(std::vector<std::string>& list, return true; } -bool cmListCommand::HandleLengthCommand(std::vector<std::string> const& args) +bool HandleLengthCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 3) { - this->SetError("sub-command LENGTH requires two arguments."); + status.SetError("sub-command LENGTH requires two arguments."); return false; } @@ -168,19 +114,20 @@ bool cmListCommand::HandleLengthCommand(std::vector<std::string> const& args) // do not check the return value here // if the list var is not found varArgsExpanded will have size 0 // and we will return 0 - this->GetList(varArgsExpanded, listName); + GetList(varArgsExpanded, listName, status.GetMakefile()); size_t length = varArgsExpanded.size(); char buffer[1024]; sprintf(buffer, "%d", static_cast<int>(length)); - this->Makefile->AddDefinition(variableName, buffer); + status.GetMakefile().AddDefinition(variableName, buffer); return true; } -bool cmListCommand::HandleGetCommand(std::vector<std::string> const& args) +bool HandleGetCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 4) { - this->SetError("sub-command GET requires at least three arguments."); + status.SetError("sub-command GET requires at least three arguments."); return false; } @@ -188,13 +135,13 @@ bool cmListCommand::HandleGetCommand(std::vector<std::string> const& args) const std::string& variableName = args.back(); // expand the variable std::vector<std::string> varArgsExpanded; - if (!this->GetList(varArgsExpanded, listName)) { - this->Makefile->AddDefinition(variableName, "NOTFOUND"); + if (!GetList(varArgsExpanded, listName, status.GetMakefile())) { + status.GetMakefile().AddDefinition(variableName, "NOTFOUND"); return true; } // FIXME: Add policy to make non-existing lists an error like empty lists. if (varArgsExpanded.empty()) { - this->SetError("GET given empty list"); + status.SetError("GET given empty list"); return false; } @@ -213,17 +160,18 @@ bool cmListCommand::HandleGetCommand(std::vector<std::string> const& args) std::ostringstream str; str << "index: " << item << " out of range (-" << nitem << ", " << nitem - 1 << ")"; - this->SetError(str.str()); + status.SetError(str.str()); return false; } value += varArgsExpanded[item]; } - this->Makefile->AddDefinition(variableName, value.c_str()); + status.GetMakefile().AddDefinition(variableName, value); return true; } -bool cmListCommand::HandleAppendCommand(std::vector<std::string> const& args) +bool HandleAppendCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { assert(args.size() >= 2); @@ -232,10 +180,11 @@ bool cmListCommand::HandleAppendCommand(std::vector<std::string> const& args) return true; } + cmMakefile& makefile = status.GetMakefile(); std::string const& listName = args[1]; // expand the variable std::string listString; - this->GetListString(listString, listName); + GetListString(listString, listName, makefile); // If `listString` or `args` is empty, no need to append `;`, // then index is going to be `1` and points to the end-of-string ";" @@ -243,11 +192,12 @@ bool cmListCommand::HandleAppendCommand(std::vector<std::string> const& args) std::string::size_type(listString.empty() || args.empty()); listString += &";"[offset] + cmJoin(cmMakeRange(args).advance(2), ";"); - this->Makefile->AddDefinition(listName, listString.c_str()); + makefile.AddDefinition(listName, listString); return true; } -bool cmListCommand::HandlePrependCommand(std::vector<std::string> const& args) +bool HandlePrependCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { assert(args.size() >= 2); @@ -256,10 +206,11 @@ bool cmListCommand::HandlePrependCommand(std::vector<std::string> const& args) return true; } + cmMakefile& makefile = status.GetMakefile(); std::string const& listName = args[1]; // expand the variable std::string listString; - this->GetListString(listString, listName); + GetListString(listString, listName, makefile); // If `listString` or `args` is empty, no need to append `;`, // then `offset` is going to be `1` and points to the end-of-string ";" @@ -268,22 +219,24 @@ bool cmListCommand::HandlePrependCommand(std::vector<std::string> const& args) listString.insert(0, cmJoin(cmMakeRange(args).advance(2), ";") + &";"[offset]); - this->Makefile->AddDefinition(listName, listString.c_str()); + makefile.AddDefinition(listName, listString); return true; } -bool cmListCommand::HandlePopBackCommand(std::vector<std::string> const& args) +bool HandlePopBackCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { assert(args.size() >= 2); + cmMakefile& makefile = status.GetMakefile(); auto ai = args.cbegin(); ++ai; // Skip subcommand name std::string const& listName = *ai++; std::vector<std::string> varArgsExpanded; - if (!this->GetList(varArgsExpanded, listName)) { + if (!GetList(varArgsExpanded, listName, makefile)) { // Can't get the list definition... undefine any vars given after. for (; ai != args.cend(); ++ai) { - this->Makefile->RemoveDefinition(*ai); + makefile.RemoveDefinition(*ai); } return true; } @@ -296,41 +249,42 @@ bool cmListCommand::HandlePopBackCommand(std::vector<std::string> const& args) // Ok, assign elements to be removed to the given variables for (; !varArgsExpanded.empty() && ai != args.cend(); ++ai) { assert(!ai->empty()); - this->Makefile->AddDefinition(*ai, varArgsExpanded.back().c_str()); + makefile.AddDefinition(*ai, varArgsExpanded.back()); varArgsExpanded.pop_back(); } // Undefine the rest variables if the list gets empty earlier... for (; ai != args.cend(); ++ai) { - this->Makefile->RemoveDefinition(*ai); + makefile.RemoveDefinition(*ai); } } - this->Makefile->AddDefinition(listName, - cmJoin(varArgsExpanded, ";").c_str()); + makefile.AddDefinition(listName, cmJoin(varArgsExpanded, ";")); } else if (ai != args.cend()) { // The list is empty, but some args were given // Need to *undefine* 'em all, cuz there are no items to assign... for (; ai != args.cend(); ++ai) { - this->Makefile->RemoveDefinition(*ai); + makefile.RemoveDefinition(*ai); } } return true; } -bool cmListCommand::HandlePopFrontCommand(std::vector<std::string> const& args) +bool HandlePopFrontCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { assert(args.size() >= 2); + cmMakefile& makefile = status.GetMakefile(); auto ai = args.cbegin(); ++ai; // Skip subcommand name std::string const& listName = *ai++; std::vector<std::string> varArgsExpanded; - if (!this->GetList(varArgsExpanded, listName)) { + if (!GetList(varArgsExpanded, listName, makefile)) { // Can't get the list definition... undefine any vars given after. for (; ai != args.cend(); ++ai) { - this->Makefile->RemoveDefinition(*ai); + makefile.RemoveDefinition(*ai); } return true; } @@ -344,33 +298,33 @@ bool cmListCommand::HandlePopFrontCommand(std::vector<std::string> const& args) auto vi = varArgsExpanded.begin(); for (; vi != varArgsExpanded.end() && ai != args.cend(); ++ai, ++vi) { assert(!ai->empty()); - this->Makefile->AddDefinition(*ai, vi->c_str()); + makefile.AddDefinition(*ai, *vi); } varArgsExpanded.erase(varArgsExpanded.begin(), vi); // Undefine the rest variables if the list gets empty earlier... for (; ai != args.cend(); ++ai) { - this->Makefile->RemoveDefinition(*ai); + makefile.RemoveDefinition(*ai); } } - this->Makefile->AddDefinition(listName, - cmJoin(varArgsExpanded, ";").c_str()); + makefile.AddDefinition(listName, cmJoin(varArgsExpanded, ";")); } else if (ai != args.cend()) { // The list is empty, but some args were given // Need to *undefine* 'em all, cuz there are no items to assign... for (; ai != args.cend(); ++ai) { - this->Makefile->RemoveDefinition(*ai); + makefile.RemoveDefinition(*ai); } } return true; } -bool cmListCommand::HandleFindCommand(std::vector<std::string> const& args) +bool HandleFindCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 4) { - this->SetError("sub-command FIND requires three arguments."); + status.SetError("sub-command FIND requires three arguments."); return false; } @@ -378,28 +332,29 @@ bool cmListCommand::HandleFindCommand(std::vector<std::string> const& args) const std::string& variableName = args.back(); // expand the variable std::vector<std::string> varArgsExpanded; - if (!this->GetList(varArgsExpanded, listName)) { - this->Makefile->AddDefinition(variableName, "-1"); + if (!GetList(varArgsExpanded, listName, status.GetMakefile())) { + status.GetMakefile().AddDefinition(variableName, "-1"); return true; } std::vector<std::string>::iterator it = std::find(varArgsExpanded.begin(), varArgsExpanded.end(), args[2]); if (it != varArgsExpanded.end()) { - std::ostringstream indexStream; - indexStream << std::distance(varArgsExpanded.begin(), it); - this->Makefile->AddDefinition(variableName, indexStream.str().c_str()); + status.GetMakefile().AddDefinition( + variableName, + std::to_string(std::distance(varArgsExpanded.begin(), it))); return true; } - this->Makefile->AddDefinition(variableName, "-1"); + status.GetMakefile().AddDefinition(variableName, "-1"); return true; } -bool cmListCommand::HandleInsertCommand(std::vector<std::string> const& args) +bool HandleInsertCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 4) { - this->SetError("sub-command INSERT requires at least three arguments."); + status.SetError("sub-command INSERT requires at least three arguments."); return false; } @@ -408,11 +363,12 @@ bool cmListCommand::HandleInsertCommand(std::vector<std::string> const& args) // expand the variable int item = atoi(args[2].c_str()); std::vector<std::string> varArgsExpanded; - if ((!this->GetList(varArgsExpanded, listName) || varArgsExpanded.empty()) && + if ((!GetList(varArgsExpanded, listName, status.GetMakefile()) || + varArgsExpanded.empty()) && item != 0) { std::ostringstream str; str << "index: " << item << " out of range (0, 0)"; - this->SetError(str.str()); + status.SetError(str.str()); return false; } @@ -425,7 +381,7 @@ bool cmListCommand::HandleInsertCommand(std::vector<std::string> const& args) std::ostringstream str; str << "index: " << item << " out of range (-" << varArgsExpanded.size() << ", " << varArgsExpanded.size() << ")"; - this->SetError(str.str()); + status.SetError(str.str()); return false; } } @@ -434,17 +390,18 @@ bool cmListCommand::HandleInsertCommand(std::vector<std::string> const& args) args.end()); std::string value = cmJoin(varArgsExpanded, ";"); - this->Makefile->AddDefinition(listName, value.c_str()); + status.GetMakefile().AddDefinition(listName, value); return true; } -bool cmListCommand::HandleJoinCommand(std::vector<std::string> const& args) +bool HandleJoinCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 4) { std::ostringstream error; error << "sub-command JOIN requires three arguments (" << args.size() - 1 << " found)."; - this->SetError(error.str()); + status.SetError(error.str()); return false; } @@ -454,30 +411,30 @@ bool cmListCommand::HandleJoinCommand(std::vector<std::string> const& args) // expand the variable std::vector<std::string> varArgsExpanded; - if (!this->GetList(varArgsExpanded, listName)) { - this->Makefile->AddDefinition(variableName, ""); + if (!GetList(varArgsExpanded, listName, status.GetMakefile())) { + status.GetMakefile().AddDefinition(variableName, ""); return true; } std::string value = cmJoin(cmMakeRange(varArgsExpanded.begin(), varArgsExpanded.end()), glue); - this->Makefile->AddDefinition(variableName, value.c_str()); + status.GetMakefile().AddDefinition(variableName, value); return true; } -bool cmListCommand::HandleRemoveItemCommand( - std::vector<std::string> const& args) +bool HandleRemoveItemCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 3) { - this->SetError("sub-command REMOVE_ITEM requires two or more arguments."); + status.SetError("sub-command REMOVE_ITEM requires two or more arguments."); return false; } const std::string& listName = args[1]; // expand the variable std::vector<std::string> varArgsExpanded; - if (!this->GetList(varArgsExpanded, listName)) { + if (!GetList(varArgsExpanded, listName, status.GetMakefile())) { return true; } @@ -491,44 +448,45 @@ bool cmListCommand::HandleRemoveItemCommand( cmRemoveMatching(varArgsExpanded, cmMakeRange(remBegin, remEnd)); std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin(); std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";"); - this->Makefile->AddDefinition(listName, value.c_str()); + status.GetMakefile().AddDefinition(listName, value); return true; } -bool cmListCommand::HandleReverseCommand(std::vector<std::string> const& args) +bool HandleReverseCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { assert(args.size() >= 2); if (args.size() > 2) { - this->SetError("sub-command REVERSE only takes one argument."); + status.SetError("sub-command REVERSE only takes one argument."); return false; } const std::string& listName = args[1]; // expand the variable std::vector<std::string> varArgsExpanded; - if (!this->GetList(varArgsExpanded, listName)) { + if (!GetList(varArgsExpanded, listName, status.GetMakefile())) { return true; } std::string value = cmJoin(cmReverseRange(varArgsExpanded), ";"); - this->Makefile->AddDefinition(listName, value.c_str()); + status.GetMakefile().AddDefinition(listName, value); return true; } -bool cmListCommand::HandleRemoveDuplicatesCommand( - std::vector<std::string> const& args) +bool HandleRemoveDuplicatesCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { assert(args.size() >= 2); if (args.size() > 2) { - this->SetError("sub-command REMOVE_DUPLICATES only takes one argument."); + status.SetError("sub-command REMOVE_DUPLICATES only takes one argument."); return false; } const std::string& listName = args[1]; // expand the variable std::vector<std::string> varArgsExpanded; - if (!this->GetList(varArgsExpanded, listName)) { + if (!GetList(varArgsExpanded, listName, status.GetMakefile())) { return true; } @@ -537,12 +495,11 @@ bool cmListCommand::HandleRemoveDuplicatesCommand( std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin(); std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";"); - this->Makefile->AddDefinition(listName, value.c_str()); + status.GetMakefile().AddDefinition(listName, value); return true; } // Helpers for list(TRANSFORM <list> ...) -namespace { using transform_type = std::function<std::string(const std::string&)>; class transform_error : public std::runtime_error @@ -693,7 +650,8 @@ public: } this->Indexes.resize(size); - auto start = this->Start, step = this->Step; + auto start = this->Start; + auto step = this->Step; std::generate(this->Indexes.begin(), this->Indexes.end(), [&start, step]() -> int { auto r = start; @@ -757,13 +715,12 @@ public: private: cmStringReplaceHelper ReplaceHelper; }; -} -bool cmListCommand::HandleTransformCommand( - std::vector<std::string> const& args) +bool HandleTransformCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 3) { - this->SetError( + status.SetError( "sub-command TRANSFORM requires an action to be specified."); return false; } @@ -853,7 +810,7 @@ bool cmListCommand::HandleTransformCommand( { "STRIP", 0, [&command](const std::string& s) -> std::string { if (command.Selector->InSelection(s)) { - return cmSystemTools::TrimWhitespace(s); + return cmTrimWhitespace(s); } return s; @@ -886,7 +843,7 @@ bool cmListCommand::HandleTransformCommand( if (descriptor == descriptors.end()) { std::ostringstream error; error << " sub-command TRANSFORM, " << args[index] << " invalid action."; - this->SetError(error.str()); + status.SetError(error.str()); return false; } @@ -896,7 +853,7 @@ bool cmListCommand::HandleTransformCommand( std::ostringstream error; error << "sub-command TRANSFORM, action " << descriptor->Name << " expects " << descriptor->Arity << " argument(s)."; - this->SetError(error.str()); + status.SetError(error.str()); return false; } @@ -909,16 +866,18 @@ bool cmListCommand::HandleTransformCommand( if (command.Name == "REPLACE") { try { - command.Action = - cm::make_unique<TransformReplace>(command.Arguments, this->Makefile); + command.Action = cm::make_unique<TransformReplace>( + command.Arguments, &status.GetMakefile()); } catch (const transform_error& e) { - this->SetError(e.what()); + status.SetError(e.what()); return false; } } - const std::string REGEX{ "REGEX" }, AT{ "AT" }, FOR{ "FOR" }, - OUTPUT_VARIABLE{ "OUTPUT_VARIABLE" }; + const std::string REGEX{ "REGEX" }; + const std::string AT{ "AT" }; + const std::string FOR{ "FOR" }; + const std::string OUTPUT_VARIABLE{ "OUTPUT_VARIABLE" }; // handle optional arguments while (args.size() > index) { @@ -927,15 +886,15 @@ bool cmListCommand::HandleTransformCommand( std::ostringstream error; error << "sub-command TRANSFORM, selector already specified (" << command.Selector->Tag << ")."; - this->SetError(error.str()); + status.SetError(error.str()); return false; } // REGEX selector if (args[index] == REGEX) { if (args.size() == ++index) { - this->SetError("sub-command TRANSFORM, selector REGEX expects " - "'regular expression' argument."); + status.SetError("sub-command TRANSFORM, selector REGEX expects " + "'regular expression' argument."); return false; } @@ -945,7 +904,7 @@ bool cmListCommand::HandleTransformCommand( error << "sub-command TRANSFORM, selector REGEX failed to compile " "regex \""; error << args[index] << "\"."; - this->SetError(error.str()); + status.SetError(error.str()); return false; } @@ -975,7 +934,7 @@ bool cmListCommand::HandleTransformCommand( } if (indexes.empty()) { - this->SetError( + status.SetError( "sub-command TRANSFORM, selector AT expects at least one " "numeric value."); return false; @@ -990,12 +949,15 @@ bool cmListCommand::HandleTransformCommand( // FOR selector if (args[index] == FOR) { if (args.size() <= ++index + 1) { - this->SetError("sub-command TRANSFORM, selector FOR expects, at least," - " two arguments."); + status.SetError( + "sub-command TRANSFORM, selector FOR expects, at least," + " two arguments."); return false; } - int start = 0, stop = 0, step = 1; + int start = 0; + int stop = 0; + int step = 1; bool valid = true; try { std::size_t pos; @@ -1016,8 +978,8 @@ bool cmListCommand::HandleTransformCommand( valid = false; } if (!valid) { - this->SetError("sub-command TRANSFORM, selector FOR expects, " - "at least, two numeric values."); + status.SetError("sub-command TRANSFORM, selector FOR expects, " + "at least, two numeric values."); return false; } // try to read a third numeric value for step @@ -1038,8 +1000,8 @@ bool cmListCommand::HandleTransformCommand( } if (step < 0) { - this->SetError("sub-command TRANSFORM, selector FOR expects " - "non negative numeric value for <step>."); + status.SetError("sub-command TRANSFORM, selector FOR expects " + "non negative numeric value for <step>."); } command.Selector = @@ -1051,8 +1013,8 @@ bool cmListCommand::HandleTransformCommand( // output variable if (args[index] == OUTPUT_VARIABLE) { if (args.size() == ++index) { - this->SetError("sub-command TRANSFORM, OUTPUT_VARIABLE " - "expects variable name argument."); + status.SetError("sub-command TRANSFORM, OUTPUT_VARIABLE " + "expects variable name argument."); return false; } @@ -1064,14 +1026,14 @@ bool cmListCommand::HandleTransformCommand( error << "sub-command TRANSFORM, '" << cmJoin(cmMakeRange(args).advance(index), " ") << "': unexpected argument(s)."; - this->SetError(error.str()); + status.SetError(error.str()); return false; } // expand the list variable std::vector<std::string> varArgsExpanded; - if (!this->GetList(varArgsExpanded, command.ListName)) { - this->Makefile->AddDefinition(command.OutputName, ""); + if (!GetList(varArgsExpanded, command.ListName, status.GetMakefile())) { + status.GetMakefile().AddDefinition(command.OutputName, ""); return true; } @@ -1083,12 +1045,12 @@ bool cmListCommand::HandleTransformCommand( try { command.Selector->Transform(varArgsExpanded, descriptor->Transform); } catch (const transform_error& e) { - this->SetError(e.what()); + status.SetError(e.what()); return false; } - this->Makefile->AddDefinition(command.OutputName, - cmJoin(varArgsExpanded, ";").c_str()); + status.GetMakefile().AddDefinition(command.OutputName, + cmJoin(varArgsExpanded, ";")); return true; } @@ -1168,11 +1130,12 @@ protected: bool descending; }; -bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args) +bool HandleSortCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { assert(args.size() >= 2); if (args.size() > 8) { - this->SetError("sub-command SORT only takes up to six arguments."); + status.SetError("sub-command SORT only takes up to six arguments."); return false; } @@ -1187,9 +1150,9 @@ bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args) const std::string option = args[argumentIndex++]; if (option == "COMPARE") { if (sortCompare != cmStringSorter::Compare::UNINITIALIZED) { - std::string error = messageHint + "option \"" + option + - "\" has been specified multiple times."; - this->SetError(error); + std::string error = cmStrCat(messageHint, "option \"", option, + "\" has been specified multiple times."); + status.SetError(error); return false; } if (argumentIndex < args.size()) { @@ -1199,23 +1162,22 @@ bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args) } else if (argument == "FILE_BASENAME") { sortCompare = cmStringSorter::Compare::FILE_BASENAME; } else { - std::string error = messageHint + "value \"" + argument + - "\" for option \"" + option + "\" is invalid."; - this->SetError(error); + std::string error = + cmStrCat(messageHint, "value \"", argument, "\" for option \"", + option, "\" is invalid."); + status.SetError(error); return false; } } else { - std::string error = - messageHint + "missing argument for option \"" + option + "\"."; - this->SetError(error); + status.SetError(cmStrCat(messageHint, "missing argument for option \"", + option, "\".")); return false; } } else if (option == "CASE") { if (sortCaseSensitivity != cmStringSorter::CaseSensitivity::UNINITIALIZED) { - std::string error = messageHint + "option \"" + option + - "\" has been specified multiple times."; - this->SetError(error); + status.SetError(cmStrCat(messageHint, "option \"", option, + "\" has been specified multiple times.")); return false; } if (argumentIndex < args.size()) { @@ -1225,23 +1187,21 @@ bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args) } else if (argument == "INSENSITIVE") { sortCaseSensitivity = cmStringSorter::CaseSensitivity::INSENSITIVE; } else { - std::string error = messageHint + "value \"" + argument + - "\" for option \"" + option + "\" is invalid."; - this->SetError(error); + status.SetError(cmStrCat(messageHint, "value \"", argument, + "\" for option \"", option, + "\" is invalid.")); return false; } } else { - std::string error = - messageHint + "missing argument for option \"" + option + "\"."; - this->SetError(error); + status.SetError(cmStrCat(messageHint, "missing argument for option \"", + option, "\".")); return false; } } else if (option == "ORDER") { if (sortOrder != cmStringSorter::Order::UNINITIALIZED) { - std::string error = messageHint + "option \"" + option + - "\" has been specified multiple times."; - this->SetError(error); + status.SetError(cmStrCat(messageHint, "option \"", option, + "\" has been specified multiple times.")); return false; } if (argumentIndex < args.size()) { @@ -1251,21 +1211,19 @@ bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args) } else if (argument == "DESCENDING") { sortOrder = cmStringSorter::Order::DESCENDING; } else { - std::string error = messageHint + "value \"" + argument + - "\" for option \"" + option + "\" is invalid."; - this->SetError(error); + status.SetError(cmStrCat(messageHint, "value \"", argument, + "\" for option \"", option, + "\" is invalid.")); return false; } } else { - std::string error = - messageHint + "missing argument for option \"" + option + "\"."; - this->SetError(error); + status.SetError(cmStrCat(messageHint, "missing argument for option \"", + option, "\".")); return false; } } else { - std::string error = - messageHint + "option \"" + option + "\" is unknown."; - this->SetError(error); + status.SetError( + cmStrCat(messageHint, "option \"", option, "\" is unknown.")); return false; } } @@ -1283,7 +1241,7 @@ bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args) const std::string& listName = args[1]; // expand the variable std::vector<std::string> varArgsExpanded; - if (!this->GetList(varArgsExpanded, listName)) { + if (!GetList(varArgsExpanded, listName, status.GetMakefile())) { return true; } @@ -1297,17 +1255,18 @@ bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args) } std::string value = cmJoin(varArgsExpanded, ";"); - this->Makefile->AddDefinition(listName, value.c_str()); + status.GetMakefile().AddDefinition(listName, value); return true; } -bool cmListCommand::HandleSublistCommand(std::vector<std::string> const& args) +bool HandleSublistCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 5) { std::ostringstream error; error << "sub-command SUBLIST requires four arguments (" << args.size() - 1 << " found)."; - this->SetError(error.str()); + status.SetError(error.str()); return false; } @@ -1316,8 +1275,9 @@ bool cmListCommand::HandleSublistCommand(std::vector<std::string> const& args) // expand the variable std::vector<std::string> varArgsExpanded; - if (!this->GetList(varArgsExpanded, listName) || varArgsExpanded.empty()) { - this->Makefile->AddDefinition(variableName, ""); + if (!GetList(varArgsExpanded, listName, status.GetMakefile()) || + varArgsExpanded.empty()) { + status.GetMakefile().AddDefinition(variableName, ""); return true; } @@ -1330,13 +1290,13 @@ bool cmListCommand::HandleSublistCommand(std::vector<std::string> const& args) std::ostringstream error; error << "begin index: " << start << " is out of range 0 - " << varArgsExpanded.size() - 1; - this->SetError(error.str()); + status.SetError(error.str()); return false; } if (length < -1) { std::ostringstream error; error << "length: " << length << " should be -1 or greater"; - this->SetError(error.str()); + status.SetError(error.str()); return false; } @@ -1346,22 +1306,24 @@ bool cmListCommand::HandleSublistCommand(std::vector<std::string> const& args) : size_type(start + length); std::vector<std::string> sublist(varArgsExpanded.begin() + start, varArgsExpanded.begin() + end); - this->Makefile->AddDefinition(variableName, cmJoin(sublist, ";").c_str()); + status.GetMakefile().AddDefinition(variableName, cmJoin(sublist, ";")); return true; } -bool cmListCommand::HandleRemoveAtCommand(std::vector<std::string> const& args) +bool HandleRemoveAtCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 3) { - this->SetError("sub-command REMOVE_AT requires at least " - "two arguments."); + status.SetError("sub-command REMOVE_AT requires at least " + "two arguments."); return false; } const std::string& listName = args[1]; // expand the variable std::vector<std::string> varArgsExpanded; - if (!this->GetList(varArgsExpanded, listName) || varArgsExpanded.empty()) { + if (!GetList(varArgsExpanded, listName, status.GetMakefile()) || + varArgsExpanded.empty()) { std::ostringstream str; str << "index: "; for (size_t i = 1; i < args.size(); ++i) { @@ -1371,7 +1333,7 @@ bool cmListCommand::HandleRemoveAtCommand(std::vector<std::string> const& args) } } str << " out of range (0, 0)"; - this->SetError(str.str()); + status.SetError(str.str()); return false; } @@ -1387,7 +1349,7 @@ bool cmListCommand::HandleRemoveAtCommand(std::vector<std::string> const& args) std::ostringstream str; str << "index: " << item << " out of range (-" << nitem << ", " << nitem - 1 << ")"; - this->SetError(str.str()); + status.SetError(str.str()); return false; } removed.push_back(static_cast<size_t>(item)); @@ -1403,24 +1365,26 @@ bool cmListCommand::HandleRemoveAtCommand(std::vector<std::string> const& args) std::vector<std::string>::const_iterator argsBegin = varArgsExpanded.begin(); std::string value = cmJoin(cmMakeRange(argsBegin, argsEnd), ";"); - this->Makefile->AddDefinition(listName, value.c_str()); + status.GetMakefile().AddDefinition(listName, value); return true; } -bool cmListCommand::HandleFilterCommand(std::vector<std::string> const& args) +bool HandleFilterCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 2) { - this->SetError("sub-command FILTER requires a list to be specified."); + status.SetError("sub-command FILTER requires a list to be specified."); return false; } if (args.size() < 3) { - this->SetError("sub-command FILTER requires an operator to be specified."); + status.SetError( + "sub-command FILTER requires an operator to be specified."); return false; } if (args.size() < 4) { - this->SetError("sub-command FILTER requires a mode to be specified."); + status.SetError("sub-command FILTER requires a mode to be specified."); return false; } @@ -1431,28 +1395,29 @@ bool cmListCommand::HandleFilterCommand(std::vector<std::string> const& args) } else if (op == "EXCLUDE") { includeMatches = false; } else { - this->SetError("sub-command FILTER does not recognize operator " + op); + status.SetError("sub-command FILTER does not recognize operator " + op); return false; } const std::string& listName = args[1]; // expand the variable std::vector<std::string> varArgsExpanded; - if (!this->GetList(varArgsExpanded, listName)) { + if (!GetList(varArgsExpanded, listName, status.GetMakefile())) { return true; } const std::string& mode = args[3]; if (mode == "REGEX") { if (args.size() != 5) { - this->SetError("sub-command FILTER, mode REGEX " - "requires five arguments."); + status.SetError("sub-command FILTER, mode REGEX " + "requires five arguments."); return false; } - return this->FilterRegex(args, includeMatches, listName, varArgsExpanded); + return FilterRegex(args, includeMatches, listName, varArgsExpanded, + status); } - this->SetError("sub-command FILTER does not recognize mode " + mode); + status.SetError("sub-command FILTER does not recognize mode " + mode); return false; } @@ -1475,19 +1440,18 @@ private: const bool includeMatches; }; -bool cmListCommand::FilterRegex(std::vector<std::string> const& args, - bool includeMatches, - std::string const& listName, - std::vector<std::string>& varArgsExpanded) +bool FilterRegex(std::vector<std::string> const& args, bool includeMatches, + std::string const& listName, + std::vector<std::string>& varArgsExpanded, + cmExecutionStatus& status) { const std::string& pattern = args[4]; cmsys::RegularExpression regex(pattern); if (!regex.is_valid()) { - std::string error = "sub-command FILTER, mode REGEX "; - error += "failed to compile regex \""; - error += pattern; - error += "\"."; - this->SetError(error); + std::string error = + cmStrCat("sub-command FILTER, mode REGEX failed to compile regex \"", + pattern, "\"."); + status.SetError(error); return false; } @@ -1497,6 +1461,39 @@ bool cmListCommand::FilterRegex(std::vector<std::string> const& args, std::remove_if(argsBegin, argsEnd, MatchesRegex(regex, includeMatches)); std::string value = cmJoin(cmMakeRange(argsBegin, newArgsEnd), ";"); - this->Makefile->AddDefinition(listName, value.c_str()); + status.GetMakefile().AddDefinition(listName, value); return true; } + +} // namespace + +bool cmListCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + if (args.size() < 2) { + status.SetError("must be called with at least two arguments."); + return false; + } + + static cmSubcommandTable const subcommand{ + { "LENGTH"_s, HandleLengthCommand }, + { "GET"_s, HandleGetCommand }, + { "APPEND"_s, HandleAppendCommand }, + { "PREPEND"_s, HandlePrependCommand }, + { "POP_BACK"_s, HandlePopBackCommand }, + { "POP_FRONT"_s, HandlePopFrontCommand }, + { "FIND"_s, HandleFindCommand }, + { "INSERT"_s, HandleInsertCommand }, + { "JOIN"_s, HandleJoinCommand }, + { "REMOVE_AT"_s, HandleRemoveAtCommand }, + { "REMOVE_ITEM"_s, HandleRemoveItemCommand }, + { "REMOVE_DUPLICATES"_s, HandleRemoveDuplicatesCommand }, + { "TRANSFORM"_s, HandleTransformCommand }, + { "SORT"_s, HandleSortCommand }, + { "SUBLIST"_s, HandleSublistCommand }, + { "REVERSE"_s, HandleReverseCommand }, + { "FILTER"_s, HandleFilterCommand }, + }; + + return subcommand(args[0], args, status); +} diff --git a/Source/cmListCommand.h b/Source/cmListCommand.h index ea3d643..274d9fd 100644 --- a/Source/cmListCommand.h +++ b/Source/cmListCommand.h @@ -8,53 +8,13 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmListCommand +/** * \brief Common list operations * */ -class cmListCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmListCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -protected: - bool HandleLengthCommand(std::vector<std::string> const& args); - bool HandleGetCommand(std::vector<std::string> const& args); - bool HandleAppendCommand(std::vector<std::string> const& args); - bool HandlePrependCommand(std::vector<std::string> const& args); - bool HandlePopBackCommand(std::vector<std::string> const& args); - bool HandlePopFrontCommand(std::vector<std::string> const& args); - bool HandleFindCommand(std::vector<std::string> const& args); - bool HandleInsertCommand(std::vector<std::string> const& args); - bool HandleJoinCommand(std::vector<std::string> const& args); - bool HandleRemoveAtCommand(std::vector<std::string> const& args); - bool HandleRemoveItemCommand(std::vector<std::string> const& args); - bool HandleRemoveDuplicatesCommand(std::vector<std::string> const& args); - bool HandleTransformCommand(std::vector<std::string> const& args); - bool HandleSortCommand(std::vector<std::string> const& args); - bool HandleSublistCommand(std::vector<std::string> const& args); - bool HandleReverseCommand(std::vector<std::string> const& args); - bool HandleFilterCommand(std::vector<std::string> const& args); - bool FilterRegex(std::vector<std::string> const& args, bool includeMatches, - std::string const& listName, - std::vector<std::string>& varArgsExpanded); - - bool GetList(std::vector<std::string>& list, const std::string& var); - bool GetListString(std::string& listString, const std::string& var); -}; +bool cmListCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index df0d00c..ff3ecd9 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -7,6 +7,7 @@ #include "cmMessenger.h" #include "cmState.h" #include "cmStateDirectory.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include <assert.h> @@ -482,8 +483,7 @@ std::vector<BT<std::string>> ExpandListWithBacktrace( std::string const& list, cmListFileBacktrace const& bt) { std::vector<BT<std::string>> result; - std::vector<std::string> tmp; - cmSystemTools::ExpandListArgument(list, tmp); + std::vector<std::string> tmp = cmExpandedList(list); result.reserve(tmp.size()); for (std::string& i : tmp) { result.emplace_back(std::move(i), bt); diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h index 9457415..5de1a74 100644 --- a/Source/cmListFileCache.h +++ b/Source/cmListFileCache.h @@ -6,7 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> -#include <memory> // IWYU pragma: keep +#include <memory> #include <stddef.h> #include <string> #include <utility> diff --git a/Source/cmLoadCacheCommand.cxx b/Source/cmLoadCacheCommand.cxx index b1fee8d..3fd7343 100644 --- a/Source/cmLoadCacheCommand.cxx +++ b/Source/cmLoadCacheCommand.cxx @@ -153,7 +153,7 @@ void cmLoadCacheCommand::CheckLine(const char* line) // prefix. var = this->Prefix + var; if (!value.empty()) { - this->Makefile->AddDefinition(var, value.c_str()); + this->Makefile->AddDefinition(var, value); } else { this->Makefile->RemoveDefinition(var); } diff --git a/Source/cmLoadCacheCommand.h b/Source/cmLoadCacheCommand.h index e0f6e4f..45e52f0 100644 --- a/Source/cmLoadCacheCommand.h +++ b/Source/cmLoadCacheCommand.h @@ -9,6 +9,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -24,7 +26,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmLoadCacheCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmLoadCacheCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index 69751b6..180e65b 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -3,16 +3,21 @@ #include "cmLoadCommandCommand.h" #include <signal.h> + #include <sstream> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <utility> + +#include "cm_memory.hxx" #include "cmCPluginAPI.cxx" #include "cmCPluginAPI.h" #include "cmDynamicLoader.h" #include "cmMakefile.h" #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmExecutionStatus; @@ -21,30 +26,98 @@ class cmExecutionStatus; # include <malloc.h> /* for malloc/free on QNX */ #endif -extern "C" void TrapsForSignalsCFunction(int sig); +namespace { + +const char* LastName = nullptr; + +extern "C" void TrapsForSignals(int sig) +{ + fprintf(stderr, "CMake loaded command %s crashed with signal: %d.\n", + LastName, sig); +} + +struct SignalHandlerGuard +{ + explicit SignalHandlerGuard(const char* name) + { + LastName = name != nullptr ? name : "????"; + + signal(SIGSEGV, TrapsForSignals); +#ifdef SIGBUS + signal(SIGBUS, TrapsForSignals); +#endif + signal(SIGILL, TrapsForSignals); + } + + ~SignalHandlerGuard() + { + signal(SIGSEGV, nullptr); +#ifdef SIGBUS + signal(SIGBUS, nullptr); +#endif + signal(SIGILL, nullptr); + } + + SignalHandlerGuard(SignalHandlerGuard const&) = delete; + SignalHandlerGuard& operator=(SignalHandlerGuard const&) = delete; +}; + +struct LoadedCommandImpl : cmLoadedCommandInfo +{ + explicit LoadedCommandImpl(CM_INIT_FUNCTION init) + : cmLoadedCommandInfo{ 0, 0, &cmStaticCAPI, 0, + nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr } + { + init(this); + } + + ~LoadedCommandImpl() + { + if (this->Destructor) { + SignalHandlerGuard guard(this->Name); + this->Destructor(this); + } + if (this->Error != nullptr) { + free(this->Error); + } + } + + LoadedCommandImpl(LoadedCommandImpl const&) = delete; + LoadedCommandImpl& operator=(LoadedCommandImpl const&) = delete; + + int DoInitialPass(cmMakefile* mf, int argc, char* argv[]) + { + SignalHandlerGuard guard(this->Name); + return this->InitialPass(this, mf, argc, argv); + } + + void DoFinalPass(cmMakefile* mf) + { + SignalHandlerGuard guard(this->Name); + this->FinalPass(this, mf); + } +}; // a class for loadabple commands class cmLoadedCommand : public cmCommand { public: - cmLoadedCommand() + cmLoadedCommand() = default; + explicit cmLoadedCommand(CM_INIT_FUNCTION init) + : Impl(std::make_shared<LoadedCommandImpl>(init)) { - memset(&this->info, 0, sizeof(this->info)); - this->info.CAPI = &cmStaticCAPI; } - //! clean up any memory allocated by the plugin - ~cmLoadedCommand() override; - /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override + std::unique_ptr<cmCommand> Clone() override { - cmLoadedCommand* newC = new cmLoadedCommand; + auto newC = cm::make_unique<cmLoadedCommand>(); // we must copy when we clone - memcpy(&newC->info, &this->info, sizeof(info)); - return newC; + newC->Impl = this->Impl; + return std::unique_ptr<cmCommand>(std::move(newC)); } /** @@ -54,66 +127,20 @@ public: bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus&) override; - /** - * This is called at the end after all the information - * specified by the command is accumulated. Most commands do - * not implement this method. At this point, reading and - * writing to the cache can be done. - */ - void FinalPass() override; - bool HasFinalPass() const override - { - return this->info.FinalPass != nullptr; - } - - static const char* LastName; - static void TrapsForSignals(int sig) - { - fprintf(stderr, "CMake loaded command %s crashed with signal: %d.\n", - cmLoadedCommand::LastName, sig); - } - static void InstallSignalHandlers(const char* name, int remove = 0) - { - cmLoadedCommand::LastName = name; - if (!name) { - cmLoadedCommand::LastName = "????"; - } - - if (!remove) { - signal(SIGSEGV, TrapsForSignalsCFunction); -#ifdef SIGBUS - signal(SIGBUS, TrapsForSignalsCFunction); -#endif - signal(SIGILL, TrapsForSignalsCFunction); - } else { - signal(SIGSEGV, nullptr); -#ifdef SIGBUS - signal(SIGBUS, nullptr); -#endif - signal(SIGILL, nullptr); - } - } - - cmLoadedCommandInfo info; +private: + std::shared_ptr<LoadedCommandImpl> Impl; }; -extern "C" void TrapsForSignalsCFunction(int sig) -{ - cmLoadedCommand::TrapsForSignals(sig); -} - -const char* cmLoadedCommand::LastName = nullptr; - bool cmLoadedCommand::InitialPass(std::vector<std::string> const& args, cmExecutionStatus&) { - if (!info.InitialPass) { + if (!this->Impl->InitialPass) { return true; } // clear the error string - if (this->info.Error) { - free(this->info.Error); + if (this->Impl->Error) { + free(this->Impl->Error); } // create argc and argv and then invoke the command @@ -126,42 +153,26 @@ bool cmLoadedCommand::InitialPass(std::vector<std::string> const& args, for (i = 0; i < argc; ++i) { argv[i] = strdup(args[i].c_str()); } - cmLoadedCommand::InstallSignalHandlers(info.Name); - int result = info.InitialPass(&info, this->Makefile, argc, argv); - cmLoadedCommand::InstallSignalHandlers(info.Name, 1); + int result = this->Impl->DoInitialPass(this->Makefile, argc, argv); cmFreeArguments(argc, argv); if (result) { + if (this->Impl->FinalPass) { + auto impl = this->Impl; + this->Makefile->AddFinalAction( + [impl](cmMakefile& makefile) { impl->DoFinalPass(&makefile); }); + } return true; } /* Initial Pass must have failed so set the error string */ - if (this->info.Error) { - this->SetError(this->info.Error); + if (this->Impl->Error) { + this->SetError(this->Impl->Error); } return false; } -void cmLoadedCommand::FinalPass() -{ - if (this->info.FinalPass) { - cmLoadedCommand::InstallSignalHandlers(info.Name); - this->info.FinalPass(&this->info, this->Makefile); - cmLoadedCommand::InstallSignalHandlers(info.Name, 1); - } -} - -cmLoadedCommand::~cmLoadedCommand() -{ - if (this->info.Destructor) { - cmLoadedCommand::InstallSignalHandlers(info.Name); - this->info.Destructor(&this->info); - cmLoadedCommand::InstallSignalHandlers(info.Name, 1); - } - if (this->info.Error) { - free(this->info.Error); - } -} +} // namespace // cmLoadCommandCommand bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args, @@ -173,16 +184,14 @@ bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args, // Construct a variable to report what file was loaded, if any. // Start by removing the definition in case of failure. - std::string reportVar = "CMAKE_LOADED_COMMAND_"; - reportVar += args[0]; + std::string reportVar = cmStrCat("CMAKE_LOADED_COMMAND_", args[0]); this->Makefile->RemoveDefinition(reportVar); // the file must exist - std::string moduleName = - this->Makefile->GetRequiredDefinition("CMAKE_SHARED_MODULE_PREFIX"); - moduleName += "cm" + args[0]; - moduleName += - this->Makefile->GetRequiredDefinition("CMAKE_SHARED_MODULE_SUFFIX"); + std::string moduleName = cmStrCat( + this->Makefile->GetRequiredDefinition("CMAKE_SHARED_MODULE_PREFIX"), "cm", + args[0], + this->Makefile->GetRequiredDefinition("CMAKE_SHARED_MODULE_SUFFIX")); // search for the file std::vector<std::string> path; @@ -208,8 +217,8 @@ bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args, cmsys::DynamicLoader::LibraryHandle lib = cmDynamicLoader::OpenLibrary(fullPath.c_str()); if (!lib) { - std::string err = "Attempt to load the library "; - err += fullPath + " failed."; + std::string err = + cmStrCat("Attempt to load the library ", fullPath, " failed."); const char* error = cmsys::DynamicLoader::LastError(); if (error) { err += " Additional error info is:\n"; @@ -220,26 +229,23 @@ bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args, } // Report what file was loaded for this command. - this->Makefile->AddDefinition(reportVar, fullPath.c_str()); + this->Makefile->AddDefinition(reportVar, fullPath); // find the init function std::string initFuncName = args[0] + "Init"; CM_INIT_FUNCTION initFunction = reinterpret_cast<CM_INIT_FUNCTION>( cmsys::DynamicLoader::GetSymbolAddress(lib, initFuncName)); if (!initFunction) { - initFuncName = "_"; - initFuncName += args[0]; - initFuncName += "Init"; + initFuncName = cmStrCat('_', args[0], "Init"); initFunction = reinterpret_cast<CM_INIT_FUNCTION>( cmsys::DynamicLoader::GetSymbolAddress(lib, initFuncName)); } // if the symbol is found call it to set the name on the // function blocker if (initFunction) { - // create a function blocker and set it up - cmLoadedCommand* f = new cmLoadedCommand(); - (*initFunction)(&f->info); - this->Makefile->GetState()->AddScriptedCommand(args[0], f); + this->Makefile->GetState()->AddScriptedCommand( + args[0], + cmLegacyCommandWrapper(cm::make_unique<cmLoadedCommand>(initFunction))); return true; } this->SetError("Attempt to load command failed. " diff --git a/Source/cmLoadCommandCommand.h b/Source/cmLoadCommandCommand.h index 021e6c7..d81cefb 100644 --- a/Source/cmLoadCommandCommand.h +++ b/Source/cmLoadCommandCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -15,7 +17,10 @@ class cmExecutionStatus; class cmLoadCommandCommand : public cmCommand { public: - cmCommand* Clone() override { return new cmLoadCommandCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmLoadCommandCommand>(); + } bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; }; diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx index 75ad2a6..7c36bdc 100644 --- a/Source/cmLocalCommonGenerator.cxx +++ b/Source/cmLocalCommonGenerator.cxx @@ -8,6 +8,7 @@ #include "cmGeneratorTarget.h" #include "cmMakefile.h" #include "cmOutputConverter.h" +#include "cmStringAlgorithms.h" class cmGlobalGenerator; @@ -51,9 +52,9 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags( this->Makefile->GetSafeDefinition("CMAKE_Fortran_MODDIR_DEFAULT"); } if (!mod_dir.empty()) { - std::string modflag = - this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG"); - modflag += mod_dir; + std::string modflag = cmStrCat( + this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG"), + mod_dir); this->AppendFlags(flags, modflag); } @@ -65,8 +66,9 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags( std::vector<std::string> includes; this->GetIncludeDirectories(includes, target, "C", config); for (std::string const& id : includes) { - std::string flg = modpath_flag; - flg += this->ConvertToOutputFormat(id, cmOutputConverter::SHELL); + std::string flg = + cmStrCat(modpath_flag, + this->ConvertToOutputFormat(id, cmOutputConverter::SHELL)); this->AppendFlags(flags, flg); } } diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 3abf2dd..57dabd1 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -21,27 +21,31 @@ #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTestGenerator.h" #include "cmVersion.h" +#include "cm_string_view.hxx" #include "cmake.h" +#include "cmsys/RegularExpression.hxx" -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) # define CM_LG_ENCODE_OBJECT_NAMES # include "cmCryptoHash.h" #endif -#include "cmsys/RegularExpression.hxx" #include <algorithm> #include <assert.h> #include <initializer_list> #include <iterator> +#include <memory> #include <sstream> #include <stdio.h> #include <string.h> #include <unordered_set> #include <utility> +#include <vector> #if defined(__HAIKU__) # include <FindDirectory.h> @@ -280,9 +284,9 @@ void cmLocalGenerator::GenerateTestFiles() const std::string& config = this->Makefile->GetConfigurations(configurationTypes, false); - std::string file = this->StateSnapshot.GetDirectory().GetCurrentBinary(); - file += "/"; - file += "CTestTestfile.cmake"; + std::string file = + cmStrCat(this->StateSnapshot.GetDirectory().GetCurrentBinary(), + "/CTestTestfile.cmake"); cmGeneratedFileStream fout(file); fout.SetCopyIfDifferent(true); @@ -307,8 +311,7 @@ void cmLocalGenerator::GenerateTestFiles() const char* testIncludeFiles = this->Makefile->GetProperty("TEST_INCLUDE_FILES"); if (testIncludeFiles) { - std::vector<std::string> includesList; - cmSystemTools::ExpandListArgument(testIncludeFiles, includesList); + std::vector<std::string> includesList = cmExpandedList(testIncludeFiles); for (std::string const& i : includesList) { fout << "include(\"" << i << "\")" << std::endl; } @@ -742,12 +745,10 @@ std::string cmLocalGenerator::GetIncludeFlags( OutputFormat shellFormat = forResponseFile ? RESPONSE : SHELL; std::ostringstream includeFlags; - std::string flagVar = "CMAKE_INCLUDE_FLAG_"; - flagVar += lang; - std::string const& includeFlag = this->Makefile->GetSafeDefinition(flagVar); - flagVar = "CMAKE_INCLUDE_FLAG_SEP_"; - flagVar += lang; - const char* sep = this->Makefile->GetDefinition(flagVar); + std::string const& includeFlag = + this->Makefile->GetSafeDefinition(cmStrCat("CMAKE_INCLUDE_FLAG_", lang)); + const char* sep = + this->Makefile->GetDefinition(cmStrCat("CMAKE_INCLUDE_FLAG_SEP_", lang)); bool quotePaths = false; if (this->Makefile->GetDefinition("CMAKE_QUOTE_INCLUDE_PATHS")) { quotePaths = true; @@ -764,23 +765,16 @@ std::string cmLocalGenerator::GetIncludeFlags( // Support special system include flag if it is available and the // normal flag is repeated for each directory. - std::string sysFlagVar = "CMAKE_INCLUDE_SYSTEM_FLAG_"; - sysFlagVar += lang; const char* sysIncludeFlag = nullptr; if (repeatFlag) { - sysIncludeFlag = this->Makefile->GetDefinition(sysFlagVar); + sysIncludeFlag = this->Makefile->GetDefinition( + cmStrCat("CMAKE_INCLUDE_SYSTEM_FLAG_", lang)); } - std::string fwSearchFlagVar = "CMAKE_"; - fwSearchFlagVar += lang; - fwSearchFlagVar += "_FRAMEWORK_SEARCH_FLAG"; - const char* fwSearchFlag = this->Makefile->GetDefinition(fwSearchFlagVar); - - std::string sysFwSearchFlagVar = "CMAKE_"; - sysFwSearchFlagVar += lang; - sysFwSearchFlagVar += "_SYSTEM_FRAMEWORK_SEARCH_FLAG"; - const char* sysFwSearchFlag = - this->Makefile->GetDefinition(sysFwSearchFlagVar); + const char* fwSearchFlag = this->Makefile->GetDefinition( + cmStrCat("CMAKE_", lang, "_FRAMEWORK_SEARCH_FLAG")); + const char* sysFwSearchFlag = this->Makefile->GetDefinition( + cmStrCat("CMAKE_", lang, "_SYSTEM_FRAMEWORK_SEARCH_FLAG")); bool flagUsed = false; std::set<std::string> emitted; @@ -790,9 +784,8 @@ std::string cmLocalGenerator::GetIncludeFlags( for (std::string const& i : includes) { if (fwSearchFlag && *fwSearchFlag && this->Makefile->IsOn("APPLE") && cmSystemTools::IsPathToFramework(i)) { - std::string frameworkDir = i; - frameworkDir += "/../"; - frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir); + std::string const frameworkDir = + cmSystemTools::CollapseFullPath(cmStrCat(i, "/../")); if (emitted.insert(frameworkDir).second) { if (sysFwSearchFlag && target && target->IsSystemIncludeDirectory(i, config, lang)) { @@ -907,9 +900,8 @@ void cmLocalGenerator::AddCompileOptions(std::string& flags, std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(jmcExprGen); std::string isJMCEnabled = cge->Evaluate(this, config); - if (cmSystemTools::IsOn(isJMCEnabled)) { - std::vector<std::string> optVec; - cmSystemTools::ExpandListArgument(jmc, optVec); + if (cmIsOn(isJMCEnabled)) { + std::vector<std::string> optVec = cmExpandedList(jmc); this->AppendCompileOptions(flags, optVec); } } @@ -960,11 +952,9 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( // These are intended to simulate additional implicit include directories. std::vector<std::string> userStandardDirs; { - std::string key = "CMAKE_"; - key += lang; - key += "_STANDARD_INCLUDE_DIRECTORIES"; - std::string const value = this->Makefile->GetSafeDefinition(key); - cmSystemTools::ExpandListArgument(value, userStandardDirs); + std::string const value = this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", lang, "_STANDARD_INCLUDE_DIRECTORIES")); + cmExpandList(value, userStandardDirs); for (std::string& usd : userStandardDirs) { cmSystemTools::ConvertToUnixSlashes(usd); } @@ -986,12 +976,11 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( // * Compilers like gfortran do not search their own implicit include // directories for modules ('.mod' files). if (lang != "Fortran") { - std::string key = "CMAKE_"; - key += lang; - key += "_IMPLICIT_INCLUDE_DIRECTORIES"; - if (const char* value = this->Makefile->GetDefinition(key)) { + const char* value = this->Makefile->GetDefinition( + cmStrCat("CMAKE_", lang, "_IMPLICIT_INCLUDE_DIRECTORIES")); + if (value != nullptr) { size_t const impDirVecOldSize = impDirVec.size(); - cmSystemTools::ExpandListArgument(value, impDirVec); + cmExpandList(value, impDirVec); // FIXME: Use cmRange with 'advance()' when it supports non-const. for (size_t i = impDirVecOldSize; i < impDirVec.size(); ++i) { cmSystemTools::ConvertToUnixSlashes(impDirVec[i]); @@ -1006,8 +995,7 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( // directly. In this case adding -I/usr/include can hide SDK headers so we // must still exclude it. if ((lang == "C" || lang == "CXX" || lang == "CUDA") && - std::find(impDirVec.begin(), impDirVec.end(), "/usr/include") == - impDirVec.end() && + !cmContains(impDirVec, "/usr/include") && std::find_if(impDirVec.begin(), impDirVec.end(), [](std::string const& d) { return cmHasLiteralSuffix(d, "/usr/include"); @@ -1017,7 +1005,7 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( } for (std::string const& i : impDirVec) { - if (implicitSet.insert(i).second) { + if (implicitSet.insert(cmSystemTools::GetRealPath(i)).second) { implicitDirs.emplace_back(i); } } @@ -1028,14 +1016,13 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( &lang](std::string const& dir) { return ( // Do not exclude directories that are not in an excluded set. - ((implicitSet.find(dir) == implicitSet.end()) && - (implicitExclude.find(dir) == implicitExclude.end())) + ((!cmContains(implicitSet, cmSystemTools::GetRealPath(dir))) && + (!cmContains(implicitExclude, dir))) // Do not exclude entries of the CPATH environment variable even though // they are implicitly searched by the compiler. They are meant to be // user-specified directories that can be re-ordered or converted to // -isystem without breaking real compiler builtin headers. - || ((lang == "C" || lang == "CXX") && - (this->EnvCPATH.find(dir) != this->EnvCPATH.end()))); + || ((lang == "C" || lang == "CXX") && cmContains(this->EnvCPATH, dir))); }; // Get the target-specific include directories. @@ -1045,8 +1032,8 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( // Support putting all the in-project include directories first if // it is requested by the project. if (this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")) { - std::string const &topSourceDir = this->GetState()->GetSourceDirectory(), - &topBinaryDir = this->GetState()->GetBinaryDirectory(); + std::string const& topSourceDir = this->GetState()->GetSourceDirectory(); + std::string const& topBinaryDir = this->GetState()->GetBinaryDirectory(); for (BT<std::string> const& udr : userDirs) { // Emit this directory only if it is a subdirectory of the // top-level source or binary tree. @@ -1082,7 +1069,7 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( if (!stripImplicitDirs) { // Append implicit directories that were requested by the user only for (BT<std::string> const& udr : userDirs) { - if (implicitSet.find(udr.Value) != implicitSet.end()) { + if (cmContains(implicitSet, cmSystemTools::GetRealPath(udr.Value))) { emitBT(udr); } } @@ -1130,11 +1117,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()) { @@ -1170,12 +1159,10 @@ void cmLocalGenerator::GetTargetFlags( CM_FALLTHROUGH; case cmStateEnums::SHARED_LIBRARY: { if (linkLanguage != "Swift") { - linkFlags = this->Makefile->GetSafeDefinition(libraryLinkVariable); - linkFlags += " "; + linkFlags = cmStrCat( + this->Makefile->GetSafeDefinition(libraryLinkVariable), ' '); if (!buildType.empty()) { - std::string build = libraryLinkVariable; - build += "_"; - build += buildType; + std::string build = cmStrCat(libraryLinkVariable, '_', buildType); linkFlags += this->Makefile->GetSafeDefinition(build); linkFlags += " "; } @@ -1203,9 +1190,8 @@ void cmLocalGenerator::GetTargetFlags( linkFlags += " "; } if (!buildType.empty()) { - std::string configLinkFlags = "LINK_FLAGS_"; - configLinkFlags += buildType; - targetLinkFlags = target->GetProperty(configLinkFlags); + targetLinkFlags = + target->GetProperty(cmStrCat("LINK_FLAGS_", buildType)); if (targetLinkFlags) { linkFlags += targetLinkFlags; linkFlags += " "; @@ -1227,9 +1213,8 @@ void cmLocalGenerator::GetTargetFlags( this->Makefile->GetSafeDefinition("CMAKE_EXE_LINKER_FLAGS"); linkFlags += " "; if (!buildType.empty()) { - std::string build = "CMAKE_EXE_LINKER_FLAGS_"; - build += buildType; - linkFlags += this->Makefile->GetSafeDefinition(build); + linkFlags += this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_EXE_LINKER_FLAGS_", buildType)); linkFlags += " "; } if (linkLanguage.empty()) { @@ -1250,11 +1235,8 @@ void cmLocalGenerator::GetTargetFlags( } if (target->IsExecutableWithExports()) { - std::string exportFlagVar = "CMAKE_EXE_EXPORTS_"; - exportFlagVar += linkLanguage; - exportFlagVar += "_FLAG"; - - linkFlags += this->Makefile->GetSafeDefinition(exportFlagVar); + linkFlags += this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_EXE_EXPORTS_", linkLanguage, "_FLAG")); linkFlags += " "; } } @@ -1265,8 +1247,7 @@ void cmLocalGenerator::GetTargetFlags( frameworkPath, linkPath); } - if (cmSystemTools::IsOn( - this->Makefile->GetDefinition("BUILD_SHARED_LIBS"))) { + if (cmIsOn(this->Makefile->GetDefinition("BUILD_SHARED_LIBS"))) { std::string sFlagVar = std::string("CMAKE_SHARED_BUILD_") + linkLanguage + std::string("_FLAGS"); linkFlags += this->Makefile->GetSafeDefinition(sFlagVar); @@ -1286,9 +1267,8 @@ void cmLocalGenerator::GetTargetFlags( linkFlags += " "; } if (!buildType.empty()) { - std::string configLinkFlags = "LINK_FLAGS_"; - configLinkFlags += buildType; - targetLinkFlags = target->GetProperty(configLinkFlags); + targetLinkFlags = + target->GetProperty(cmStrCat("LINK_FLAGS_", buildType)); if (targetLinkFlags) { linkFlags += targetLinkFlags; linkFlags += " "; @@ -1364,8 +1344,7 @@ static std::string GetFrameworkFlags(const std::string& lang, // will already have added a -F for the framework for (std::string const& include : includes) { if (lg->GetGlobalGenerator()->NameResolvesToFramework(include)) { - std::string frameworkDir = include; - frameworkDir += "/../"; + std::string frameworkDir = cmStrCat(include, "/../"); frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir); emitted.insert(frameworkDir); } @@ -1463,20 +1442,12 @@ void cmLocalGenerator::OutputLinkLibraries( } // Add standard libraries for this language. - std::string standardLibsVar = "CMAKE_"; - standardLibsVar += cli.GetLinkLanguage(); - standardLibsVar += "_STANDARD_LIBRARIES"; - std::string stdLibString; - if (const char* stdLibs = this->Makefile->GetDefinition(standardLibsVar)) { - stdLibString = stdLibs; - } + std::string stdLibString = this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", cli.GetLinkLanguage(), "_STANDARD_LIBRARIES")); // Append the framework search path flags. - std::string fwSearchFlagVar = "CMAKE_"; - fwSearchFlagVar += linkLanguage; - fwSearchFlagVar += "_FRAMEWORK_SEARCH_FLAG"; - std::string fwSearchFlag = - this->Makefile->GetSafeDefinition(fwSearchFlagVar); + std::string fwSearchFlag = this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", linkLanguage, "_FRAMEWORK_SEARCH_FLAG")); frameworkPath = linkLineComputer->ComputeFrameworkPath(cli, fwSearchFlag); linkPath = @@ -1511,8 +1482,10 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065( } CM_FALLTHROUGH; case cmPolicies::OLD: - // OLD behavior is to always add the flags - add_shlib_flags = true; + // OLD behavior is to always add the flags, except on AIX where + // we compute symbol exports if ENABLE_EXPORTS is on. + add_shlib_flags = + !(tgt.Target->IsAIX() && tgt.GetPropertyAsBool("ENABLE_EXPORTS")); break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: @@ -1521,16 +1494,16 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065( cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0065)); CM_FALLTHROUGH; case cmPolicies::NEW: - // NEW behavior is to only add the flags if ENABLE_EXPORTS is on - add_shlib_flags = tgt.GetPropertyAsBool("ENABLE_EXPORTS"); + // NEW behavior is to only add the flags if ENABLE_EXPORTS is on, + // except on AIX where we compute symbol exports. + add_shlib_flags = + !tgt.Target->IsAIX() && tgt.GetPropertyAsBool("ENABLE_EXPORTS"); break; } if (add_shlib_flags) { - std::string linkFlagsVar = "CMAKE_SHARED_LIBRARY_LINK_"; - linkFlagsVar += linkLanguage; - linkFlagsVar += "_FLAGS"; - linkFlags = this->Makefile->GetSafeDefinition(linkFlagsVar); + linkFlags = this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_SHARED_LIBRARY_LINK_", linkLanguage, "_FLAGS")); } } return linkFlags; @@ -1588,10 +1561,8 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, const std::string& config) { // Add language-specific flags. - std::string flagsVar = "CMAKE_"; - flagsVar += lang; - flagsVar += "_FLAGS"; - this->AddConfigVariableFlags(flags, flagsVar, config); + this->AddConfigVariableFlags(flags, cmStrCat("CMAKE_", lang, "_FLAGS"), + config); // Add MSVC runtime library flags. This is activated by the presence // of a default selection whether or not it is overridden by a property. @@ -1749,9 +1720,8 @@ bool cmLocalGenerator::GetRealDependency(const std::string& inName, // Treat the name as relative to the source directory in which it // was given. - dep = this->StateSnapshot.GetDirectory().GetCurrentSource(); - dep += "/"; - dep += inName; + dep = cmStrCat(this->StateSnapshot.GetDirectory().GetCurrentSource(), '/', + inName); return true; } @@ -1762,10 +1732,9 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags, // Add flags for dealing with shared libraries for this language. if (shared) { - flagsVar = "CMAKE_SHARED_LIBRARY_"; - flagsVar += lang; - flagsVar += "_FLAGS"; - this->AppendFlags(flags, this->Makefile->GetDefinition(flagsVar)); + this->AppendFlags(flags, + this->Makefile->GetDefinition( + cmStrCat("CMAKE_SHARED_LIBRARY_", lang, "_FLAGS"))); } } @@ -1784,7 +1753,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag( std::string extProp = lang + "_EXTENSIONS"; bool ext = true; if (const char* extPropValue = target->GetProperty(extProp)) { - if (cmSystemTools::IsOff(extPropValue)) { + if (cmIsOff(extPropValue)) { ext = false; } } @@ -1798,8 +1767,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag( "CMAKE_" + lang + "_EXTENSION_COMPILE_OPTION"; if (const char* opt = target->Target->GetMakefile()->GetDefinition(option_flag)) { - std::vector<std::string> optVec; - cmSystemTools::ExpandListArgument(opt, optVec); + std::vector<std::string> optVec = cmExpandedList(opt); for (std::string const& i : optVec) { this->AppendFlagEscape(flags, i); } @@ -1827,8 +1795,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag( "does not know the compile flags to use to enable it."; this->IssueMessage(MessageType::FATAL_ERROR, e.str()); } else { - std::vector<std::string> optVec; - cmSystemTools::ExpandListArgument(opt, optVec); + std::vector<std::string> optVec = cmExpandedList(opt); for (std::string const& i : optVec) { this->AppendFlagEscape(flags, i); } @@ -1888,8 +1855,7 @@ void cmLocalGenerator::AddCompilerRequirementFlag( std::string const& opt = target->Target->GetMakefile()->GetRequiredDefinition(option_flag); - std::vector<std::string> optVec; - cmSystemTools::ExpandListArgument(opt, optVec); + std::vector<std::string> optVec = cmExpandedList(opt); for (std::string const& i : optVec) { this->AppendFlagEscape(flags, i); } @@ -1901,12 +1867,11 @@ void cmLocalGenerator::AddCompilerRequirementFlag( // for which a flag is defined. for (; stdIt < defaultStdIt; ++stdIt) { std::string option_flag = - "CMAKE_" + lang + *stdIt + "_" + type + "_COMPILE_OPTION"; + cmStrCat("CMAKE_", lang, *stdIt, "_", type, "_COMPILE_OPTION"); if (const char* opt = target->Target->GetMakefile()->GetDefinition(option_flag)) { - std::vector<std::string> optVec; - cmSystemTools::ExpandListArgument(opt, optVec); + std::vector<std::string> optVec = cmExpandedList(opt); for (std::string const& i : optVec) { this->AppendFlagEscape(flags, i); } @@ -2054,9 +2019,7 @@ bool cmLocalGenerator::GetShouldUseOldFlags(bool shared, std::string originalFlags = this->GlobalGenerator->GetSharedLibFlagsForLanguage(lang); if (shared) { - std::string flagsVar = "CMAKE_SHARED_LIBRARY_"; - flagsVar += lang; - flagsVar += "_FLAGS"; + std::string flagsVar = cmStrCat("CMAKE_SHARED_LIBRARY_", lang, "_FLAGS"); std::string const& flags = this->Makefile->GetSafeDefinition(flagsVar); if (flags != originalFlags) { @@ -2095,20 +2058,15 @@ void cmLocalGenerator::AddPositionIndependentFlags(std::string& flags, std::string picFlags; if (targetType == cmStateEnums::EXECUTABLE) { - std::string flagsVar = "CMAKE_"; - flagsVar += lang; - flagsVar += "_COMPILE_OPTIONS_PIE"; - picFlags = this->Makefile->GetSafeDefinition(flagsVar); + picFlags = this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_PIE")); } if (picFlags.empty()) { - std::string flagsVar = "CMAKE_"; - flagsVar += lang; - flagsVar += "_COMPILE_OPTIONS_PIC"; - picFlags = this->Makefile->GetSafeDefinition(flagsVar); + picFlags = this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_PIC")); } if (!picFlags.empty()) { - std::vector<std::string> options; - cmSystemTools::ExpandListArgument(picFlags, options); + std::vector<std::string> options = cmExpandedList(picFlags); for (std::string const& o : options) { this->AppendFlagEscape(flags, o); } @@ -2179,8 +2137,7 @@ void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags, return; } - std::vector<std::string> flagsList; - cmSystemTools::ExpandListArgument(rawFlagsList, flagsList); + std::vector<std::string> flagsList = cmExpandedList(rawFlagsList); for (std::string const& o : flagsList) { this->AppendFlagEscape(flags, o); } @@ -2201,10 +2158,10 @@ void cmLocalGenerator::AppendPositionIndependentLinkerFlags( return; } - const std::string mode = cmSystemTools::IsOn(PICValue) ? "PIE" : "NO_PIE"; + const std::string mode = cmIsOn(PICValue) ? "PIE" : "NO_PIE"; std::string supported = "CMAKE_" + lang + "_LINK_" + mode + "_SUPPORTED"; - if (cmSystemTools::IsOff(this->Makefile->GetDefinition(supported))) { + if (cmIsOff(this->Makefile->GetDefinition(supported))) { return; } @@ -2215,8 +2172,7 @@ void cmLocalGenerator::AppendPositionIndependentLinkerFlags( return; } - std::vector<std::string> flagsList; - cmSystemTools::ExpandListArgument(pieFlags, flagsList); + std::vector<std::string> flagsList = cmExpandedList(pieFlags); for (const auto& flag : flagsList) { this->AppendFlagEscape(flags, flag); } @@ -2232,8 +2188,7 @@ void cmLocalGenerator::AppendCompileOptions(std::string& options, } // Expand the list of options. - std::vector<std::string> options_vec; - cmSystemTools::ExpandListArgument(options_list, options_vec); + std::vector<std::string> options_vec = cmExpandedList(options_list); this->AppendCompileOptions(options, options_vec, regex); } @@ -2267,8 +2222,7 @@ void cmLocalGenerator::AppendIncludeDirectories( } // Expand the list of includes. - std::vector<std::string> includes_vec; - cmSystemTools::ExpandListArgument(includes_list, includes_vec); + std::vector<std::string> includes_vec = cmExpandedList(includes_list); this->AppendIncludeDirectories(includes, includes_vec, sourceFile); } @@ -2293,7 +2247,7 @@ void cmLocalGenerator::AppendIncludeDirectories( std::string inc = include; - if (!cmSystemTools::IsOff(inc)) { + if (!cmIsOff(inc)) { cmSystemTools::ConvertToUnixSlashes(inc); } @@ -2345,10 +2299,8 @@ void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines, // Lookup the define flag for the current language. std::string dflag = "-D"; if (!lang.empty()) { - std::string defineFlagVar = "CMAKE_"; - defineFlagVar += lang; - defineFlagVar += "_DEFINE_FLAG"; - const char* df = this->Makefile->GetDefinition(defineFlagVar); + const char* df = + this->Makefile->GetDefinition(cmStrCat("CMAKE_", lang, "_DEFINE_FLAG")); if (df && *df) { dflag = df; } @@ -2394,13 +2346,10 @@ void cmLocalGenerator::AppendFeatureOptions(std::string& flags, const std::string& lang, const char* feature) { - std::string optVar = "CMAKE_"; - optVar += lang; - optVar += "_COMPILE_OPTIONS_"; - optVar += feature; - if (const char* optionList = this->Makefile->GetDefinition(optVar)) { - std::vector<std::string> options; - cmSystemTools::ExpandListArgument(optionList, options); + const char* optionList = this->Makefile->GetDefinition( + cmStrCat("CMAKE_", lang, "_COMPILE_OPTIONS_", feature)); + if (optionList != nullptr) { + std::vector<std::string> options = cmExpandedList(optionList); for (std::string const& o : options) { this->AppendFlagEscape(flags, o); } @@ -2555,8 +2504,8 @@ static bool cmLocalGeneratorShortenObjectName(std::string& objName, objName.find('/', objName.size() - max_len + 32); if (pos != std::string::npos) { cmCryptoHash md5(cmCryptoHash::AlgoMD5); - std::string md5name = md5.HashString(objName.substr(0, pos)); - md5name += objName.substr(pos); + std::string md5name = cmStrCat(md5.HashString(objName.substr(0, pos)), + cm::string_view(objName).substr(pos)); objName = md5name; // The object name is now short enough. @@ -2751,10 +2700,8 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget( if (!replaceExt) { std::string lang = source.GetLanguage(); if (!lang.empty()) { - std::string repVar = "CMAKE_"; - repVar += lang; - repVar += "_OUTPUT_EXTENSION_REPLACE"; - replaceExt = this->Makefile->IsOn(repVar); + replaceExt = this->Makefile->IsOn( + cmStrCat("CMAKE_", lang, "_OUTPUT_EXTENSION_REPLACE")); } } @@ -2963,7 +2910,7 @@ void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target, // back to the directory-level values set by the user. cmMakefile* mf = this->Makefile; cmMakefile::ScopePushPop varScope(mf); - mf->AddDefinition("MACOSX_BUNDLE_EXECUTABLE_NAME", targetName.c_str()); + mf->AddDefinition("MACOSX_BUNDLE_EXECUTABLE_NAME", targetName); cmLGInfoProp(mf, target, "MACOSX_BUNDLE_INFO_STRING"); cmLGInfoProp(mf, target, "MACOSX_BUNDLE_ICON_FILE"); cmLGInfoProp(mf, target, "MACOSX_BUNDLE_GUI_IDENTIFIER"); @@ -3002,7 +2949,7 @@ void cmLocalGenerator::GenerateFrameworkInfoPList( // back to the directory-level values set by the user. cmMakefile* mf = this->Makefile; cmMakefile::ScopePushPop varScope(mf); - mf->AddDefinition("MACOSX_FRAMEWORK_NAME", targetName.c_str()); + mf->AddDefinition("MACOSX_FRAMEWORK_NAME", targetName); cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_ICON_FILE"); cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_IDENTIFIER"); cmLGInfoProp(mf, target, "MACOSX_FRAMEWORK_SHORT_VERSION_STRING"); diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index f0c6806..455e491 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -461,7 +461,7 @@ private: void ComputeObjectMaxPath(); }; -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) bool cmLocalGeneratorCheckObjectName(std::string& objName, std::string::size_type dir_len, std::string::size_type max_total_len); diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx index bf25f98..b00dda1 100644 --- a/Source/cmLocalGhsMultiGenerator.cxx +++ b/Source/cmLocalGhsMultiGenerator.cxx @@ -7,6 +7,7 @@ #include "cmGlobalGenerator.h" #include "cmSourceFile.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include <algorithm> @@ -23,9 +24,7 @@ cmLocalGhsMultiGenerator::~cmLocalGhsMultiGenerator() = default; std::string cmLocalGhsMultiGenerator::GetTargetDirectory( cmGeneratorTarget const* target) const { - std::string dir; - dir += target->GetName(); - dir += ".dir"; + std::string dir = cmStrCat(target->GetName(), ".dir"); return dir; } @@ -63,11 +62,8 @@ void cmLocalGhsMultiGenerator::ComputeObjectFilenames( std::map<cmSourceFile const*, std::string>& mapping, cmGeneratorTarget const* gt) { - std::string dir_max; - dir_max += this->GetCurrentBinaryDirectory(); - dir_max += "/"; - dir_max += this->GetTargetDirectory(gt); - dir_max += "/"; + std::string dir_max = cmStrCat(this->GetCurrentBinaryDirectory(), '/', + this->GetTargetDirectory(gt), '/'); // Count the number of object files with each name. Note that // filesystem may not be case sensitive. @@ -75,9 +71,10 @@ void cmLocalGhsMultiGenerator::ComputeObjectFilenames( for (auto const& si : mapping) { cmSourceFile const* sf = si.first; - std::string objectNameLower = cmSystemTools::LowerCase( - cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath())); - objectNameLower += this->GlobalGenerator->GetLanguageOutputExtension(*sf); + std::string objectNameLower = cmStrCat( + cmSystemTools::LowerCase( + cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath())), + this->GlobalGenerator->GetLanguageOutputExtension(*sf)); counts[objectNameLower] += 1; } @@ -85,9 +82,9 @@ void cmLocalGhsMultiGenerator::ComputeObjectFilenames( // object name computation. for (auto& si : mapping) { cmSourceFile const* sf = si.first; - std::string objectName = - cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()); - objectName += this->GlobalGenerator->GetLanguageOutputExtension(*sf); + std::string objectName = cmStrCat( + cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()), + this->GlobalGenerator->GetLanguageOutputExtension(*sf)); if (counts[cmSystemTools::LowerCase(objectName)] > 1) { const_cast<cmGeneratorTarget*>(gt)->AddExplicitObjectName(sf); diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 81cafa3..e28b876 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -5,7 +5,7 @@ #include <algorithm> #include <assert.h> #include <iterator> -#include <memory> // IWYU pragma: keep +#include <memory> #include <sstream> #include <stdio.h> #include <utility> @@ -25,6 +25,7 @@ #include "cmSourceFile.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" #include "cmsys/FStream.hxx" @@ -102,8 +103,7 @@ void cmLocalNinjaGenerator::Generate() std::string cmLocalNinjaGenerator::GetTargetDirectory( cmGeneratorTarget const* target) const { - std::string dir = "CMakeFiles/"; - dir += target->GetName(); + std::string dir = cmStrCat("CMakeFiles/", target->GetName()); #if defined(__VMS) dir += "_dir"; #else @@ -221,8 +221,7 @@ void cmLocalNinjaGenerator::WritePools(std::ostream& os) if (jobpools) { cmGlobalNinjaGenerator::WriteComment( os, "Pools defined by global property JOB_POOLS"); - std::vector<std::string> pools; - cmSystemTools::ExpandListArgument(jobpools, pools); + std::vector<std::string> pools = cmExpandedList(jobpools); for (std::string const& pool : pools) { const std::string::size_type eq = pool.find('='); unsigned int jobs; @@ -300,8 +299,7 @@ std::string cmLocalNinjaGenerator::WriteCommandScript( if (target) { scriptPath = target->GetSupportDirectory(); } else { - scriptPath = this->GetCurrentBinaryDirectory(); - scriptPath += "/CMakeFiles"; + scriptPath = cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles"); } cmSystemTools::MakeDirectory(scriptPath); scriptPath += '/'; @@ -555,7 +553,8 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements() ++j; for (; j != i->second.end(); ++j) { - std::vector<std::string> jDeps, depsIntersection; + std::vector<std::string> jDeps; + std::vector<std::string> depsIntersection; this->GetGlobalNinjaGenerator()->AppendTargetDependsClosure(*j, jDeps); std::sort(jDeps.begin(), jDeps.end()); std::set_intersection(ccTargetDeps.begin(), ccTargetDeps.end(), @@ -613,7 +612,7 @@ void cmLocalNinjaGenerator::AdditionalCleanFiles() { cmGeneratorExpression ge; auto cge = ge.Parse(prop_value); - cmSystemTools::ExpandListArgument( + cmExpandList( cge->Evaluate(this, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")), cleanFiles); diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index c392e97..106e506 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -5,11 +5,12 @@ #include "cmsys/FStream.hxx" #include "cmsys/Terminal.h" #include <algorithm> -#include <memory> // IWYU pragma: keep #include <sstream> #include <stdio.h> #include <utility> +#include "cm_memory.hxx" + #include "cmAlgorithms.h" #include "cmCustomCommand.h" // IWYU pragma: keep #include "cmCustomCommandGenerator.h" @@ -31,6 +32,7 @@ #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVersion.h" #include "cmake.h" @@ -38,7 +40,7 @@ // Include dependency scanners for supported languages. Only the // C/C++ scanner is needed for bootstrapping CMake. #include "cmDependsC.h" -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP # include "cmDependsFortran.h" # include "cmDependsJava.h" #endif @@ -162,11 +164,8 @@ void cmLocalUnixMakefileGenerator3::GetLocalObjectFiles( gt->GetObjectSources( objectSources, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); // Compute full path to object file directory for this target. - std::string dir; - dir += gt->LocalGenerator->GetCurrentBinaryDirectory(); - dir += "/"; - dir += this->GetTargetDirectory(gt); - dir += "/"; + std::string dir = cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), + '/', this->GetTargetDirectory(gt), '/'); // Compute the name of each object file. for (cmSourceFile const* sf : objectSources) { bool hasSourceExtension = true; @@ -363,14 +362,12 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets( emitted.insert(target->GetName()); // for subdirs add a rule to build this specific target by name. - localName = this->GetRelativeTargetDirectory(target); - localName += "/rule"; + localName = cmStrCat(this->GetRelativeTargetDirectory(target), "/rule"); commands.clear(); depends.clear(); // Build the target for this pass. - std::string makefile2 = "CMakeFiles/"; - makefile2 += "Makefile2"; + std::string makefile2 = "CMakeFiles/Makefile2"; commands.push_back(this->GetRecursiveMakeCall(makefile2, localName)); this->CreateCDCommand(commands, this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory()); @@ -386,13 +383,12 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets( } // Add a fast rule to build the target - std::string makefileName = this->GetRelativeTargetDirectory(target); - makefileName += "/build.make"; + std::string makefileName = + cmStrCat(this->GetRelativeTargetDirectory(target), "/build.make"); // make sure the makefile name is suitable for a makefile - std::string makeTargetName = this->GetRelativeTargetDirectory(target); - makeTargetName += "/build"; - localName = target->GetName(); - localName += "/fast"; + std::string makeTargetName = + cmStrCat(this->GetRelativeTargetDirectory(target), "/build"); + localName = cmStrCat(target->GetName(), "/fast"); depends.clear(); commands.clear(); commands.push_back( @@ -405,10 +401,9 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets( // Add a local name for the rule to relink the target before // installation. if (target->NeedRelinkBeforeInstall(this->ConfigName)) { - makeTargetName = this->GetRelativeTargetDirectory(target); - makeTargetName += "/preinstall"; - localName = target->GetName(); - localName += "/preinstall"; + makeTargetName = + cmStrCat(this->GetRelativeTargetDirectory(target), "/preinstall"); + localName = cmStrCat(target->GetName(), "/preinstall"); depends.clear(); commands.clear(); commands.push_back( @@ -425,9 +420,9 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets( void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile() { - std::string infoFileName = this->GetCurrentBinaryDirectory(); - infoFileName += "/CMakeFiles"; - infoFileName += "/CMakeDirectoryInformation.cmake"; + std::string infoFileName = + cmStrCat(this->GetCurrentBinaryDirectory(), + "/CMakeFiles/CMakeDirectoryInformation.cmake"); // Open the output file. cmGeneratedFileStream infoFileStream(infoFileName); @@ -483,9 +478,8 @@ void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile() std::string cmLocalUnixMakefileGenerator3::ConvertToFullPath( const std::string& localPath) { - std::string dir = this->GetCurrentBinaryDirectory(); - dir += "/"; - dir += localPath; + std::string dir = + cmStrCat(this->GetCurrentBinaryDirectory(), '/', localPath); return dir; } @@ -766,19 +760,18 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsBottom( std::vector<std::string> commands; cmake* cm = this->GlobalGenerator->GetCMakeInstance(); if (cm->DoWriteGlobVerifyTarget()) { - std::string rescanRule = "$(CMAKE_COMMAND) -P "; - rescanRule += this->ConvertToOutputFormat(cm->GetGlobVerifyScript(), - cmOutputConverter::SHELL); + std::string rescanRule = + cmStrCat("$(CMAKE_COMMAND) -P ", + this->ConvertToOutputFormat(cm->GetGlobVerifyScript(), + cmOutputConverter::SHELL)); commands.push_back(rescanRule); } - std::string cmakefileName = "CMakeFiles/"; - cmakefileName += "Makefile.cmake"; - std::string runRule = - "$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)"; - runRule += " --check-build-system "; - runRule += - this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL); - runRule += " 0"; + std::string cmakefileName = "CMakeFiles/Makefile.cmake"; + std::string runRule = cmStrCat( + "$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) " + "--check-build-system ", + this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL), + " 0"); std::vector<std::string> no_depends; commands.push_back(std::move(runRule)); @@ -819,8 +812,8 @@ void cmLocalUnixMakefileGenerator3::WriteConvenienceRule( std::string cmLocalUnixMakefileGenerator3::GetRelativeTargetDirectory( cmGeneratorTarget* target) { - std::string dir = this->HomeRelativeOutputPath; - dir += this->GetTargetDirectory(target); + std::string dir = + cmStrCat(this->HomeRelativeOutputPath, this->GetTargetDirectory(target)); return dir; } @@ -851,7 +844,7 @@ void cmLocalUnixMakefileGenerator3::AppendRuleDepend( // it is specifically enabled by the user or project. const char* nodep = this->Makefile->GetDefinition("CMAKE_SKIP_RULE_DEPENDENCY"); - if (!nodep || cmSystemTools::IsOff(nodep)) { + if (!nodep || cmIsOff(nodep)) { depends.emplace_back(ruleFileName); } } @@ -961,7 +954,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( // This command was specified as a path to a file in the // current directory. Add a leading "./" so it can run // without the current directory being in the search path. - cmd = "./" + cmd; + cmd = cmStrCat("./", cmd); } std::string launcher; @@ -1015,18 +1008,16 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( std::string::size_type rcurly = cmd.find('}'); if (rcurly == std::string::npos || rcurly > lcurly) { // The first curly is a left curly. Use the hack. - std::string hack_cmd = cmd.substr(0, lcurly); - hack_cmd += "{{}"; - hack_cmd += cmd.substr(lcurly + 1); - cmd = hack_cmd; + cmd = + cmStrCat(cmd.substr(0, lcurly), "{{}", cmd.substr(lcurly + 1)); } } } if (launcher.empty()) { if (useCall) { - cmd = "call " + cmd; + cmd = cmStrCat("call ", cmd); } else if (this->IsNMake() && cmd[0] == '"') { - cmd = "echo >nul && " + cmd; + cmd = cmStrCat("echo >nul && ", cmd); } } commands1.push_back(std::move(cmd)); @@ -1045,10 +1036,8 @@ void cmLocalUnixMakefileGenerator3::AppendCleanCommand( cmGeneratorTarget* target, const char* filename) { std::string currentBinDir = this->GetCurrentBinaryDirectory(); - std::string cleanfile = currentBinDir; - cleanfile += "/"; - cleanfile += this->GetTargetDirectory(target); - cleanfile += "/cmake_clean"; + std::string cleanfile = cmStrCat( + currentBinDir, '/', this->GetTargetDirectory(target), "/cmake_clean"); if (filename) { cleanfile += "_"; cleanfile += filename; @@ -1068,11 +1057,12 @@ void cmLocalUnixMakefileGenerator3::AppendCleanCommand( fout << ")\n"; } { - std::string remove = "$(CMAKE_COMMAND) -P "; - remove += this->ConvertToOutputFormat( - this->MaybeConvertToRelativePath(this->GetCurrentBinaryDirectory(), - cleanfile), - cmOutputConverter::SHELL); + std::string remove = + cmStrCat("$(CMAKE_COMMAND) -P ", + this->ConvertToOutputFormat( + this->MaybeConvertToRelativePath( + this->GetCurrentBinaryDirectory(), cleanfile), + cmOutputConverter::SHELL)); commands.push_back(std::move(remove)); } @@ -1102,7 +1092,7 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand( this->Makefile->GetProperty("ADDITIONAL_CLEAN_FILES")) { cmGeneratorExpression ge; std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop_value); - cmSystemTools::ExpandListArgument( + cmExpandList( cge->Evaluate(this, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")), cleanFiles); @@ -1115,8 +1105,8 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand( this->GetGlobalGenerator()->GetLocalGenerators().at(0); std::string const& binaryDir = rootLG->GetCurrentBinaryDirectory(); std::string const& currentBinaryDir = this->GetCurrentBinaryDirectory(); - std::string cleanfile = currentBinaryDir; - cleanfile += "/CMakeFiles/cmake_directory_clean.cmake"; + std::string cleanfile = + cmStrCat(currentBinaryDir, "/CMakeFiles/cmake_directory_clean.cmake"); // Write clean script { std::string cleanfilePath = cmSystemTools::CollapseFullPath(cleanfile); @@ -1135,10 +1125,11 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand( } // Create command { - std::string remove = "$(CMAKE_COMMAND) -P "; - remove += this->ConvertToOutputFormat( - rootLG->MaybeConvertToRelativePath(binaryDir, cleanfile), - cmOutputConverter::SHELL); + std::string remove = + cmStrCat("$(CMAKE_COMMAND) -P ", + this->ConvertToOutputFormat( + rootLG->MaybeConvertToRelativePath(binaryDir, cleanfile), + cmOutputConverter::SHELL)); commands.push_back(std::move(remove)); } } @@ -1184,12 +1175,12 @@ void cmLocalUnixMakefileGenerator3::AppendEcho( std::string cmd; if (color_name.empty() && !progress) { // Use the native echo command. - cmd = "@echo "; - cmd += this->EscapeForShell(line, false, true); + cmd = cmStrCat("@echo ", this->EscapeForShell(line, false, true)); } else { // Use cmake to echo the text in color. - cmd = "@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) "; - cmd += color_name; + cmd = cmStrCat( + "@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) ", + color_name); if (progress) { cmd += "--progress-dir="; cmd += this->ConvertToOutputFormat( @@ -1225,8 +1216,7 @@ void cmLocalUnixMakefileGenerator3::AppendEcho( std::string cmLocalUnixMakefileGenerator3::CreateMakeVariable( std::string const& s, std::string const& s2) { - std::string unmodified = s; - unmodified += s2; + std::string unmodified = cmStrCat(s, s2); // if there is no restriction on the length of make variables // and there are no "." characters in the string, then return the // unmodified combination. @@ -1344,9 +1334,9 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies( // may have changed. In this case discard all old dependencies. bool needRescanDirInfo = false; { - std::string dirInfoFile = this->GetCurrentBinaryDirectory(); - dirInfoFile += "/CMakeFiles"; - dirInfoFile += "/CMakeDirectoryInformation.cmake"; + std::string dirInfoFile = + cmStrCat(this->GetCurrentBinaryDirectory(), + "/CMakeFiles/CMakeDirectoryInformation.cmake"); int result; if (!ftc->Compare(internalDependFile, dirInfoFile, &result) || result < 0) { @@ -1388,8 +1378,8 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies( // The dependencies must be regenerated. std::string targetName = cmSystemTools::GetFilenameName(targetDir); targetName = targetName.substr(0, targetName.length() - 4); - std::string message = "Scanning dependencies of target "; - message += targetName; + std::string message = + cmStrCat("Scanning dependencies of target ", targetName); cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta | cmsysTerminal_Color_ForegroundBold, message.c_str(), true, color); @@ -1410,9 +1400,9 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( cmMakefile* mf = this->Makefile; bool haveDirectoryInfo = false; { - std::string dirInfoFile = this->GetCurrentBinaryDirectory(); - dirInfoFile += "/CMakeFiles"; - dirInfoFile += "/CMakeDirectoryInformation.cmake"; + std::string dirInfoFile = + cmStrCat(this->GetCurrentBinaryDirectory(), + "/CMakeFiles/CMakeDirectoryInformation.cmake"); if (mf->ReadListFile(dirInfoFile) && !cmSystemTools::GetErrorOccuredFlag()) { haveDirectoryInfo = true; @@ -1423,7 +1413,7 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( if (haveDirectoryInfo) { // Test whether we need to force Unix paths. if (const char* force = mf->GetDefinition("CMAKE_FORCE_UNIX_PATHS")) { - if (!cmSystemTools::IsOff(force)) { + if (!cmIsOff(force)) { cmSystemTools::SetForceUnixPaths(true); } } @@ -1465,9 +1455,8 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( this->WriteDisclaimer(internalRuleFileStream); // for each language we need to scan, scan it - std::vector<std::string> langs; - cmSystemTools::ExpandListArgument( - mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES"), langs); + std::vector<std::string> langs = + cmExpandedList(mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES")); for (std::string const& lang : langs) { // construct the checker // Create the scanner for this language @@ -1477,7 +1466,7 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( // TODO: Handle RC (resource files) dependencies correctly. scanner = cm::make_unique<cmDependsC>(this, targetDir, lang, &validDeps); } -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP else if (lang == "Fortran") { ruleFileStream << "# Note that incremental build could trigger " << "a call to cmake_copy_f90_mod on each re-build\n"; @@ -1511,8 +1500,7 @@ void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose) } // Convert the string to a list and preserve empty entries. - std::vector<std::string> pairs; - cmSystemTools::ExpandListArgument(pairs_string, pairs, true); + std::vector<std::string> pairs = cmExpandedList(pairs_string, true); for (std::vector<std::string>::const_iterator i = pairs.begin(); i != pairs.end() && (i + 1) != pairs.end();) { const std::string& depender = *i++; @@ -1625,8 +1613,8 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( std::vector<std::string> commands; // Write the all rule. - std::string recursiveTarget = this->GetCurrentBinaryDirectory(); - recursiveTarget += "/all"; + std::string recursiveTarget = + cmStrCat(this->GetCurrentBinaryDirectory(), "/all"); bool regenerate = !this->GlobalGenerator->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION"); @@ -1634,16 +1622,15 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( depends.emplace_back("cmake_check_build_system"); } - std::string progressDir = this->GetBinaryDirectory(); - progressDir += "/CMakeFiles"; + std::string progressDir = + cmStrCat(this->GetBinaryDirectory(), "/CMakeFiles"); { std::ostringstream progCmd; progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start "; progCmd << this->ConvertToOutputFormat( cmSystemTools::CollapseFullPath(progressDir), cmOutputConverter::SHELL); - std::string progressFile = "/CMakeFiles"; - progressFile += "/progress.marks"; + std::string progressFile = "/CMakeFiles/progress.marks"; std::string progressFileNameFull = this->ConvertToFullPath(progressFile); progCmd << " " << this->ConvertToOutputFormat( @@ -1651,8 +1638,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( cmOutputConverter::SHELL); commands.push_back(progCmd.str()); } - std::string mf2Dir = "CMakeFiles/"; - mf2Dir += "Makefile2"; + std::string mf2Dir = "CMakeFiles/Makefile2"; commands.push_back(this->GetRecursiveMakeCall(mf2Dir, recursiveTarget)); this->CreateCDCommand(commands, this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory()); @@ -1668,8 +1654,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( commands, true); // Write the clean rule. - recursiveTarget = this->GetCurrentBinaryDirectory(); - recursiveTarget += "/clean"; + recursiveTarget = cmStrCat(this->GetCurrentBinaryDirectory(), "/clean"); commands.clear(); depends.clear(); commands.push_back(this->GetRecursiveMakeCall(mf2Dir, recursiveTarget)); @@ -1684,13 +1669,12 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( depends, commands, true); // Write the preinstall rule. - recursiveTarget = this->GetCurrentBinaryDirectory(); - recursiveTarget += "/preinstall"; + recursiveTarget = cmStrCat(this->GetCurrentBinaryDirectory(), "/preinstall"); commands.clear(); depends.clear(); const char* noall = this->Makefile->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY"); - if (!noall || cmSystemTools::IsOff(noall)) { + if (!noall || cmIsOff(noall)) { // Drive the build before installing. depends.emplace_back("all"); } else if (regenerate) { @@ -1712,20 +1696,19 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( commands.clear(); cmake* cm = this->GlobalGenerator->GetCMakeInstance(); if (cm->DoWriteGlobVerifyTarget()) { - std::string rescanRule = "$(CMAKE_COMMAND) -P "; - rescanRule += this->ConvertToOutputFormat(cm->GetGlobVerifyScript(), - cmOutputConverter::SHELL); + std::string rescanRule = + cmStrCat("$(CMAKE_COMMAND) -P ", + this->ConvertToOutputFormat(cm->GetGlobVerifyScript(), + cmOutputConverter::SHELL)); commands.push_back(rescanRule); } - std::string cmakefileName = "CMakeFiles/"; - cmakefileName += "Makefile.cmake"; + std::string cmakefileName = "CMakeFiles/Makefile.cmake"; { - std::string runRule = - "$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)"; - runRule += " --check-build-system "; - runRule += - this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL); - runRule += " 1"; + std::string runRule = cmStrCat( + "$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) " + "--check-build-system ", + this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL), + " 1"); commands.push_back(std::move(runRule)); } this->CreateCDCommand(commands, this->GetBinaryDirectory(), @@ -1743,8 +1726,7 @@ void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf, if (!infoDef) { return; } - std::vector<std::string> files; - cmSystemTools::ExpandListArgument(infoDef, files); + std::vector<std::string> files = cmExpandedList(infoDef); // Each depend information file corresponds to a target. Clear the // dependencies for that target. @@ -1846,9 +1828,8 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( cmakefileStream << " )\n"; // Tell the dependency scanner what compiler is used. - std::string cidVar = "CMAKE_"; - cidVar += implicitLang.first; - cidVar += "_COMPILER_ID"; + std::string cidVar = + cmStrCat("CMAKE_", implicitLang.first, "_COMPILER_ID"); const char* cid = this->Makefile->GetDefinition(cidVar); if (cid && *cid) { cmakefileStream << "set(CMAKE_" << implicitLang.first @@ -1912,11 +1893,11 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( std::vector<std::string> transformRules; if (const char* xform = this->Makefile->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) { - cmSystemTools::ExpandListArgument(xform, transformRules); + cmExpandList(xform, transformRules); } if (const char* xform = target->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) { - cmSystemTools::ExpandListArgument(xform, transformRules); + cmExpandList(xform, transformRules); } if (!transformRules.empty()) { cmakefileStream << "set(CMAKE_INCLUDE_TRANSFORMS\n"; @@ -1939,10 +1920,9 @@ std::string cmLocalUnixMakefileGenerator3::GetRecursiveMakeCall( const std::string& makefile, const std::string& tgt) { // Call make on the given file. - std::string cmd; - cmd += "$(MAKE) -f "; - cmd += this->ConvertToOutputFormat(makefile, cmOutputConverter::SHELL); - cmd += " "; + std::string cmd = cmStrCat( + "$(MAKE) -f ", + this->ConvertToOutputFormat(makefile, cmOutputConverter::SHELL), ' '); cmGlobalUnixMakefileGenerator3* gg = static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator); @@ -2073,8 +2053,7 @@ std::string cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath( std::string cmLocalUnixMakefileGenerator3::GetTargetDirectory( cmGeneratorTarget const* target) const { - std::string dir = "CMakeFiles/"; - dir += target->GetName(); + std::string dir = cmStrCat("CMakeFiles/", target->GetName()); #if defined(__VMS) dir += "_dir"; #else @@ -2117,13 +2096,12 @@ void cmLocalUnixMakefileGenerator3::CreateCDCommand( // On Windows we must perform each step separately and then change // back because the shell keeps the working directory between // commands. - std::string cmd = cd_cmd; - cmd += this->ConvertToOutputForExisting(tgtDir); + std::string cmd = + cmStrCat(cd_cmd, this->ConvertToOutputForExisting(tgtDir)); commands.insert(commands.begin(), cmd); // Change back to the starting directory. - cmd = cd_cmd; - cmd += this->ConvertToOutputForExisting(relDir); + cmd = cmStrCat(cd_cmd, this->ConvertToOutputForExisting(relDir)); commands.push_back(std::move(cmd)); } else { // On UNIX we must construct a single shell command to change diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx index d45c335..6d7b359 100644 --- a/Source/cmLocalVisualStudio10Generator.cxx +++ b/Source/cmLocalVisualStudio10Generator.cxx @@ -121,8 +121,7 @@ void cmLocalVisualStudio10Generator::ReadAndStoreExternalGUID( return; } - std::string guidStoreName = name; - guidStoreName += "_GUID_CMAKE"; + std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE"); // save the GUID in the cache this->GlobalGenerator->GetCMakeInstance()->AddCacheEntry( guidStoreName.c_str(), parser.GUID.c_str(), "Stored GUID", diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 8154f3e..2c91974 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -97,11 +97,8 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets() cmCustomCommandLines force_commands; force_commands.push_back(force_command); std::string no_main_dependency; - std::string force = this->GetCurrentBinaryDirectory(); - force += "/CMakeFiles"; - force += "/"; - force += l->GetName(); - force += "_force"; + std::string force = cmStrCat(this->GetCurrentBinaryDirectory(), + "/CMakeFiles/", l->GetName(), "_force"); if (cmSourceFile* file = this->Makefile->AddCustomCommandToOutput( force.c_str(), no_depends, no_main_dependency, force_commands, " ", 0, true)) { @@ -144,11 +141,10 @@ void cmLocalVisualStudio7Generator::WriteStampFiles() { // Touch a timestamp file used to determine when the project file is // out of date. - std::string stampName = this->GetCurrentBinaryDirectory(); - stampName += "/CMakeFiles"; + std::string stampName = + cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles"); cmSystemTools::MakeDirectory(stampName.c_str()); - stampName += "/"; - stampName += "generate.stamp"; + stampName += "/generate.stamp"; cmsys::ofstream stamp(stampName.c_str()); stamp << "# CMake generation timestamp file for this directory.\n"; @@ -158,8 +154,7 @@ void cmLocalVisualStudio7Generator::WriteStampFiles() // dependencies. If any file listed in it is newer than itself then // CMake must rerun. Otherwise the project files are up to date and // the stamp file can just be touched. - std::string depName = stampName; - depName += ".depend"; + std::string depName = cmStrCat(stampName, ".depend"); cmsys::ofstream depFile(depName.c_str()); depFile << "# CMake generation dependency list for this directory.\n"; @@ -199,9 +194,7 @@ void cmLocalVisualStudio7Generator::CreateSingleVCProj( target->Target->SetProperty("GENERATOR_FILE_NAME", lname.c_str()); // create the dsp.cmake file std::string fname; - fname = this->GetCurrentBinaryDirectory(); - fname += "/"; - fname += lname; + fname = cmStrCat(this->GetCurrentBinaryDirectory(), '/', lname); if (this->FortranProject) { fname += ".vfproj"; } else { @@ -228,9 +221,8 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() return nullptr; } - std::string makefileIn = this->GetCurrentSourceDirectory(); - makefileIn += "/"; - makefileIn += "CMakeLists.txt"; + std::string makefileIn = + cmStrCat(this->GetCurrentSourceDirectory(), "/CMakeLists.txt"); makefileIn = cmSystemTools::CollapseFullPath(makefileIn); if (cmSourceFile* file = this->Makefile->GetSource(makefileIn)) { if (file->GetCustomCommand()) { @@ -253,20 +245,15 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() std::unique(listFiles.begin(), listFiles.end()); listFiles.erase(new_end, listFiles.end()); - std::string stampName = this->GetCurrentBinaryDirectory(); - stampName += "/"; - stampName += "CMakeFiles/"; - stampName += "generate.stamp"; + std::string stampName = + cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/generate.stamp"); cmCustomCommandLine commandLine; commandLine.push_back(cmSystemTools::GetCMakeCommand()); - std::string comment = "Building Custom Rule "; - comment += makefileIn; + std::string comment = cmStrCat("Building Custom Rule ", makefileIn); std::string args; - args = "-S"; - args += this->GetSourceDirectory(); + args = cmStrCat("-S", this->GetSourceDirectory()); commandLine.push_back(args); - args = "-B"; - args += this->GetBinaryDirectory(); + args = cmStrCat("-B", this->GetBinaryDirectory()); commandLine.push_back(args); commandLine.push_back("--check-stamp-file"); commandLine.push_back(stampName); @@ -721,9 +708,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE")); // Add a definition for the configuration name. - std::string configDefine = "CMAKE_INTDIR=\""; - configDefine += configName; - configDefine += "\""; + std::string configDefine = cmStrCat("CMAKE_INTDIR=\"", configName, '"'); targetOptions.AddDefine(configDefine); // Add the export symbol definition for shared library objects. @@ -733,9 +718,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( // The intermediate directory name consists of a directory for the // target and a subdirectory for the configuration name. - std::string intermediateDir = this->GetTargetDirectory(target); - intermediateDir += "/"; - intermediateDir += configName; + std::string intermediateDir = + cmStrCat(this->GetTargetDirectory(target), '/', configName); if (target->GetType() < cmStateEnums::UTILITY) { std::string const& outDir = @@ -956,8 +940,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( extraLinkOptions += targetLinkFlags; } std::string configTypeUpper = cmSystemTools::UpperCase(configName); - std::string linkFlagsConfig = "LINK_FLAGS_"; - linkFlagsConfig += configTypeUpper; + std::string linkFlagsConfig = cmStrCat("LINK_FLAGS_", configTypeUpper); targetLinkFlags = target->GetProperty(linkFlagsConfig.c_str()); if (targetLinkFlags) { extraLinkOptions += " "; @@ -989,12 +972,9 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( case cmStateEnums::UNKNOWN_LIBRARY: break; case cmStateEnums::OBJECT_LIBRARY: { - std::string libpath = this->GetTargetDirectory(target); - libpath += "/"; - libpath += configName; - libpath += "/"; - libpath += target->GetName(); - libpath += ".lib"; + std::string libpath = + cmStrCat(this->GetTargetDirectory(target), '/', configName, '/', + target->GetName(), ".lib"); const char* tool = this->FortranProject ? "VFLibrarianTool" : "VCLibrarianTool"; fout << "\t\t\t<Tool\n" @@ -1005,9 +985,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( } case cmStateEnums::STATIC_LIBRARY: { std::string targetNameFull = target->GetFullName(configName); - std::string libpath = target->GetDirectory(configName); - libpath += "/"; - libpath += targetNameFull; + std::string libpath = + cmStrCat(target->GetDirectory(configName), '/', targetNameFull); const char* tool = "VCLibrarianTool"; if (this->FortranProject) { tool = "VFLibrarianTool"; @@ -1049,9 +1028,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( // Compute the variable name to lookup standard libraries for this // language. - std::string standardLibsVar = "CMAKE_"; - standardLibsVar += linkLanguage; - standardLibsVar += "_STANDARD_LIBRARIES"; + std::string standardLibsVar = + cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LIBRARIES"); const char* tool = "VCLinkerTool"; if (this->FortranProject) { tool = "VFLinkerTool"; @@ -1071,9 +1049,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( fout << " "; this->Internal->OutputLibraries(fout, cli.GetItems()); fout << "\"\n"; - temp = target->GetDirectory(configName); - temp += "/"; - temp += targetNames.Output; + temp = + cmStrCat(target->GetDirectory(configName), '/', targetNames.Output); fout << "\t\t\t\tOutputFile=\"" << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n"; this->WriteTargetVersionAttribute(fout, target); @@ -1081,9 +1058,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( fout << "\t\t\t\tAdditionalLibraryDirectories=\""; this->OutputLibraryDirectories(fout, cli.GetDirectories()); fout << "\"\n"; - temp = target->GetPDBDirectory(configName); - temp += "/"; - temp += targetNames.PDB; + temp = + cmStrCat(target->GetPDBDirectory(configName), '/', targetNames.PDB); fout << "\t\t\t\tProgramDatabaseFile=\"" << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n"; if (targetOptions.IsDebug()) { @@ -1096,17 +1072,14 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( fout << "\t\t\t\tSubSystem=\"8\"\n"; } } - std::string stackVar = "CMAKE_"; - stackVar += linkLanguage; - stackVar += "_STACK_SIZE"; + std::string stackVar = cmStrCat("CMAKE_", linkLanguage, "_STACK_SIZE"); const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str()); if (stackVal) { fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\"\n"; } - temp = - target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact); - temp += "/"; - temp += targetNames.ImportLibrary; + temp = cmStrCat( + target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact), + '/', targetNames.ImportLibrary); fout << "\t\t\t\tImportLibrary=\"" << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\""; if (this->FortranProject) { @@ -1130,9 +1103,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( // Compute the variable name to lookup standard libraries for this // language. - std::string standardLibsVar = "CMAKE_"; - standardLibsVar += linkLanguage; - standardLibsVar += "_STANDARD_LIBRARIES"; + std::string standardLibsVar = + cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LIBRARIES"); const char* tool = "VCLinkerTool"; if (this->FortranProject) { tool = "VFLinkerTool"; @@ -1152,9 +1124,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( fout << " "; this->Internal->OutputLibraries(fout, cli.GetItems()); fout << "\"\n"; - temp = target->GetDirectory(configName); - temp += "/"; - temp += targetNames.Output; + temp = + cmStrCat(target->GetDirectory(configName), '/', targetNames.Output); fout << "\t\t\t\tOutputFile=\"" << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n"; this->WriteTargetVersionAttribute(fout, target); @@ -1190,17 +1161,14 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( fout << "\t\t\t\tSubSystem=\"" << (isWin32Executable ? "2" : "1") << "\"\n"; } - std::string stackVar = "CMAKE_"; - stackVar += linkLanguage; - stackVar += "_STACK_SIZE"; + std::string stackVar = cmStrCat("CMAKE_", linkLanguage, "_STACK_SIZE"); const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str()); if (stackVal) { fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\""; } - temp = - target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact); - temp += "/"; - temp += targetNames.ImportLibrary; + temp = cmStrCat( + target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact), + '/', targetNames.ImportLibrary); fout << "\t\t\t\tImportLibrary=\"" << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"/>\n"; break; @@ -1509,8 +1477,7 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( fc.CompileDefs = genexInterpreter.Evaluate(cdefs, COMPILE_DEFINITIONS); needfc = true; } - std::string defPropName = "COMPILE_DEFINITIONS_"; - defPropName += configUpper; + std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper); if (const char* ccdefs = sf.GetProperty(defPropName)) { fc.CompileDefsConfig = genexInterpreter.Evaluate(ccdefs, COMPILE_DEFINITIONS); @@ -1525,8 +1492,7 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( // Check for extra object-file dependencies. if (const char* deps = sf.GetProperty("OBJECT_DEPENDS")) { - std::vector<std::string> depends; - cmSystemTools::ExpandListArgument(deps, depends); + std::vector<std::string> depends = cmExpandedList(deps); const char* sep = ""; for (std::vector<std::string>::iterator j = depends.begin(); j != depends.end(); ++j) { @@ -1540,9 +1506,8 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( const std::string& linkLanguage = gt->GetLinkerLanguage(config.c_str()); // If HEADER_FILE_ONLY is set, we must suppress this generation in // the project file - fc.ExcludedFromBuild = sf.GetPropertyAsBool("HEADER_FILE_ONLY") || - std::find(acs.Configs.begin(), acs.Configs.end(), ci) == - acs.Configs.end(); + fc.ExcludedFromBuild = + sf.GetPropertyAsBool("HEADER_FILE_ONLY") || !cmContains(acs.Configs, ci); if (fc.ExcludedFromBuild) { needfc = true; } @@ -1586,13 +1551,9 @@ std::string cmLocalVisualStudio7Generator::ComputeLongestObjectDirectory( // Compute the maximum length full path to the intermediate // files directory for any configuration. This is used to construct // object file names that do not produce paths that are too long. - std::string dir_max; - dir_max += this->GetCurrentBinaryDirectory(); - dir_max += "/"; - dir_max += this->GetTargetDirectory(target); - dir_max += "/"; - dir_max += config_max; - dir_max += "/"; + std::string dir_max = + cmStrCat(this->GetCurrentBinaryDirectory(), '/', + this->GetTargetDirectory(target), '/', config_max, '/'); return dir_max; } @@ -2142,8 +2103,7 @@ void cmLocalVisualStudio7Generator::ReadAndStoreExternalGUID( if (parser.GUID.empty()) { return; } - std::string guidStoreName = name; - guidStoreName += "_GUID_CMAKE"; + std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE"); // save the GUID in the cache this->GlobalGenerator->GetCMakeInstance()->AddCacheEntry( guidStoreName.c_str(), parser.GUID.c_str(), "Stored GUID", @@ -2153,9 +2113,7 @@ void cmLocalVisualStudio7Generator::ReadAndStoreExternalGUID( std::string cmLocalVisualStudio7Generator::GetTargetDirectory( cmGeneratorTarget const* target) const { - std::string dir; - dir += target->GetName(); - dir += ".dir"; + std::string dir = cmStrCat(target->GetName(), ".dir"); return dir; } diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h index 3fdafd2..585eb3c 100644 --- a/Source/cmLocalVisualStudioGenerator.h +++ b/Source/cmLocalVisualStudioGenerator.h @@ -6,7 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <map> -#include <memory> // IWYU pragma: keep +#include <memory> #include <string> #include "cmGlobalVisualStudioGenerator.h" diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx index 9c36627..5a06d4a 100644 --- a/Source/cmLocalXCodeGenerator.cxx +++ b/Source/cmLocalXCodeGenerator.cxx @@ -65,9 +65,8 @@ void cmLocalXCodeGenerator::ComputeObjectFilenames( std::map<std::string, int> counts; for (auto& si : mapping) { cmSourceFile const* sf = si.first; - std::string objectName = - cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()); - objectName += ".o"; + std::string objectName = cmStrCat( + cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()), ".o"); std::string objectNameLower = cmSystemTools::LowerCase(objectName); counts[objectNameLower] += 1; diff --git a/Source/cmMachO.cxx b/Source/cmMachO.cxx index d4af1e0..bec3ad8 100644 --- a/Source/cmMachO.cxx +++ b/Source/cmMachO.cxx @@ -2,12 +2,15 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMachO.h" +#include "cmAlgorithms.h" #include "cmsys/FStream.hxx" -#include <algorithm> -#include <stddef.h> + +#include <cstddef> #include <string> #include <vector> +#include "cm_memory.hxx" + // Include the Mach-O format information system header. #include <mach-o/fat.h> #include <mach-o/loader.h> @@ -120,7 +123,7 @@ protected: // Implementation for reading Mach-O header and load commands. // This is 32 or 64 bit arch specific. -template <class T> +template <typename T> class cmMachOHeaderAndLoadCommandsImpl : public cmMachOHeaderAndLoadCommands { public: @@ -306,15 +309,11 @@ bool cmMachOInternal::read_mach_o(uint32_t file_offset) // External class implementation. cmMachO::cmMachO(const char* fname) - : Internal(nullptr) + : Internal(cm::make_unique<cmMachOInternal>(fname)) { - this->Internal = new cmMachOInternal(fname); } -cmMachO::~cmMachO() -{ - delete this->Internal; -} +cmMachO::~cmMachO() = default; std::string const& cmMachO::GetErrorMessage() const { diff --git a/Source/cmMachO.h b/Source/cmMachO.h index 5482465..0c44b55 100644 --- a/Source/cmMachO.h +++ b/Source/cmMachO.h @@ -41,7 +41,7 @@ public: private: friend class cmMachOInternal; bool Valid() const; - cmMachOInternal* Internal; + std::unique_ptr<cmMachOInternal> Internal; }; #endif diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index e9c6aea..201cc13 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -2,48 +2,36 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMacroCommand.h" -#include <sstream> #include <stdio.h> #include <utility> +#include "cm_memory.hxx" +#include "cm_static_string_view.hxx" +#include "cm_string_view.hxx" + #include "cmAlgorithms.h" #include "cmExecutionStatus.h" +#include "cmFunctionBlocker.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmPolicies.h" #include "cmRange.h" #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" +namespace { + // define the class for macro commands -class cmMacroHelperCommand : public cmCommand +class cmMacroHelperCommand { public: /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override - { - cmMacroHelperCommand* newC = new cmMacroHelperCommand; - // we must copy when we clone - newC->Args = this->Args; - newC->Functions = this->Functions; - newC->FilePath = this->FilePath; - newC->Policies = this->Policies; - return newC; - } - - /** * This is called when the command is first encountered in * the CMakeLists.txt file. */ - bool InvokeInitialPass(const std::vector<cmListFileArgument>& args, - cmExecutionStatus&) override; - - bool InitialPass(std::vector<std::string> const&, - cmExecutionStatus&) override - { - return false; - } + bool operator()(std::vector<cmListFileArgument> const& args, + cmExecutionStatus& inStatus) const; std::vector<std::string> Args; std::vector<cmListFileFunction> Functions; @@ -51,30 +39,31 @@ public: std::string FilePath; }; -bool cmMacroHelperCommand::InvokeInitialPass( - const std::vector<cmListFileArgument>& args, cmExecutionStatus& inStatus) +bool cmMacroHelperCommand::operator()( + std::vector<cmListFileArgument> const& args, + cmExecutionStatus& inStatus) const { + cmMakefile& makefile = inStatus.GetMakefile(); + // Expand the argument list to the macro. std::vector<std::string> expandedArgs; - this->Makefile->ExpandArguments(args, expandedArgs); + makefile.ExpandArguments(args, expandedArgs); // make sure the number of arguments passed is at least the number // required by the signature if (expandedArgs.size() < this->Args.size() - 1) { std::string errorMsg = - "Macro invoked with incorrect arguments for macro named: "; - errorMsg += this->Args[0]; - this->SetError(errorMsg); + cmStrCat("Macro invoked with incorrect arguments for macro named: ", + this->Args[0]); + inStatus.SetError(errorMsg); return false; } - cmMakefile::MacroPushPop macroScope(this->Makefile, this->FilePath, + cmMakefile::MacroPushPop macroScope(&makefile, this->FilePath, this->Policies); // set the value of argc - std::ostringstream argcDefStream; - argcDefStream << expandedArgs.size(); - std::string argcDef = argcDefStream.str(); + std::string argcDef = std::to_string(expandedArgs.size()); std::vector<std::string>::const_iterator eit = expandedArgs.begin() + (this->Args.size() - 1); @@ -130,9 +119,8 @@ bool cmMacroHelperCommand::InvokeInitialPass( arg.Line = k.Line; newLFF.Arguments.push_back(std::move(arg)); } - cmExecutionStatus status; - if (!this->Makefile->ExecuteCommand(newLFF, status) || - status.GetNestedError()) { + cmExecutionStatus status(makefile); + if (!makefile.ExecuteCommand(newLFF, status) || status.GetNestedError()) { // The error message should have already included the call stack // so we do not need to report an error here. macroScope.Quiet(); @@ -151,68 +139,59 @@ bool cmMacroHelperCommand::InvokeInitialPass( return true; } -bool cmMacroFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, - cmMakefile& mf, - cmExecutionStatus&) +class cmMacroFunctionBlocker : public cmFunctionBlocker { - // record commands until we hit the ENDMACRO - // at the ENDMACRO call we shift gears and start looking for invocations - if (lff.Name.Lower == "macro") { - this->Depth++; - } else if (lff.Name.Lower == "endmacro") { - // if this is the endmacro for this macro then execute - if (!this->Depth) { - mf.AppendProperty("MACROS", this->Args[0].c_str()); - // create a new command and add it to cmake - cmMacroHelperCommand* f = new cmMacroHelperCommand(); - f->Args = this->Args; - f->Functions = this->Functions; - f->FilePath = this->GetStartingContext().FilePath; - mf.RecordPolicies(f->Policies); - mf.GetState()->AddScriptedCommand(this->Args[0], f); - // remove the function blocker now that the macro is defined - mf.RemoveFunctionBlocker(this, lff); - return true; - } - // decrement for each nested macro that ends - this->Depth--; - } +public: + cm::string_view StartCommandName() const override { return "macro"_s; } + cm::string_view EndCommandName() const override { return "endmacro"_s; } - // if it wasn't an endmacro and we are not executing then we must be - // recording - this->Functions.push_back(lff); - return true; -} + bool ArgumentsMatch(cmListFileFunction const&, + cmMakefile& mf) const override; + + bool Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& status) override; + + std::vector<std::string> Args; +}; -bool cmMacroFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, - cmMakefile& mf) +bool cmMacroFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile& mf) const { - if (lff.Name.Lower == "endmacro") { - std::vector<std::string> expandedArguments; - mf.ExpandArguments(lff.Arguments, expandedArguments, - this->GetStartingContext().FilePath.c_str()); - // if the endmacro has arguments make sure they - // match the arguments of the macro - if ((expandedArguments.empty() || - (expandedArguments[0] == this->Args[0]))) { - return true; - } - } + std::vector<std::string> expandedArguments; + mf.ExpandArguments(lff.Arguments, expandedArguments, + this->GetStartingContext().FilePath.c_str()); + return expandedArguments.empty() || expandedArguments[0] == this->Args[0]; +} - return false; +bool cmMacroFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& status) +{ + cmMakefile& mf = status.GetMakefile(); + mf.AppendProperty("MACROS", this->Args[0].c_str()); + // create a new command and add it to cmake + cmMacroHelperCommand f; + f.Args = this->Args; + f.Functions = std::move(functions); + f.FilePath = this->GetStartingContext().FilePath; + mf.RecordPolicies(f.Policies); + mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f)); + return true; +} } -bool cmMacroCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmMacroCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } // create a function blocker - cmMacroFunctionBlocker* f = new cmMacroFunctionBlocker(); - cmAppend(f->Args, args); - this->Makefile->AddFunctionBlocker(f); + { + auto fb = cm::make_unique<cmMacroFunctionBlocker>(); + cmAppend(fb->Args, args); + status.GetMakefile().AddFunctionBlocker(std::move(fb)); + } return true; } diff --git a/Source/cmMacroCommand.h b/Source/cmMacroCommand.h index b54ed66..25091ea 100644 --- a/Source/cmMacroCommand.h +++ b/Source/cmMacroCommand.h @@ -8,40 +8,10 @@ #include <string> #include <vector> -#include "cmCommand.h" -#include "cmFunctionBlocker.h" -#include "cmListFileCache.h" - class cmExecutionStatus; -class cmMakefile; - -class cmMacroFunctionBlocker : public cmFunctionBlocker -{ -public: - bool IsFunctionBlocked(const cmListFileFunction&, cmMakefile& mf, - cmExecutionStatus&) override; - bool ShouldRemove(const cmListFileFunction&, cmMakefile& mf) override; - - std::vector<std::string> Args; - std::vector<cmListFileFunction> Functions; - int Depth = 0; -}; /// Starts macro() ... endmacro() block -class cmMacroCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmMacroCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmMacroCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmMakeDirectoryCommand.cxx b/Source/cmMakeDirectoryCommand.cxx index aff4ca6..cdde6f9 100644 --- a/Source/cmMakeDirectoryCommand.cxx +++ b/Source/cmMakeDirectoryCommand.cxx @@ -2,23 +2,22 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMakeDirectoryCommand.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmSystemTools.h" -class cmExecutionStatus; - // cmMakeDirectoryCommand -bool cmMakeDirectoryCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmMakeDirectoryCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 1) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } - if (!this->Makefile->CanIWriteThisFile(args[0])) { + if (!status.GetMakefile().CanIWriteThisFile(args[0])) { std::string e = "attempted to create a directory: " + args[0] + " into a source directory."; - this->SetError(e); + status.SetError(e); cmSystemTools::SetFatalErrorOccured(); return false; } diff --git a/Source/cmMakeDirectoryCommand.h b/Source/cmMakeDirectoryCommand.h index d2637f3..2474383 100644 --- a/Source/cmMakeDirectoryCommand.h +++ b/Source/cmMakeDirectoryCommand.h @@ -8,11 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmMakeDirectoryCommand +/** * \brief Specify auxiliary source code directories. * * cmMakeDirectoryCommand specifies source code directories @@ -21,20 +19,7 @@ class cmExecutionStatus; * A side effect of this command is to create a subdirectory in the build * directory structure. */ -class cmMakeDirectoryCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmMakeDirectoryCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmMakeDirectoryCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index e0f69cb..f101cdc 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -9,14 +9,13 @@ #include <cstring> #include <ctype.h> #include <iterator> -#include <memory> // IWYU pragma: keep +#include <memory> #include <sstream> #include <stdio.h> #include <stdlib.h> #include <utility> #include "cmAlgorithms.h" -#include "cmCommand.h" #include "cmCommandArgumentParserHelper.h" #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" @@ -24,6 +23,7 @@ #include "cmExpandedCommandArgument.h" // IWYU pragma: keep #include "cmFileLockPool.h" #include "cmFunctionBlocker.h" +#include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionEvaluationFile.h" #include "cmGlobalGenerator.h" @@ -48,7 +48,7 @@ #include "cmConfigure.h" // IWYU pragma: keep -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP # include "cmVariableWatch.h" #endif @@ -98,7 +98,7 @@ cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator, // cmListFileCache in the top level if necessary. this->CheckCMP0000 = false; -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) this->AddSourceGroup("", "^.*$"); this->AddSourceGroup("Source Files", CM_SOURCE_REGEX); this->AddSourceGroup("Header Files", CM_HEADER_REGEX); @@ -118,8 +118,6 @@ cmMakefile::~cmMakefile() cmDeleteAll(this->SourceFiles); cmDeleteAll(this->Tests); cmDeleteAll(this->ImportedTargetsOwned); - cmDeleteAll(this->FinalPassCommands); - cmDeleteAll(this->FunctionBlockers); cmDeleteAll(this->EvaluationFiles); } @@ -324,7 +322,13 @@ void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const msg << " "; } msg << ")"; - cmSystemTools::Message(msg.str()); + + auto& f = this->GetCMakeInstance()->GetTraceFile(); + if (f) { + f << msg.str() << '\n'; + } else { + cmSystemTools::Message(msg.str()); + } } // Helper class to make sure the call stack is valid. @@ -356,6 +360,11 @@ private: cmMakefile* Makefile; }; +void cmMakefile::OnExecuteCommand(std::function<void()> callback) +{ + this->ExecuteCommandCallback = std::move(callback); +} + bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, cmExecutionStatus& status) { @@ -367,6 +376,10 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, return result; } + if (this->ExecuteCommandCallback) { + this->ExecuteCommandCallback(); + } + // Place this call on the call stack. cmMakefileCall stack_manager(this, lff, status); static_cast<void>(stack_manager); @@ -390,12 +403,8 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, } // Lookup the command prototype. - if (cmCommand* proto = + if (cmState::Command command = this->GetState()->GetCommandByExactName(lff.Name.Lower)) { - // Clone the prototype. - std::unique_ptr<cmCommand> pcmd(proto->Clone()); - pcmd->SetMakefile(this); - // Decide whether to invoke the command. if (!cmSystemTools::GetFatalErrorOccured()) { // if trace is enabled, print out invoke information @@ -403,29 +412,25 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, this->PrintCommandTrace(lff); } // Try invoking the command. - bool invokeSucceeded = pcmd->InvokeInitialPass(lff.Arguments, status); + bool invokeSucceeded = command(lff.Arguments, status); bool hadNestedError = status.GetNestedError(); if (!invokeSucceeded || hadNestedError) { if (!hadNestedError) { // The command invocation requested that we report an error. std::string const error = - std::string(lff.Name.Original) + " " + pcmd->GetError(); + std::string(lff.Name.Original) + " " + status.GetError(); this->IssueMessage(MessageType::FATAL_ERROR, error); } result = false; if (this->GetCMakeInstance()->GetWorkingMode() != cmake::NORMAL_MODE) { cmSystemTools::SetFatalErrorOccured(); } - } else if (pcmd->HasFinalPass()) { - // use the command - this->FinalPassCommands.push_back(pcmd.release()); } } } else { if (!cmSystemTools::GetFatalErrorOccured()) { - std::string error = "Unknown CMake command \""; - error += lff.Name.Original; - error += "\"."; + std::string error = + cmStrCat("Unknown CMake command \"", lff.Name.Original, "\"."); this->IssueMessage(MessageType::FATAL_ERROR, error); result = false; cmSystemTools::SetFatalErrorOccured(); @@ -567,8 +572,9 @@ void cmMakefile::IncludeScope::EnforceCMP0011() bool cmMakefile::ReadDependentFile(const std::string& filename, bool noPolicyScope) { - this->AddDefinition("CMAKE_PARENT_LIST_FILE", - this->GetDefinition("CMAKE_CURRENT_LIST_FILE")); + if (const char* def = this->GetDefinition("CMAKE_CURRENT_LIST_FILE")) { + this->AddDefinition("CMAKE_PARENT_LIST_FILE", def); + } std::string filenametoread = cmSystemTools::CollapseFullPath( filename, this->GetCurrentSourceDirectory()); @@ -651,9 +657,9 @@ void cmMakefile::ReadListFile(cmListFile const& listFile, this->GetSafeDefinition("CMAKE_PARENT_LIST_FILE"); std::string currentFile = this->GetSafeDefinition("CMAKE_CURRENT_LIST_FILE"); - this->AddDefinition("CMAKE_CURRENT_LIST_FILE", filenametoread.c_str()); + this->AddDefinition("CMAKE_CURRENT_LIST_FILE", filenametoread); this->AddDefinition("CMAKE_CURRENT_LIST_DIR", - cmSystemTools::GetFilenamePath(filenametoread).c_str()); + cmSystemTools::GetFilenamePath(filenametoread)); this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE"); this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE"); @@ -662,7 +668,7 @@ void cmMakefile::ReadListFile(cmListFile const& listFile, // Run the parsed commands. const size_t numberFunctions = listFile.Functions.size(); for (size_t i = 0; i < numberFunctions; ++i) { - cmExecutionStatus status; + cmExecutionStatus status(*this); this->ExecuteCommand(listFile.Functions[i], status); if (cmSystemTools::GetFatalErrorOccured()) { break; @@ -674,10 +680,10 @@ void cmMakefile::ReadListFile(cmListFile const& listFile, } this->CheckForUnusedVariables(); - this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile.c_str()); - this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile.c_str()); + this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile); + this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile); this->AddDefinition("CMAKE_CURRENT_LIST_DIR", - cmSystemTools::GetFilenamePath(currentFile).c_str()); + cmSystemTools::GetFilenamePath(currentFile)); this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE"); this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE"); this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR"); @@ -769,6 +775,11 @@ struct file_not_persistent }; } +void cmMakefile::AddFinalAction(FinalAction action) +{ + this->FinalActions.push_back(std::move(action)); +} + void cmMakefile::FinalPass() { // do all the variable expansions here @@ -776,8 +787,8 @@ void cmMakefile::FinalPass() // give all the commands a chance to do something // after the file has been parsed before generation - for (cmCommand* fpCommand : this->FinalPassCommands) { - fpCommand->FinalPass(); + for (FinalAction& action : this->FinalActions) { + action(*this); } // go through all configured files and see which ones still exist. @@ -1176,10 +1187,8 @@ cmTarget* cmMakefile::AddUtilityCommand( // Store the custom command in the target. if (!commandLines.empty() || !depends.empty()) { - std::string force = this->GetCurrentBinaryDirectory(); - force += "/CMakeFiles"; - force += "/"; - force += utilityName; + std::string force = + cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/", utilityName); std::vector<std::string> forced; forced.push_back(force); std::string no_main_dependency; @@ -1343,8 +1352,7 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove) if (remove) { if (const char* cdefs = this->GetProperty("COMPILE_DEFINITIONS")) { // Expand the list. - std::vector<std::string> defs; - cmSystemTools::ExpandListArgument(cdefs, defs); + std::vector<std::string> defs = cmExpandedList(cdefs); // Recompose the list without the definition. std::vector<std::string>::const_iterator defEnd = @@ -1385,8 +1393,8 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent) std::vector<std::string> configs; this->GetConfigurations(configs); for (std::string const& config : configs) { - std::string defPropName = "COMPILE_DEFINITIONS_"; - defPropName += cmSystemTools::UpperCase(config); + std::string defPropName = + cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config)); const char* prop = parent->GetProperty(defPropName); this->SetProperty(defPropName, prop); } @@ -1420,7 +1428,7 @@ void cmMakefile::PushFunctionScope(std::string const& fileName, this->PushLoopBlockBarrier(); -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) this->GetGlobalGenerator()->GetFileLockPool().PushFunctionScope(); #endif @@ -1437,7 +1445,7 @@ void cmMakefile::PopFunctionScope(bool reportError) this->PopFunctionBlockerBarrier(reportError); -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) this->GetGlobalGenerator()->GetFileLockPool().PopFunctionScope(); #endif @@ -1479,8 +1487,8 @@ public: , ReportError(true) { std::string currentStart = - this->Makefile->StateSnapshot.GetDirectory().GetCurrentSource(); - currentStart += "/CMakeLists.txt"; + cmStrCat(this->Makefile->StateSnapshot.GetDirectory().GetCurrentSource(), + "/CMakeLists.txt"); this->Makefile->StateSnapshot.SetListFile(currentStart); this->Makefile->StateSnapshot = this->Makefile->StateSnapshot.GetState()->CreatePolicyScopeSnapshot( @@ -1492,7 +1500,7 @@ public: this->Snapshot = this->GG->GetCMakeInstance()->GetCurrentSnapshot(); this->GG->GetCMakeInstance()->SetCurrentSnapshot(this->Snapshot); this->GG->SetCurrentMakefile(mf); -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) this->GG->GetFileLockPool().PushFileScope(); #endif } @@ -1501,7 +1509,7 @@ public: { this->Makefile->PopFunctionBlockerBarrier(this->ReportError); this->Makefile->PopSnapshot(this->ReportError); -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) this->GG->GetFileLockPool().PopFileScope(); #endif this->GG->SetCurrentMakefile(this->CurrentMakefile); @@ -1523,9 +1531,8 @@ private: void cmMakefile::Configure() { - std::string currentStart = - this->StateSnapshot.GetDirectory().GetCurrentSource(); - currentStart += "/CMakeLists.txt"; + std::string currentStart = cmStrCat( + this->StateSnapshot.GetDirectory().GetCurrentSource(), "/CMakeLists.txt"); // Add the bottom of all backtraces within this directory. // We will never pop this scope because it should be available @@ -1535,12 +1542,12 @@ void cmMakefile::Configure() BuildsystemFileScope scope(this); // make sure the CMakeFiles dir is there - std::string filesDir = this->StateSnapshot.GetDirectory().GetCurrentBinary(); - filesDir += "/CMakeFiles"; + std::string filesDir = cmStrCat( + this->StateSnapshot.GetDirectory().GetCurrentBinary(), "/CMakeFiles"); cmSystemTools::MakeDirectory(filesDir); assert(cmSystemTools::FileExists(currentStart, true)); - this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentStart.c_str()); + this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentStart); cmListFile listFile; if (!listFile.ParseFile(currentStart.c_str(), this->GetMessenger(), @@ -1578,7 +1585,7 @@ void cmMakefile::Configure() allowedCommands.insert("message"); isProblem = false; for (cmListFileFunction const& func : listFile.Functions) { - if (allowedCommands.find(func.Name.Lower) == allowedCommands.end()) { + if (!cmContains(allowedCommands, func.Name.Lower)) { isProblem = true; break; } @@ -1647,8 +1654,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf) mf->InitializeFromParent(this); std::string currentStart = mf->GetCurrentSourceDirectory(); if (this->GetCMakeInstance()->GetDebugOutput()) { - std::string msg = " Entering "; - msg += currentStart; + std::string msg = cmStrCat(" Entering ", currentStart); cmSystemTools::Message(msg); } @@ -1690,8 +1696,8 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf) mf->Configure(); if (this->GetCMakeInstance()->GetDebugOutput()) { - std::string msg = " Returning to "; - msg += this->GetCurrentSourceDirectory(); + std::string msg = + cmStrCat(" Returning to ", this->GetCurrentSourceDirectory()); cmSystemTools::Message(msg); } } @@ -1788,26 +1794,27 @@ void cmMakefile::AddSystemIncludeDirectories(const std::set<std::string>& incs) } } -void cmMakefile::AddDefinition(const std::string& name, const char* value) +void cmMakefile::AddDefinition(const std::string& name, cm::string_view value) { - if (!value) { - return; - } - if (this->VariableInitialized(name)) { this->LogUnused("changing definition", name); } this->StateSnapshot.SetDefinition(name, value); -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP cmVariableWatch* vv = this->GetVariableWatch(); if (vv) { vv->VariableAccessed(name, cmVariableWatch::VARIABLE_MODIFIED_ACCESS, - value, this); + value.data(), this); } #endif } +void cmMakefile::AddDefinitionBool(const std::string& name, bool value) +{ + this->AddDefinition(name, value ? "ON" : "OFF"); +} + void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, const char* doc, cmStateEnums::CacheEntryType type, @@ -1831,10 +1838,10 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, std::vector<std::string> files; nvalue = value ? value : ""; - cmSystemTools::ExpandListArgument(nvalue, files); + cmExpandList(nvalue, files); nvalue.clear(); for (cc = 0; cc < files.size(); cc++) { - if (!cmSystemTools::IsOff(files[cc])) { + if (!cmIsOff(files[cc])) { files[cc] = cmSystemTools::CollapseFullPath(files[cc]); } if (cc > 0) { @@ -1853,23 +1860,6 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, this->StateSnapshot.RemoveDefinition(name); } -void cmMakefile::AddDefinition(const std::string& name, bool value) -{ - if (this->VariableInitialized(name)) { - this->LogUnused("changing definition", name); - } - - this->StateSnapshot.SetDefinition(name, value ? "ON" : "OFF"); - -#ifdef CMAKE_BUILD_WITH_CMAKE - cmVariableWatch* vv = this->GetVariableWatch(); - if (vv) { - vv->VariableAccessed(name, cmVariableWatch::VARIABLE_MODIFIED_ACCESS, - value ? "ON" : "OFF", this); - } -#endif -} - void cmMakefile::CheckForUnusedVariables() const { if (!this->WarnUnused) { @@ -1914,8 +1904,7 @@ void cmMakefile::LogUnused(const char* reason, const std::string& name) const if (!this->ExecutionStatusStack.empty()) { path = this->GetExecutionContext().FilePath; } else { - path = this->GetCurrentSourceDirectory(); - path += "/CMakeLists.txt"; + path = cmStrCat(this->GetCurrentSourceDirectory(), "/CMakeLists.txt"); } if (this->CheckSystemVars || this->IsProjectFile(path.c_str())) { @@ -1932,7 +1921,7 @@ void cmMakefile::RemoveDefinition(const std::string& name) this->LogUnused("unsetting", name); } this->StateSnapshot.RemoveDefinition(name); -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP cmVariableWatch* vv = this->GetVariableWatch(); if (vv) { vv->VariableAccessed(name, cmVariableWatch::VARIABLE_REMOVED_ACCESS, @@ -1963,8 +1952,7 @@ void cmMakefile::AddGlobalLinkInformation(cmTarget& target) } if (const char* linkLibsProp = this->GetProperty("LINK_LIBRARIES")) { - std::vector<std::string> linkLibs; - cmSystemTools::ExpandListArgument(linkLibsProp, linkLibs); + std::vector<std::string> linkLibs = cmExpandedList(linkLibsProp); for (std::vector<std::string>::iterator j = linkLibs.begin(); j != linkLibs.end(); ++j) { @@ -2090,7 +2078,7 @@ cmSourceFile* cmMakefile::GetSourceFileWithOutput( return nullptr; } -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) cmSourceGroup* cmMakefile::GetSourceGroup( const std::vector<std::string>& name) const { @@ -2186,8 +2174,7 @@ cmSourceGroup* cmMakefile::GetOrCreateSourceGroup(const std::string& name) if (delimiter == nullptr) { delimiter = "\\"; } - return this->GetOrCreateSourceGroup( - cmSystemTools::tokenize(name, delimiter)); + return this->GetOrCreateSourceGroup(cmTokenize(name, delimiter)); } /** @@ -2292,8 +2279,7 @@ void cmMakefile::ExpandVariablesCMP0019() } if (const char* linkLibsProp = this->GetProperty("LINK_LIBRARIES")) { - std::vector<std::string> linkLibs; - cmSystemTools::ExpandListArgument(linkLibsProp, linkLibs); + std::vector<std::string> linkLibs = cmExpandedList(linkLibsProp); for (std::vector<std::string>::iterator l = linkLibs.begin(); l != linkLibs.end(); ++l) { @@ -2336,7 +2322,7 @@ void cmMakefile::ExpandVariablesCMP0019() bool cmMakefile::IsOn(const std::string& name) const { const char* value = this->GetDefinition(name); - return cmSystemTools::IsOn(value); + return cmIsOn(value); } bool cmMakefile::IsSet(const std::string& name) const @@ -2350,7 +2336,7 @@ bool cmMakefile::IsSet(const std::string& name) const return false; } - if (cmSystemTools::IsNOTFOUND(value)) { + if (cmIsNOTFOUND(value)) { return false; } @@ -2472,7 +2458,7 @@ bool cmMakefile::IsDefinitionSet(const std::string& name) const if (!def) { def = this->GetState()->GetInitializedCacheValue(name); } -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP if (cmVariableWatch* vv = this->GetVariableWatch()) { if (!def) { vv->VariableAccessed( @@ -2489,7 +2475,7 @@ const std::string* cmMakefile::GetDef(const std::string& name) const if (!def) { def = this->GetState()->GetInitializedCacheValue(name); } -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP cmVariableWatch* vv = this->GetVariableWatch(); if (vv && !this->SuppressSideEffects) { bool const watch_function_executed = @@ -2608,8 +2594,8 @@ const std::string& cmMakefile::ExpandVariablesInString( } // ...otherwise, see if there's a difference that needs to be warned about. else if (compareResults && (newResult != source || newError != mtype)) { - std::string msg = cmPolicies::GetPolicyWarning(cmPolicies::CMP0053); - msg += "\n"; + std::string msg = + cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0053), '\n'); std::string msg_input = original; cmSystemTools::ReplaceString(msg_input, "\n", "\n "); @@ -2679,7 +2665,7 @@ MessageType cmMakefile::ExpandVariablesInStringOld( if (const char* val = this->GetDefinition(var)) { // Store the value in the output escaping as requested. if (escapeQuotes) { - source.append(cmSystemTools::EscapeQuotes(val)); + source.append(cmEscapeQuotes(val)); } else { source.append(val); } @@ -2824,9 +2810,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew( switch (var.domain) { case NORMAL: if (filename && lookup == lineVar) { - std::ostringstream ostr; - ostr << line; - varresult = ostr.str(); + varresult = std::to_string(line); } else { value = this->GetDefinition(lookup); } @@ -2843,7 +2827,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew( // Get the string we're meant to append to. if (value) { if (escapeQuotes) { - varresult = cmSystemTools::EscapeQuotes(value); + varresult = cmEscapeQuotes(value); } else { varresult = value; } @@ -2969,7 +2953,7 @@ MessageType cmMakefile::ExpandVariablesInStringNew( } if (escapeQuotes) { - varresult = cmSystemTools::EscapeQuotes(varresult); + varresult = cmEscapeQuotes(varresult); } // Skip over the variable. result.append(last, in - last); @@ -3062,7 +3046,7 @@ std::string cmMakefile::GetConfigurations(std::vector<std::string>& configs, if (this->GetGlobalGenerator()->IsMultiConfig()) { if (const char* configTypes = this->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { - cmSystemTools::ExpandListArgument(configTypes, configs); + cmExpandList(configTypes, configs); } return ""; } @@ -3077,19 +3061,11 @@ bool cmMakefile::IsFunctionBlocked(const cmListFileFunction& lff, cmExecutionStatus& status) { // if there are no blockers get out of here - if (this->FunctionBlockers.begin() == this->FunctionBlockers.end()) { + if (this->FunctionBlockers.empty()) { return false; } - // loop over all function blockers to see if any block this command - // evaluate in reverse, this is critical for balanced IF statements etc - for (cmFunctionBlocker* pos : cmReverseRange(this->FunctionBlockers)) { - if (pos->IsFunctionBlocked(lff, *this, status)) { - return true; - } - } - - return false; + return this->FunctionBlockers.top()->IsFunctionBlocked(lff, status); } void cmMakefile::PushFunctionBlockerBarrier() @@ -3103,8 +3079,9 @@ void cmMakefile::PopFunctionBlockerBarrier(bool reportError) FunctionBlockersType::size_type barrier = this->FunctionBlockerBarriers.back(); while (this->FunctionBlockers.size() > barrier) { - std::unique_ptr<cmFunctionBlocker> fb(this->FunctionBlockers.back()); - this->FunctionBlockers.pop_back(); + std::unique_ptr<cmFunctionBlocker> fb( + std::move(this->FunctionBlockers.top())); + this->FunctionBlockers.pop(); if (reportError) { // Report the context in which the unclosed block was opened. cmListFileContext const& lfc = fb->GetStartingContext(); @@ -3186,7 +3163,7 @@ bool cmMakefile::ExpandArguments(std::vector<cmListFileArgument> const& inArgs, if (i.Delim == cmListFileArgument::Quoted) { outArgs.push_back(value); } else { - cmSystemTools::ExpandListArgument(value, outArgs); + cmExpandList(value, outArgs); } } return !cmSystemTools::GetFatalErrorOccured(); @@ -3218,8 +3195,7 @@ bool cmMakefile::ExpandArguments( if (i.Delim == cmListFileArgument::Quoted) { outArgs.emplace_back(value, true); } else { - std::vector<std::string> stringArgs; - cmSystemTools::ExpandListArgument(value, stringArgs); + std::vector<std::string> stringArgs = cmExpandedList(value); for (std::string const& stringArg : stringArgs) { outArgs.emplace_back(stringArg, false); } @@ -3228,54 +3204,25 @@ bool cmMakefile::ExpandArguments( return !cmSystemTools::GetFatalErrorOccured(); } -void cmMakefile::AddFunctionBlocker(cmFunctionBlocker* fb) +void cmMakefile::AddFunctionBlocker(std::unique_ptr<cmFunctionBlocker> fb) { if (!this->ExecutionStatusStack.empty()) { // Record the context in which the blocker is created. fb->SetStartingContext(this->GetExecutionContext()); } - this->FunctionBlockers.push_back(fb); + this->FunctionBlockers.push(std::move(fb)); } -std::unique_ptr<cmFunctionBlocker> cmMakefile::RemoveFunctionBlocker( - cmFunctionBlocker* fb, const cmListFileFunction& lff) +std::unique_ptr<cmFunctionBlocker> cmMakefile::RemoveFunctionBlocker() { - // Find the function blocker stack barrier for the current scope. - // We only remove a blocker whose index is not less than the barrier. - FunctionBlockersType::size_type barrier = 0; - if (!this->FunctionBlockerBarriers.empty()) { - barrier = this->FunctionBlockerBarriers.back(); - } + assert(!this->FunctionBlockers.empty()); + assert(this->FunctionBlockerBarriers.empty() || + this->FunctionBlockers.size() > this->FunctionBlockerBarriers.back()); - // Search for the function blocker whose scope this command ends. - for (FunctionBlockersType::size_type i = this->FunctionBlockers.size(); - i > barrier; --i) { - std::vector<cmFunctionBlocker*>::iterator pos = - this->FunctionBlockers.begin() + (i - 1); - if (*pos == fb) { - // Warn if the arguments do not match, but always remove. - if (!(*pos)->ShouldRemove(lff, *this)) { - cmListFileContext const& lfc = fb->GetStartingContext(); - cmListFileContext closingContext = - cmListFileContext::FromCommandContext(lff, lfc.FilePath); - std::ostringstream e; - /* clang-format off */ - e << "A logical block opening on the line\n" - << " " << lfc << "\n" - << "closes on the line\n" - << " " << closingContext << "\n" - << "with mis-matching arguments."; - /* clang-format on */ - this->IssueMessage(MessageType::AUTHOR_WARNING, e.str()); - } - cmFunctionBlocker* b = *pos; - this->FunctionBlockers.erase(pos); - return std::unique_ptr<cmFunctionBlocker>(b); - } - } - - return std::unique_ptr<cmFunctionBlocker>(); + auto b = std::move(this->FunctionBlockers.top()); + this->FunctionBlockers.pop(); + return b; } std::string const& cmMakefile::GetHomeDirectory() const @@ -3290,20 +3237,18 @@ std::string const& cmMakefile::GetHomeOutputDirectory() const void cmMakefile::SetScriptModeFile(std::string const& scriptfile) { - this->AddDefinition("CMAKE_SCRIPT_MODE_FILE", scriptfile.c_str()); + this->AddDefinition("CMAKE_SCRIPT_MODE_FILE", scriptfile); } void cmMakefile::SetArgcArgv(const std::vector<std::string>& args) { - std::ostringstream strStream; - strStream << args.size(); - this->AddDefinition("CMAKE_ARGC", strStream.str().c_str()); + this->AddDefinition("CMAKE_ARGC", std::to_string(args.size())); // this->MarkVariableAsUsed("CMAKE_ARGC"); for (unsigned int t = 0; t < args.size(); ++t) { std::ostringstream tmpStream; tmpStream << "CMAKE_ARGV" << t; - this->AddDefinition(tmpStream.str(), args[t].c_str()); + this->AddDefinition(tmpStream.str(), args[t]); // this->MarkVariableAsUsed(tmpStream.str().c_str()); } } @@ -3375,7 +3320,7 @@ void cmMakefile::AddTargetObject(std::string const& tgtName, cmSourceFile* sf = this->GetOrCreateSource(objFile, true); sf->SetObjectLibrary(tgtName); sf->SetProperty("EXTERNAL_OBJECT", "1"); -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) this->SourceGroups[this->ObjectLibrariesSourceGroupIndex].AddGroupFile( sf->GetFullPath()); #endif @@ -3384,8 +3329,9 @@ void cmMakefile::AddTargetObject(std::string const& tgtName, void cmMakefile::EnableLanguage(std::vector<std::string> const& lang, bool optional) { - this->AddDefinition("CMAKE_CFG_INTDIR", - this->GetGlobalGenerator()->GetCMakeCFGIntDir()); + if (const char* def = this->GetGlobalGenerator()->GetCMakeCFGIntDir()) { + this->AddDefinition("CMAKE_CFG_INTDIR", def); + } // If RC is explicitly listed we need to do it after other languages. // On some platforms we enable RC implicitly while enabling others. // Do not let that look like recursive enable_language(RC). @@ -3556,7 +3502,7 @@ cmGlobalGenerator* cmMakefile::GetGlobalGenerator() const return this->GlobalGenerator; } -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP cmVariableWatch* cmMakefile::GetVariableWatch() const { if (this->GetCMakeInstance() && @@ -3604,8 +3550,7 @@ std::string cmMakefile::GetModulesFile(const std::string& filename, // Always search in CMAKE_MODULE_PATH: const char* cmakeModulePath = this->GetDefinition("CMAKE_MODULE_PATH"); if (cmakeModulePath) { - std::vector<std::string> modulePath; - cmSystemTools::ExpandListArgument(cmakeModulePath, modulePath); + std::vector<std::string> modulePath = cmExpandedList(cmakeModulePath); // Look through the possible module directories. for (std::string itempl : modulePath) { @@ -3620,9 +3565,8 @@ std::string cmMakefile::GetModulesFile(const std::string& filename, } // Always search in the standard modules location. - moduleInCMakeRoot = cmSystemTools::GetCMakeRoot(); - moduleInCMakeRoot += "/Modules/"; - moduleInCMakeRoot += filename; + moduleInCMakeRoot = + cmStrCat(cmSystemTools::GetCMakeRoot(), "/Modules/", filename); cmSystemTools::ConvertToUnixSlashes(moduleInCMakeRoot); if (!cmSystemTools::FileExists(moduleInCMakeRoot)) { moduleInCMakeRoot.clear(); @@ -3697,7 +3641,7 @@ void cmMakefile::ConfigureString(const std::string& input, std::string& output, // Replace #cmakedefine instances. if (this->cmDefineRegex.find(line)) { const char* def = this->GetDefinition(this->cmDefineRegex.match(2)); - if (!cmSystemTools::IsOff(def)) { + if (!cmIsOff(def)) { const std::string indentation = this->cmDefineRegex.match(1); cmSystemTools::ReplaceString(line, "#" + indentation + "cmakedefine", "#" + indentation + "define"); @@ -3713,7 +3657,7 @@ void cmMakefile::ConfigureString(const std::string& input, std::string& output, cmSystemTools::ReplaceString(line, "#" + indentation + "cmakedefine01", "#" + indentation + "define"); output += line; - if (!cmSystemTools::IsOff(def)) { + if (!cmIsOff(def)) { output += " 1"; } else { output += " 0"; @@ -3788,8 +3732,7 @@ int cmMakefile::ConfigureFile(const std::string& infile, } else { newLineCharacters = "\n"; } - std::string tempOutputFile = soutfile; - tempOutputFile += ".tmp"; + std::string tempOutputFile = cmStrCat(soutfile, ".tmp"); cmsys::ofstream fout(tempOutputFile.c_str(), omode); if (!fout) { cmSystemTools::Error("Could not open file for write in copy operation " + @@ -3877,7 +3820,7 @@ const char* cmMakefile::GetProperty(const std::string& prop, bool chain) const bool cmMakefile::GetPropertyAsBool(const std::string& prop) const { - return cmSystemTools::IsOn(this->GetProperty(prop)); + return cmIsOn(this->GetProperty(prop)); } std::vector<std::string> cmMakefile::GetPropertyKeys() const @@ -3930,15 +3873,13 @@ void cmMakefile::AddCMakeDependFilesFromUser() { std::vector<std::string> deps; if (const char* deps_str = this->GetProperty("CMAKE_CONFIGURE_DEPENDS")) { - cmSystemTools::ExpandListArgument(deps_str, deps); + cmExpandList(deps_str, deps); } for (std::string const& dep : deps) { if (cmSystemTools::FileIsFullPath(dep)) { this->AddCMakeDependFile(dep); } else { - std::string f = this->GetCurrentSourceDirectory(); - f += "/"; - f += dep; + std::string f = cmStrCat(this->GetCurrentSourceDirectory(), '/', dep); this->AddCMakeDependFile(f); } } @@ -3978,14 +3919,14 @@ void cmMakefile::PushScope() this->GetState()->CreateVariableScopeSnapshot(this->StateSnapshot); this->PushLoopBlockBarrier(); -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) this->GetGlobalGenerator()->GetFileLockPool().PushFunctionScope(); #endif } void cmMakefile::PopScope() { -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) this->GetGlobalGenerator()->GetFileLockPool().PopFunctionScope(); #endif @@ -4009,7 +3950,7 @@ void cmMakefile::RaiseScope(const std::string& var, const char* varDef) return; } -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP cmVariableWatch* vv = this->GetVariableWatch(); if (vv) { vv->VariableAccessed(var, cmVariableWatch::VARIABLE_MODIFIED_ACCESS, @@ -4059,7 +4000,7 @@ cmTarget* cmMakefile::FindTargetToUse(const std::string& name, bool cmMakefile::IsAlias(const std::string& name) const { - if (this->AliasTargets.find(name) != this->AliasTargets.end()) { + if (cmContains(this->AliasTargets, name)) { return true; } return this->GetGlobalGenerator()->IsAlias(name); @@ -4237,7 +4178,7 @@ void cmMakefile::StoreMatches(cmsys::RegularExpression& re) std::string const& m = re.match(i); if (!m.empty()) { std::string const& var = matchVariables[i]; - this->AddDefinition(var, m.c_str()); + this->AddDefinition(var, m); this->MarkVariableAsUsed(var); highest = static_cast<char>('0' + i); } @@ -4267,7 +4208,7 @@ bool cmMakefile::PolicyOptionalWarningEnabled(std::string const& var) { // Check for an explicit CMAKE_POLICY_WARNING_CMP<NNNN> setting. if (const char* val = this->GetDefinition(var)) { - return cmSystemTools::IsOn(val); + return cmIsOn(val); } // Enable optional policy warnings with --debug-output, --trace, // or --trace-expand. @@ -4300,7 +4241,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, // Deprecate old policies, especially those that require a lot // of code to maintain the old behavior. - if (status == cmPolicies::OLD && id <= cmPolicies::CMP0066 && + if (status == cmPolicies::OLD && id <= cmPolicies::CMP0067 && !(this->GetCMakeInstance()->GetIsInTryCompile() && ( // Policies set by cmCoreTryCompile::TryCompileCode. @@ -4424,10 +4365,8 @@ bool cmMakefile::AddRequiredTargetFeature(cmTarget* target, return false; } - std::vector<std::string> availableFeatures; - cmSystemTools::ExpandListArgument(features, availableFeatures); - if (std::find(availableFeatures.begin(), availableFeatures.end(), feature) == - availableFeatures.end()) { + std::vector<std::string> availableFeatures = cmExpandedList(features); + if (!cmContains(availableFeatures, feature)) { std::ostringstream e; e << "The compiler feature \"" << feature << "\" is not known to " << lang << " compiler\n\"" @@ -4549,10 +4488,10 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target, const char* defaultCStandard = this->GetDefinition("CMAKE_C_STANDARD_DEFAULT"); if (!defaultCStandard) { - std::ostringstream e; - e << "CMAKE_C_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " - "not fully configured for this compiler."; - this->IssueMessage(MessageType::INTERNAL_ERROR, e.str()); + this->IssueMessage( + MessageType::INTERNAL_ERROR, + "CMAKE_C_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " + "not fully configured for this compiler."); // Return true so the caller does not try to lookup the default standard. return true; } @@ -4633,10 +4572,10 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target, const char* defaultCxxStandard = this->GetDefinition("CMAKE_CXX_STANDARD_DEFAULT"); if (!defaultCxxStandard) { - std::ostringstream e; - e << "CMAKE_CXX_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " - "not fully configured for this compiler."; - this->IssueMessage(MessageType::INTERNAL_ERROR, e.str()); + this->IssueMessage( + MessageType::INTERNAL_ERROR, + "CMAKE_CXX_STANDARD_DEFAULT is not set. COMPILE_FEATURES support " + "not fully configured for this compiler."); // Return true so the caller does not try to lookup the default standard. return true; } @@ -4694,33 +4633,28 @@ void cmMakefile::CheckNeededCxxLanguage(const std::string& feature, { if (const char* propCxx98 = this->GetDefinition("CMAKE_CXX98_COMPILE_FEATURES")) { - std::vector<std::string> props; - cmSystemTools::ExpandListArgument(propCxx98, props); - needCxx98 = std::find(props.begin(), props.end(), feature) != props.end(); + std::vector<std::string> props = cmExpandedList(propCxx98); + needCxx98 = cmContains(props, feature); } if (const char* propCxx11 = this->GetDefinition("CMAKE_CXX11_COMPILE_FEATURES")) { - std::vector<std::string> props; - cmSystemTools::ExpandListArgument(propCxx11, props); - needCxx11 = std::find(props.begin(), props.end(), feature) != props.end(); + std::vector<std::string> props = cmExpandedList(propCxx11); + needCxx11 = cmContains(props, feature); } if (const char* propCxx14 = this->GetDefinition("CMAKE_CXX14_COMPILE_FEATURES")) { - std::vector<std::string> props; - cmSystemTools::ExpandListArgument(propCxx14, props); - needCxx14 = std::find(props.begin(), props.end(), feature) != props.end(); + std::vector<std::string> props = cmExpandedList(propCxx14); + needCxx14 = cmContains(props, feature); } if (const char* propCxx17 = this->GetDefinition("CMAKE_CXX17_COMPILE_FEATURES")) { - std::vector<std::string> props; - cmSystemTools::ExpandListArgument(propCxx17, props); - needCxx17 = std::find(props.begin(), props.end(), feature) != props.end(); + std::vector<std::string> props = cmExpandedList(propCxx17); + needCxx17 = cmContains(props, feature); } if (const char* propCxx20 = this->GetDefinition("CMAKE_CXX20_COMPILE_FEATURES")) { - std::vector<std::string> props; - cmSystemTools::ExpandListArgument(propCxx20, props); - needCxx20 = std::find(props.begin(), props.end(), feature) != props.end(); + std::vector<std::string> props = cmExpandedList(propCxx20); + needCxx20 = cmContains(props, feature); } } @@ -4818,21 +4752,18 @@ void cmMakefile::CheckNeededCLanguage(const std::string& feature, { if (const char* propC90 = this->GetDefinition("CMAKE_C90_COMPILE_FEATURES")) { - std::vector<std::string> props; - cmSystemTools::ExpandListArgument(propC90, props); - needC90 = std::find(props.begin(), props.end(), feature) != props.end(); + std::vector<std::string> props = cmExpandedList(propC90); + needC90 = cmContains(props, feature); } if (const char* propC99 = this->GetDefinition("CMAKE_C99_COMPILE_FEATURES")) { - std::vector<std::string> props; - cmSystemTools::ExpandListArgument(propC99, props); - needC99 = std::find(props.begin(), props.end(), feature) != props.end(); + std::vector<std::string> props = cmExpandedList(propC99); + needC99 = cmContains(props, feature); } if (const char* propC11 = this->GetDefinition("CMAKE_C11_COMPILE_FEATURES")) { - std::vector<std::string> props; - cmSystemTools::ExpandListArgument(propC11, props); - needC11 = std::find(props.begin(), props.end(), feature) != props.end(); + std::vector<std::string> props = cmExpandedList(propC11); + needC11 = cmContains(props, feature); } } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index d223347..dcc4e77 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -7,8 +7,9 @@ #include "cmsys/RegularExpression.hxx" #include <deque> +#include <functional> #include <map> -#include <memory> // IWYU pragma: keep +#include <memory> #include <set> #include <stack> #include <stddef.h> @@ -16,6 +17,8 @@ #include <unordered_map> #include <vector> +#include "cm_string_view.hxx" + #include "cmAlgorithms.h" #include "cmListFileCache.h" #include "cmMessageType.h" @@ -24,13 +27,13 @@ #include "cmSourceFileLocationKind.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmTarget.h" -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) # include "cmSourceGroup.h" #endif -class cmCommand; class cmCompiledGeneratorExpression; class cmCustomCommandLines; class cmExecutionStatus; @@ -95,7 +98,7 @@ public: /** * Add a function blocker to this makefile */ - void AddFunctionBlocker(cmFunctionBlocker* fb); + void AddFunctionBlocker(std::unique_ptr<cmFunctionBlocker> fb); /// @return whether we are processing the top CMakeLists.txt file. bool IsRootMakefile() const; @@ -104,8 +107,7 @@ public: * Remove the function blocker whose scope ends with the given command. * This returns ownership of the function blocker object. */ - std::unique_ptr<cmFunctionBlocker> RemoveFunctionBlocker( - cmFunctionBlocker* fb, const cmListFileFunction& lff); + std::unique_ptr<cmFunctionBlocker> RemoveFunctionBlocker(); /** * Try running cmake and building a file. This is used for dynalically @@ -125,6 +127,13 @@ public: bool EnforceUniqueName(std::string const& name, std::string& msg, bool isCustom = false) const; + using FinalAction = std::function<void(cmMakefile&)>; + + /** + * Register an action that is executed during FinalPass + */ + void AddFinalAction(FinalAction action); + /** * Perform FinalPass, Library dependency analysis etc before output of the * makefile. @@ -132,7 +141,7 @@ public: void ConfigureFinalPass(); /** - * run the final pass on all commands. + * run all FinalActions. */ void FinalPass(); @@ -256,18 +265,17 @@ public: * Add a variable definition to the build. This variable * can be used in CMake to refer to lists, directories, etc. */ - void AddDefinition(const std::string& name, const char* value); + void AddDefinition(const std::string& name, cm::string_view value); + /** + * Add bool variable definition to the build. + */ + void AddDefinitionBool(const std::string& name, bool); //! Add a definition to this makefile and the global cmake cache. void AddCacheDefinition(const std::string& name, const char* value, const char* doc, cmStateEnums::CacheEntryType type, bool force = false); /** - * Add bool variable definition to the build. - */ - void AddDefinition(const std::string& name, bool); - - /** * Remove a variable definition from the build. This is not valid * for cache entries, and will only affect the current makefile. */ @@ -495,7 +503,7 @@ public: */ bool CanIWriteThisFile(std::string const& fileName) const; -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) /** * Get the vector source groups. */ @@ -619,6 +627,11 @@ public: void PrintCommandTrace(const cmListFileFunction& lff) const; /** + * Set a callback that is invoked whenever ExecuteCommand is called. + */ + void OnExecuteCommand(std::function<void()> callback); + + /** * Execute a single CMake command. Returns true if the command * succeeded or false if it failed. */ @@ -636,7 +649,7 @@ public: * Get the variable watch. This is used to determine when certain variables * are accessed. */ -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP cmVariableWatch* GetVariableWatch() const; #endif @@ -932,12 +945,12 @@ protected: // Track the value of the computed DEFINITIONS property. std::string DefineFlagsOrig; -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) std::vector<cmSourceGroup> SourceGroups; size_t ObjectLibrariesSourceGroupIndex; #endif - std::vector<cmCommand*> FinalPassCommands; + std::vector<FinalAction> FinalActions; cmGlobalGenerator* GlobalGenerator; bool IsFunctionBlocked(const cmListFileFunction& lff, cmExecutionStatus& status); @@ -955,7 +968,10 @@ private: bool EnforceUniqueDir(const std::string& srcPath, const std::string& binPath) const; - typedef std::vector<cmFunctionBlocker*> FunctionBlockersType; + std::function<void()> ExecuteCommandCallback; + using FunctionBlockerPtr = std::unique_ptr<cmFunctionBlocker>; + using FunctionBlockersType = + std::stack<FunctionBlockerPtr, std::vector<FunctionBlockerPtr>>; FunctionBlockersType FunctionBlockers; std::vector<FunctionBlockersType::size_type> FunctionBlockerBarriers; void PushFunctionBlockerBarrier(); @@ -986,7 +1002,8 @@ private: cmPolicies::PolicyMap const& pm = cmPolicies::PolicyMap()); void PopPolicy(); void PopSnapshot(bool reportError = true); - friend class cmCMakePolicyCommand; + friend bool cmCMakePolicyCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); class IncludeScope; friend class IncludeScope; diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 6b9b9c7..7bc05b1 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -2,13 +2,14 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMakefileExecutableTargetGenerator.h" -#include <memory> // IWYU pragma: keep #include <set> #include <sstream> #include <string> #include <utility> #include <vector> +#include "cm_memory.hxx" + #include "cmAlgorithms.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" @@ -25,6 +26,7 @@ #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmMakefileExecutableTargetGenerator::cmMakefileExecutableTargetGenerator( @@ -81,7 +83,7 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles() void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( bool relink) { -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP const bool requiresDeviceLinking = requireDeviceLinking( *this->GeneratorTarget, *this->LocalGenerator, this->ConfigName); if (!requiresDeviceLinking) { @@ -109,14 +111,13 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( cmLocalUnixMakefileGenerator3::EchoProgress progress; this->MakeEchoProgress(progress); // Add the link message. - std::string buildEcho = "Linking "; - buildEcho += linkLanguage; - buildEcho += " device code "; - buildEcho += this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), - this->DeviceLinkObject), - cmOutputConverter::SHELL); + std::string buildEcho = + cmStrCat("Linking ", linkLanguage, " device code ", + this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetCurrentBinaryDirectory(), + this->DeviceLinkObject), + cmOutputConverter::SHELL)); this->LocalGenerator->AppendEcho( commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress); } @@ -128,9 +129,8 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( // Add flags to create an executable. // Add symbol export flags if necessary. if (this->GeneratorTarget->IsExecutableWithExports()) { - std::string export_flag_var = "CMAKE_EXE_EXPORTS_"; - export_flag_var += linkLanguage; - export_flag_var += "_FLAG"; + std::string export_flag_var = + cmStrCat("CMAKE_EXE_EXPORTS_", linkLanguage, "_FLAG"); this->LocalGenerator->AppendFlags( linkFlags, this->Makefile->GetDefinition(export_flag_var)); } @@ -163,7 +163,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( const std::string linkRuleVar = "CMAKE_CUDA_DEVICE_LINK_EXECUTABLE"; const std::string linkRule = this->GetLinkRule(linkRuleVar); std::vector<std::string> commands1; - cmSystemTools::ExpandListArgument(linkRule, real_link_commands); + cmExpandList(linkRule, real_link_commands); bool useResponseFileForObjects = this->CheckUseResponseFileForObjects(linkLanguage); @@ -232,8 +232,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( const char* val = this->LocalGenerator->GetRuleLauncher( this->GeneratorTarget, "RULE_LAUNCH_LINK"); if (val && *val) { - launcher = val; - launcher += " "; + launcher = cmStrCat(val, ' '); } std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( @@ -242,7 +241,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule( // Expand placeholders in the commands. rulePlaceholderExpander->SetTargetImpLib(targetOutputReal); for (std::string& real_link_command : real_link_commands) { - real_link_command = launcher + real_link_command; + real_link_command = cmStrCat(launcher, real_link_command); rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, real_link_command, vars); } @@ -295,14 +294,13 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) if (this->GeneratorTarget->IsAppBundleOnApple()) { this->OSXBundleGenerator->CreateAppBundle(targetNames.Output, outpath); } - outpath += "/"; + outpath += '/'; std::string outpathImp; if (relink) { - outpath = this->Makefile->GetCurrentBinaryDirectory(); - outpath += "/CMakeFiles"; - outpath += "/CMakeRelink.dir"; + outpath = cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), + "/CMakeFiles/CMakeRelink.dir"); cmSystemTools::MakeDirectory(outpath); - outpath += "/"; + outpath += '/'; if (!targetNames.ImportLibrary.empty()) { outpathImp = outpath; } @@ -312,7 +310,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) outpathImp = this->GeneratorTarget->GetDirectory( this->ConfigName, cmStateEnums::ImportLibraryArtifact); cmSystemTools::MakeDirectory(outpathImp); - outpathImp += "/"; + outpathImp += '/'; } } @@ -323,7 +321,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) std::string pdbOutputPath = this->GeneratorTarget->GetPDBDirectory(this->ConfigName); cmSystemTools::MakeDirectory(pdbOutputPath); - pdbOutputPath += "/"; + pdbOutputPath += '/'; std::string targetFullPath = outpath + targetNames.Output; std::string targetFullPathReal = outpath + targetNames.Real; @@ -370,10 +368,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) cmLocalUnixMakefileGenerator3::EchoProgress progress; this->MakeEchoProgress(progress); // Add the link message. - std::string buildEcho = "Linking "; - buildEcho += linkLanguage; - buildEcho += " executable "; - buildEcho += targetOutPath; + std::string buildEcho = + cmStrCat("Linking ", linkLanguage, " executable ", targetOutPath); this->LocalGenerator->AppendEcho( commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress); } @@ -396,9 +392,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Add symbol export flags if necessary. if (this->GeneratorTarget->IsExecutableWithExports()) { - std::string export_flag_var = "CMAKE_EXE_EXPORTS_"; - export_flag_var += linkLanguage; - export_flag_var += "_FLAG"; + std::string export_flag_var = + cmStrCat("CMAKE_EXE_EXPORTS_", linkLanguage, "_FLAG"); this->LocalGenerator->AppendFlags( linkFlags, this->Makefile->GetDefinition(export_flag_var)); } @@ -482,20 +477,18 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Construct the main link rule. std::vector<std::string> real_link_commands; - std::string linkRuleVar = "CMAKE_"; - linkRuleVar += linkLanguage; - linkRuleVar += "_LINK_EXECUTABLE"; + std::string linkRuleVar = this->GeneratorTarget->GetCreateRuleVariable( + linkLanguage, this->ConfigName); std::string linkRule = this->GetLinkRule(linkRuleVar); std::vector<std::string> commands1; - cmSystemTools::ExpandListArgument(linkRule, real_link_commands); + cmExpandList(linkRule, real_link_commands); if (this->GeneratorTarget->IsExecutableWithExports()) { // If a separate rule for creating an import library is specified // add it now. - std::string implibRuleVar = "CMAKE_"; - implibRuleVar += linkLanguage; - implibRuleVar += "_CREATE_IMPORT_LIBRARY"; + std::string implibRuleVar = + cmStrCat("CMAKE_", linkLanguage, "_CREATE_IMPORT_LIBRARY"); if (const char* rule = this->Makefile->GetDefinition(implibRuleVar)) { - cmSystemTools::ExpandListArgument(rule, real_link_commands); + cmExpandList(rule, real_link_commands); } } @@ -590,10 +583,10 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) vars.Manifests = manifests.c_str(); if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { - std::string cmakeCommand = this->LocalGenerator->ConvertToOutputFormat( - cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); - cmakeCommand += " -E __run_co_compile --lwyu="; - cmakeCommand += targetOutPathReal; + std::string cmakeCommand = + cmStrCat(this->LocalGenerator->ConvertToOutputFormat( + cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), + " -E __run_co_compile --lwyu=", targetOutPathReal); real_link_commands.push_back(std::move(cmakeCommand)); } @@ -602,8 +595,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) const char* val = this->LocalGenerator->GetRuleLauncher( this->GeneratorTarget, "RULE_LAUNCH_LINK"); if (val && *val) { - launcher = val; - launcher += " "; + launcher = cmStrCat(val, ' '); } std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( @@ -612,7 +604,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Expand placeholders in the commands. rulePlaceholderExpander->SetTargetImpLib(targetOutPathImport); for (std::string& real_link_command : real_link_commands) { - real_link_command = launcher + real_link_command; + real_link_command = cmStrCat(launcher, real_link_command); rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, real_link_command, vars); } @@ -639,10 +631,9 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) // Add a rule to create necessary symlinks for the library. if (targetOutPath != targetOutPathReal) { - std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_executable "; - symlink += targetOutPathReal; - symlink += " "; - symlink += targetOutPath; + std::string symlink = + cmStrCat("$(CMAKE_COMMAND) -E cmake_symlink_executable ", + targetOutPathReal, ' ', targetOutPath); commands1.push_back(std::move(symlink)); this->LocalGenerator->CreateCDCommand( commands1, this->Makefile->GetCurrentBinaryDirectory(), diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index b9f7c6d..252279f 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -2,13 +2,14 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMakefileLibraryTargetGenerator.h" -#include <memory> // IWYU pragma: keep #include <set> #include <sstream> #include <stddef.h> #include <utility> #include <vector> +#include "cm_memory.hxx" + #include "cmAlgorithms.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" @@ -25,6 +26,7 @@ #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmMakefileLibraryTargetGenerator::cmMakefileLibraryTargetGenerator( @@ -161,9 +163,8 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) std::string linkLanguage = this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); - std::string linkRuleVar = "CMAKE_"; - linkRuleVar += linkLanguage; - linkRuleVar += "_CREATE_SHARED_LIBRARY"; + std::string linkRuleVar = + cmStrCat("CMAKE_", linkLanguage, "_CREATE_SHARED_LIBRARY"); std::string extraFlags; this->GetTargetLinkFlags(extraFlags, linkLanguage); @@ -196,9 +197,8 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink) std::string linkLanguage = this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); - std::string linkRuleVar = "CMAKE_"; - linkRuleVar += linkLanguage; - linkRuleVar += "_CREATE_SHARED_MODULE"; + std::string linkRuleVar = + cmStrCat("CMAKE_", linkLanguage, "_CREATE_SHARED_MODULE"); std::string extraFlags; this->GetTargetLinkFlags(extraFlags, linkLanguage); @@ -219,9 +219,8 @@ void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink) { std::string linkLanguage = this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); - std::string linkRuleVar = "CMAKE_"; - linkRuleVar += linkLanguage; - linkRuleVar += "_CREATE_MACOSX_FRAMEWORK"; + std::string linkRuleVar = + cmStrCat("CMAKE_", linkLanguage, "_CREATE_MACOSX_FRAMEWORK"); std::string extraFlags; this->GetTargetLinkFlags(extraFlags, linkLanguage); @@ -234,7 +233,7 @@ void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink) void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( const std::string& linkRuleVar, bool relink) { -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP // TODO: Merge the methods that call this method to avoid // code duplication. std::vector<std::string> commands; @@ -262,12 +261,13 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( cmLocalUnixMakefileGenerator3::EchoProgress progress; this->MakeEchoProgress(progress); // Add the link message. - std::string buildEcho = "Linking " + linkLanguage + " device code "; - buildEcho += this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), - this->DeviceLinkObject), - cmOutputConverter::SHELL); + std::string buildEcho = + cmStrCat("Linking ", linkLanguage, " device code ", + this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetCurrentBinaryDirectory(), + this->DeviceLinkObject), + cmOutputConverter::SHELL)); this->LocalGenerator->AppendEcho( commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress); } @@ -358,8 +358,7 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( const char* val = this->LocalGenerator->GetRuleLauncher( this->GeneratorTarget, "RULE_LAUNCH_LINK"); if (val && *val) { - launcher = val; - launcher += " "; + launcher = cmStrCat(val, ' '); } std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( @@ -368,11 +367,11 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( // Construct the main link rule and expand placeholders. rulePlaceholderExpander->SetTargetImpLib(targetOutputReal); std::string linkRule = this->GetLinkRule(linkRuleVar); - cmSystemTools::ExpandListArgument(linkRule, real_link_commands); + cmExpandList(linkRule, real_link_commands); // Expand placeholders. for (std::string& real_link_command : real_link_commands) { - real_link_command = launcher + real_link_command; + real_link_command = cmStrCat(launcher, real_link_command); rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, real_link_command, vars); } @@ -463,30 +462,29 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( outpath = this->GeneratorTarget->GetDirectory(this->ConfigName); this->OSXBundleGenerator->CreateFramework(this->TargetNames.Output, outpath); - outpath += "/"; + outpath += '/'; } else if (this->GeneratorTarget->IsCFBundleOnApple()) { outpath = this->GeneratorTarget->GetDirectory(this->ConfigName); this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output, outpath); - outpath += "/"; + outpath += '/'; } else if (relink) { - outpath = this->Makefile->GetCurrentBinaryDirectory(); - outpath += "/CMakeFiles"; - outpath += "/CMakeRelink.dir"; + outpath = cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), + "/CMakeFiles/CMakeRelink.dir"); cmSystemTools::MakeDirectory(outpath); - outpath += "/"; + outpath += '/'; if (!this->TargetNames.ImportLibrary.empty()) { outpathImp = outpath; } } else { outpath = this->GeneratorTarget->GetDirectory(this->ConfigName); cmSystemTools::MakeDirectory(outpath); - outpath += "/"; + outpath += '/'; if (!this->TargetNames.ImportLibrary.empty()) { outpathImp = this->GeneratorTarget->GetDirectory( this->ConfigName, cmStateEnums::ImportLibraryArtifact); cmSystemTools::MakeDirectory(outpathImp); - outpathImp += "/"; + outpathImp += '/'; } } @@ -535,8 +533,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( cmLocalUnixMakefileGenerator3::EchoProgress progress; this->MakeEchoProgress(progress); // Add the link message. - std::string buildEcho = "Linking "; - buildEcho += linkLanguage; + std::string buildEcho = cmStrCat("Linking ", linkLanguage); switch (this->GeneratorTarget->GetType()) { case cmStateEnums::STATIC_LIBRARY: buildEcho += " static library "; @@ -640,35 +637,32 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( std::string::size_type archiveCommandLimit = std::string::npos; if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) { haveStaticLibraryRule = this->Makefile->IsDefinitionSet(linkRuleVar); - std::string arCreateVar = "CMAKE_"; - arCreateVar += linkLanguage; - arCreateVar += "_ARCHIVE_CREATE"; + std::string arCreateVar = + cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_CREATE"); arCreateVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( arCreateVar, linkLanguage, this->ConfigName); if (const char* rule = this->Makefile->GetDefinition(arCreateVar)) { - cmSystemTools::ExpandListArgument(rule, archiveCreateCommands); + cmExpandList(rule, archiveCreateCommands); } - std::string arAppendVar = "CMAKE_"; - arAppendVar += linkLanguage; - arAppendVar += "_ARCHIVE_APPEND"; + std::string arAppendVar = + cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_APPEND"); arAppendVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( arAppendVar, linkLanguage, this->ConfigName); if (const char* rule = this->Makefile->GetDefinition(arAppendVar)) { - cmSystemTools::ExpandListArgument(rule, archiveAppendCommands); + cmExpandList(rule, archiveAppendCommands); } - std::string arFinishVar = "CMAKE_"; - arFinishVar += linkLanguage; - arFinishVar += "_ARCHIVE_FINISH"; + std::string arFinishVar = + cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_FINISH"); arFinishVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( arFinishVar, linkLanguage, this->ConfigName); if (const char* rule = this->Makefile->GetDefinition(arFinishVar)) { - cmSystemTools::ExpandListArgument(rule, archiveFinishCommands); + cmExpandList(rule, archiveFinishCommands); } } @@ -820,8 +814,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( const char* val = this->LocalGenerator->GetRuleLauncher( this->GeneratorTarget, "RULE_LAUNCH_LINK"); if (val && *val) { - launcher = val; - launcher += " "; + launcher = cmStrCat(val, ' '); } std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( @@ -878,19 +871,19 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( } else { // Get the set of commands. std::string linkRule = this->GetLinkRule(linkRuleVar); - cmSystemTools::ExpandListArgument(linkRule, real_link_commands); + cmExpandList(linkRule, real_link_commands); if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE") && (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY)) { - std::string cmakeCommand = this->LocalGenerator->ConvertToOutputFormat( - cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); - cmakeCommand += " -E __run_co_compile --lwyu="; - cmakeCommand += targetOutPathReal; + std::string cmakeCommand = cmStrCat( + this->LocalGenerator->ConvertToOutputFormat( + cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), + " -E __run_co_compile --lwyu=", targetOutPathReal); real_link_commands.push_back(std::move(cmakeCommand)); } // Expand placeholders. for (std::string& real_link_command : real_link_commands) { - real_link_command = launcher + real_link_command; + real_link_command = cmStrCat(launcher, real_link_command); rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, real_link_command, vars); } @@ -920,12 +913,9 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Frameworks are handled by cmOSXBundleGenerator. if (targetOutPath != targetOutPathReal && !this->GeneratorTarget->IsFrameworkOnApple()) { - std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library "; - symlink += targetOutPathReal; - symlink += " "; - symlink += targetOutPathSO; - symlink += " "; - symlink += targetOutPath; + std::string symlink = + cmStrCat("$(CMAKE_COMMAND) -E cmake_symlink_library ", targetOutPathReal, + ' ', targetOutPathSO, ' ', targetOutPath); commands1.push_back(std::move(symlink)); this->LocalGenerator->CreateCDCommand( commands1, this->Makefile->GetCurrentBinaryDirectory(), diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index b3bab4b..f99fe4e 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMakefileTargetGenerator.h" -#include <memory> // IWYU pragma: keep +#include <memory> #include <sstream> #include <stdio.h> #include <utility> @@ -28,6 +28,7 @@ #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" @@ -48,7 +49,7 @@ cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target) this->NoRuleMessages = false; if (const char* ruleStatus = cm->GetState()->GetGlobalProperty("RULE_MESSAGES")) { - this->NoRuleMessages = cmSystemTools::IsOff(ruleStatus); + this->NoRuleMessages = cmIsOff(ruleStatus); } MacOSXContentGenerator = new MacOSXContentGeneratorType(this); } @@ -89,8 +90,8 @@ void cmMakefileTargetGenerator::GetTargetLinkFlags( this->LocalGenerator->AppendFlags( flags, this->GeneratorTarget->GetProperty("LINK_FLAGS")); - std::string linkFlagsConfig = "LINK_FLAGS_"; - linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName); + std::string linkFlagsConfig = + cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(this->ConfigName)); this->LocalGenerator->AppendFlags( flags, this->GeneratorTarget->GetProperty(linkFlagsConfig)); @@ -113,14 +114,13 @@ void cmMakefileTargetGenerator::CreateRuleFile() cmSystemTools::MakeDirectory(this->TargetBuildDirectoryFull); // Construct the rule file name. - this->BuildFileName = this->TargetBuildDirectory; - this->BuildFileName += "/build.make"; - this->BuildFileNameFull = this->TargetBuildDirectoryFull; - this->BuildFileNameFull += "/build.make"; + this->BuildFileName = cmStrCat(this->TargetBuildDirectory, "/build.make"); + this->BuildFileNameFull = + cmStrCat(this->TargetBuildDirectoryFull, "/build.make"); // Construct the rule file name. - this->ProgressFileNameFull = this->TargetBuildDirectoryFull; - this->ProgressFileNameFull += "/progress.make"; + this->ProgressFileNameFull = + cmStrCat(this->TargetBuildDirectoryFull, "/progress.make"); // reset the progress count this->NumberOfProgressActions = 0; @@ -130,10 +130,10 @@ void cmMakefileTargetGenerator::CreateRuleFile() this->BuildFileStream = new cmGeneratedFileStream(this->BuildFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding()); - this->BuildFileStream->SetCopyIfDifferent(true); if (!this->BuildFileStream) { return; } + this->BuildFileStream->SetCopyIfDifferent(true); this->LocalGenerator->WriteDisclaimer(*this->BuildFileStream); if (this->GlobalGenerator->AllowDeleteOnError()) { std::vector<std::string> no_depends; @@ -158,10 +158,9 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() std::vector<std::string> files; cmGeneratorExpression ge; std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop_value); - cmSystemTools::ExpandListArgument( - cge->Evaluate(this->LocalGenerator, config, false, this->GeneratorTarget, - nullptr, nullptr), - files); + cmExpandList(cge->Evaluate(this->LocalGenerator, config, false, + this->GeneratorTarget, nullptr, nullptr), + files); return files; }; @@ -186,7 +185,7 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() // add custom commands to the clean rules? const char* clean_no_custom = this->Makefile->GetProperty("CLEAN_NO_CUSTOM"); - bool clean = cmSystemTools::IsOff(clean_no_custom); + bool clean = cmIsOff(clean_no_custom); // First generate the object rule files. Save a list of all object // files for this target. @@ -260,8 +259,8 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() : ""); // Include the dependencies for the target. - std::string dependFileNameFull = this->TargetBuildDirectoryFull; - dependFileNameFull += "/depend.make"; + std::string dependFileNameFull = + cmStrCat(this->TargetBuildDirectoryFull, "/depend.make"); *this->BuildFileStream << "# Include any dependencies generated for this target.\n" << this->GlobalGenerator->IncludeDirective << " " << root @@ -295,15 +294,15 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() // Open the flags file. This should be copy-if-different because the // rules may depend on this file itself. - this->FlagFileNameFull = this->TargetBuildDirectoryFull; - this->FlagFileNameFull += "/flags.make"; + this->FlagFileNameFull = + cmStrCat(this->TargetBuildDirectoryFull, "/flags.make"); this->FlagFileStream = new cmGeneratedFileStream(this->FlagFileNameFull, false, this->GlobalGenerator->GetMakefileEncoding()); - this->FlagFileStream->SetCopyIfDifferent(true); if (!this->FlagFileStream) { return; } + this->FlagFileStream->SetCopyIfDifferent(true); this->LocalGenerator->WriteDisclaimer(*this->FlagFileStream); // Include the flags for the target. @@ -325,9 +324,7 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags() // put the compiler in the rules.make file so that if it changes // things rebuild for (std::string const& language : languages) { - std::string compiler = "CMAKE_"; - compiler += language; - compiler += "_COMPILER"; + std::string compiler = cmStrCat("CMAKE_", language, "_COMPILER"); *this->FlagFileStream << "# compile " << language << " with " << this->Makefile->GetSafeDefinition(compiler) << "\n"; @@ -362,9 +359,8 @@ void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()( std::string const& input = source.GetFullPath(); // Get the output file location. - std::string output = macdir; - output += "/"; - output += cmSystemTools::GetFilenameName(input); + std::string output = + cmStrCat(macdir, '/', cmSystemTools::GetFilenameName(input)); this->Generator->CleanFiles.insert( this->Generator->LocalGenerator->MaybeConvertToRelativePath( this->Generator->LocalGenerator->GetCurrentBinaryDirectory(), output)); @@ -375,16 +371,16 @@ void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()( std::vector<std::string> depends; std::vector<std::string> commands; depends.push_back(input); - std::string copyEcho = "Copying OS X content "; - copyEcho += output; + std::string copyEcho = cmStrCat("Copying OS X content ", output); this->Generator->LocalGenerator->AppendEcho( commands, copyEcho, cmLocalUnixMakefileGenerator3::EchoBuild); - std::string copyCommand = "$(CMAKE_COMMAND) -E copy "; - copyCommand += this->Generator->LocalGenerator->ConvertToOutputFormat( - input, cmOutputConverter::SHELL); - copyCommand += " "; - copyCommand += this->Generator->LocalGenerator->ConvertToOutputFormat( - output, cmOutputConverter::SHELL); + std::string copyCommand = + cmStrCat("$(CMAKE_COMMAND) -E copy ", + this->Generator->LocalGenerator->ConvertToOutputFormat( + input, cmOutputConverter::SHELL), + ' ', + this->Generator->LocalGenerator->ConvertToOutputFormat( + output, cmOutputConverter::SHELL)); commands.push_back(std::move(copyCommand)); this->Generator->LocalGenerator->WriteMakeRule( *this->Generator->BuildFileStream, nullptr, output, depends, commands, @@ -407,9 +403,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::string const& objectName = this->GeneratorTarget->GetObjectName(&source); std::string obj = - this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); - obj += "/"; - obj += objectName; + cmStrCat(this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), + '/', objectName); // Avoid generating duplicate rules. if (this->ObjectFiles.find(obj) == this->ObjectFiles.end()) { @@ -445,9 +440,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( this->WriteObjectBuildFile(obj, lang, source, depends); // The object file should be checked for dependency integrity. - std::string objFullPath = this->LocalGenerator->GetCurrentBinaryDirectory(); - objFullPath += "/"; - objFullPath += obj; + std::string objFullPath = + cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/', obj); objFullPath = cmSystemTools::CollapseFullPath(objFullPath); std::string srcFullPath = cmSystemTools::CollapseFullPath(source.GetFullPath()); @@ -467,17 +461,15 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( // generate the depend scanning rule this->WriteObjectDependRules(source, depends); - std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath(); - relativeObj += obj; + std::string relativeObj = + cmStrCat(this->LocalGenerator->GetHomeRelativeOutputPath(), obj); // Write the build rule. // Build the set of compiler flags. std::string flags; // Add language-specific flags. - std::string langFlags = "$("; - langFlags += lang; - langFlags += "_FLAGS)"; + std::string langFlags = cmStrCat("$(", lang, "_FLAGS)"); this->LocalGenerator->AppendFlags(flags, langFlags); std::string config = this->LocalGenerator->GetConfigName(); @@ -539,8 +531,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( << "_DEFINES = " << evaluatedDefs << "\n" << "\n"; } - std::string defPropName = "COMPILE_DEFINITIONS_"; - defPropName += configUpper; + std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper); if (const char* config_compile_defs = source.GetProperty(defPropName)) { const std::string& evaluatedDefs = genexInterpreter.Evaluate(config_compile_defs, COMPILE_DEFINITIONS); @@ -564,10 +555,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( if (!this->NoRuleMessages) { cmLocalUnixMakefileGenerator3::EchoProgress progress; this->MakeEchoProgress(progress); - std::string buildEcho = "Building "; - buildEcho += lang; - buildEcho += " object "; - buildEcho += relativeObj; + std::string buildEcho = + cmStrCat("Building ", lang, " object ", relativeObj); this->LocalGenerator->AppendEcho(commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoBuild, &progress); @@ -587,9 +576,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( targetFullPathReal = this->GeneratorTarget->GetFullPath( this->ConfigName, cmStateEnums::RuntimeBinaryArtifact, true); targetFullPathPDB = - this->GeneratorTarget->GetPDBDirectory(this->ConfigName); - targetFullPathPDB += "/"; - targetFullPathPDB += this->GeneratorTarget->GetPDBName(this->ConfigName); + cmStrCat(this->GeneratorTarget->GetPDBDirectory(this->ConfigName), '/', + this->GeneratorTarget->GetPDBName(this->ConfigName)); } targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat( @@ -638,9 +626,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( vars.ObjectFileDir = objectFileDir.c_str(); vars.Flags = flags.c_str(); - std::string definesString = "$("; - definesString += lang; - definesString += "_DEFINES)"; + std::string definesString = cmStrCat("$(", lang, "_DEFINES)"); this->LocalGenerator->JoinDefines(defines, definesString, lang); @@ -679,12 +665,12 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( } const std::string& compileRule = this->Makefile->GetRequiredDefinition(cmdVar); - cmSystemTools::ExpandListArgument(compileRule, compileCommands); + cmExpandList(compileRule, compileCommands); } else { const std::string cmdVar = "CMAKE_" + lang + "_COMPILE_OBJECT"; const std::string& compileRule = this->Makefile->GetRequiredDefinition(cmdVar); - cmSystemTools::ExpandListArgument(compileRule, compileCommands); + cmExpandList(compileRule, compileCommands); } if (this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS") && @@ -781,8 +767,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( // If compiler launcher was specified and not consumed above, it // goes to the beginning of the command line. if (!compileCommands.empty() && !compilerLauncher.empty()) { - std::vector<std::string> args; - cmSystemTools::ExpandListArgument(compilerLauncher, args, true); + std::vector<std::string> args = cmExpandedList(compilerLauncher, true); if (!args.empty()) { args[0] = this->LocalGenerator->ConvertToOutputFormat( args[0], cmOutputConverter::SHELL); @@ -798,14 +783,13 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( const char* val = this->LocalGenerator->GetRuleLauncher( this->GeneratorTarget, "RULE_LAUNCH_COMPILE"); if (val && *val) { - launcher = val; - launcher += " "; + launcher = cmStrCat(val, ' '); } } // Expand placeholders in the commands. for (std::string& compileCommand : compileCommands) { - compileCommand = launcher + compileCommand; + compileCommand = cmStrCat(launcher, compileCommand); rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator, compileCommand, vars); } @@ -821,7 +805,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( std::vector<std::string> outputs(1, relativeObj); if (const char* extra_outputs_str = source.GetProperty("OBJECT_OUTPUTS")) { // Register these as extra files to clean. - cmSystemTools::ExpandListArgument(extra_outputs_str, outputs); + cmExpandList(extra_outputs_str, outputs); this->CleanFiles.insert(outputs.begin() + 1, outputs.end()); } @@ -846,20 +830,17 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( std::string relativeObjI = relativeObjBase + ".i"; std::string objI = objBase + ".i"; - std::string preprocessEcho = "Preprocessing "; - preprocessEcho += lang; - preprocessEcho += " source to "; - preprocessEcho += objI; + std::string preprocessEcho = + cmStrCat("Preprocessing ", lang, " source to ", objI); this->LocalGenerator->AppendEcho( commands, preprocessEcho, cmLocalUnixMakefileGenerator3::EchoBuild); - std::string preprocessRuleVar = "CMAKE_"; - preprocessRuleVar += lang; - preprocessRuleVar += "_CREATE_PREPROCESSED_SOURCE"; + std::string preprocessRuleVar = + cmStrCat("CMAKE_", lang, "_CREATE_PREPROCESSED_SOURCE"); if (const char* preprocessRule = this->Makefile->GetDefinition(preprocessRuleVar)) { - std::vector<std::string> preprocessCommands; - cmSystemTools::ExpandListArgument(preprocessRule, preprocessCommands); + std::vector<std::string> preprocessCommands = + cmExpandedList(preprocessRule); std::string shellObjI = this->LocalGenerator->ConvertToOutputFormat( objI, cmOutputConverter::SHELL); @@ -878,8 +859,9 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( this->LocalGenerator->GetBinaryDirectory()); cmAppend(commands, preprocessCommands); } else { - std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable "; - cmd += preprocessRuleVar; + std::string cmd = + cmStrCat("$(CMAKE_COMMAND) -E cmake_unimplemented_variable ", + preprocessRuleVar); commands.push_back(std::move(cmd)); } @@ -893,20 +875,17 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( std::string relativeObjS = relativeObjBase + ".s"; std::string objS = objBase + ".s"; - std::string assemblyEcho = "Compiling "; - assemblyEcho += lang; - assemblyEcho += " source to assembly "; - assemblyEcho += objS; + std::string assemblyEcho = + cmStrCat("Compiling ", lang, " source to assembly ", objS); this->LocalGenerator->AppendEcho( commands, assemblyEcho, cmLocalUnixMakefileGenerator3::EchoBuild); - std::string assemblyRuleVar = "CMAKE_"; - assemblyRuleVar += lang; - assemblyRuleVar += "_CREATE_ASSEMBLY_SOURCE"; + std::string assemblyRuleVar = + cmStrCat("CMAKE_", lang, "_CREATE_ASSEMBLY_SOURCE"); if (const char* assemblyRule = this->Makefile->GetDefinition(assemblyRuleVar)) { - std::vector<std::string> assemblyCommands; - cmSystemTools::ExpandListArgument(assemblyRule, assemblyCommands); + std::vector<std::string> assemblyCommands = + cmExpandedList(assemblyRule); std::string shellObjS = this->LocalGenerator->ConvertToOutputFormat( objS, cmOutputConverter::SHELL); @@ -924,8 +903,9 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( this->LocalGenerator->GetBinaryDirectory()); cmAppend(commands, assemblyCommands); } else { - std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable "; - cmd += assemblyRuleVar; + std::string cmd = + cmStrCat("$(CMAKE_COMMAND) -E cmake_unimplemented_variable ", + assemblyRuleVar); commands.push_back(std::move(cmd)); } @@ -942,9 +922,9 @@ void cmMakefileTargetGenerator::WriteTargetCleanRules() std::vector<std::string> commands; // Construct the clean target name. - std::string cleanTarget = - this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget); - cleanTarget += "/clean"; + std::string cleanTarget = cmStrCat( + this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget), + "/clean"); // Construct the clean command. this->LocalGenerator->AppendCleanCommand(commands, this->CleanFiles, @@ -1028,15 +1008,14 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() // must write the targets depend info file std::string dir = this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); - this->InfoFileNameFull = dir; - this->InfoFileNameFull += "/DependInfo.cmake"; + this->InfoFileNameFull = cmStrCat(dir, "/DependInfo.cmake"); this->InfoFileNameFull = this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull); this->InfoFileStream = new cmGeneratedFileStream(this->InfoFileNameFull); - this->InfoFileStream->SetCopyIfDifferent(true); - if (!*this->InfoFileStream) { + if (!this->InfoFileStream) { return; } + this->InfoFileStream->SetCopyIfDifferent(true); this->LocalGenerator->WriteDependLanguageInfo(*this->InfoFileStream, this->GeneratorTarget); @@ -1088,9 +1067,9 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() std::vector<std::string> commands; // Construct the name of the dependency generation target. - std::string depTarget = - this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget); - depTarget += "/depend"; + std::string depTarget = cmStrCat( + this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget), + "/depend"); // Add a command to call CMake to scan dependencies. CMake will // touch the corresponding depends file after scanning dependencies. @@ -1181,7 +1160,7 @@ void cmMakefileTargetGenerator::WriteObjectDependRules( // shared between the object file and dependency scanning rule. depends.push_back(source.GetFullPath()); if (const char* objectDeps = source.GetProperty("OBJECT_DEPENDS")) { - cmSystemTools::ExpandListArgument(objectDeps, depends); + cmExpandList(objectDeps, depends); } } @@ -1235,8 +1214,8 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile( void cmMakefileTargetGenerator::MakeEchoProgress( cmLocalUnixMakefileGenerator3::EchoProgress& progress) const { - progress.Dir = this->LocalGenerator->GetBinaryDirectory(); - progress.Dir += "/CMakeFiles"; + progress.Dir = + cmStrCat(this->LocalGenerator->GetBinaryDirectory(), "/CMakeFiles"); std::ostringstream progressArg; progressArg << "$(CMAKE_PROGRESS_" << this->NumberOfProgressActions << ")"; progress.Arg = progressArg.str(); @@ -1370,8 +1349,8 @@ void cmMakefileTargetGenerator::WriteTargetDriverRule( // Compute the name of the driver target. std::string dir = this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget); - std::string buildTargetRuleName = dir; - buildTargetRuleName += relink ? "/preinstall" : "/build"; + std::string buildTargetRuleName = + cmStrCat(dir, relink ? "/preinstall" : "/build"); buildTargetRuleName = this->LocalGenerator->MaybeConvertToRelativePath( this->LocalGenerator->GetBinaryDirectory(), buildTargetRuleName); @@ -1426,8 +1405,7 @@ void cmMakefileTargetGenerator::AppendObjectDepends( std::string const& relPath = this->LocalGenerator->GetHomeRelativeOutputPath(); for (std::string const& obj : this->Objects) { - std::string objTarget = relPath; - objTarget += obj; + std::string objTarget = cmStrCat(relPath, obj); depends.push_back(std::move(objTarget)); } @@ -1473,9 +1451,9 @@ std::string cmMakefileTargetGenerator::GetLinkRule( { std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar); if (this->GeneratorTarget->HasImplibGNUtoMS(this->ConfigName)) { - std::string ruleVar = "CMAKE_"; - ruleVar += this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); - ruleVar += "_GNUtoMS_RULE"; + std::string ruleVar = cmStrCat( + "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName), + "_GNUtoMS_RULE"); if (const char* rule = this->Makefile->GetDefinition(ruleVar)) { linkRule += rule; } @@ -1496,9 +1474,8 @@ void cmMakefileTargetGenerator::CreateLinkScript( std::vector<std::string>& makefile_depends) { // Create the link script file. - std::string linkScriptName = this->TargetBuildDirectoryFull; - linkScriptName += "/"; - linkScriptName += name; + std::string linkScriptName = + cmStrCat(this->TargetBuildDirectoryFull, '/', name); cmGeneratedFileStream linkScriptStream(linkScriptName); linkScriptStream.SetCopyIfDifferent(true); for (std::string const& link_command : link_commands) { @@ -1510,12 +1487,13 @@ void cmMakefileTargetGenerator::CreateLinkScript( } // Create the makefile command to invoke the link script. - std::string link_command = "$(CMAKE_COMMAND) -E cmake_link_script "; - link_command += this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), linkScriptName), - cmOutputConverter::SHELL); - link_command += " --verbose=$(VERBOSE)"; + std::string link_command = cmStrCat( + "$(CMAKE_COMMAND) -E cmake_link_script ", + this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetCurrentBinaryDirectory(), linkScriptName), + cmOutputConverter::SHELL), + " --verbose=$(VERBOSE)"); makefile_commands.push_back(std::move(link_command)); makefile_depends.push_back(std::move(linkScriptName)); } @@ -1528,7 +1506,7 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects( "CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_OBJECTS"; if (const char* val = this->Makefile->GetDefinition(responseVar)) { if (*val) { - return cmSystemTools::IsOn(val); + return cmIsOn(val); } } @@ -1567,7 +1545,7 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForLibraries( "CMAKE_" + l + "_USE_RESPONSE_FILE_FOR_LIBRARIES"; if (const char* val = this->Makefile->GetDefinition(responseVar)) { if (*val) { - return cmSystemTools::IsOn(val); + return cmIsOn(val); } } @@ -1580,9 +1558,8 @@ std::string cmMakefileTargetGenerator::CreateResponseFile( std::vector<std::string>& makefile_depends) { // Create the response file. - std::string responseFileNameFull = this->TargetBuildDirectoryFull; - responseFileNameFull += "/"; - responseFileNameFull += name; + std::string responseFileNameFull = + cmStrCat(this->TargetBuildDirectoryFull, '/', name); cmGeneratedFileStream responseStream(responseFileNameFull); responseStream.SetCopyIfDifferent(true); responseStream << options << "\n"; @@ -1592,9 +1569,8 @@ std::string cmMakefileTargetGenerator::CreateResponseFile( makefile_depends.push_back(std::move(responseFileNameFull)); // Construct the name to be used on the command line. - std::string responseFileName = this->TargetBuildDirectory; - responseFileName += "/"; - responseFileName += name; + std::string responseFileName = + cmStrCat(this->TargetBuildDirectory, '/', name); return responseFileName; } @@ -1626,10 +1602,9 @@ void cmMakefileTargetGenerator::CreateLinkLibs( if (useResponseFile && linkLibs.find_first_not_of(' ') != std::string::npos) { // Lookup the response file reference flag. - std::string responseFlagVar = "CMAKE_"; - responseFlagVar += - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); - responseFlagVar += "_RESPONSE_FILE_LINK_FLAG"; + std::string responseFlagVar = cmStrCat( + "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName), + "_RESPONSE_FILE_LINK_FLAG"); const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar); if (!responseFlag) { responseFlag = "@"; @@ -1640,9 +1615,9 @@ void cmMakefileTargetGenerator::CreateLinkLibs( this->CreateResponseFile("linklibs.rsp", linkLibs, makefile_depends); // Reference the response file. - linkLibs = responseFlag; - linkLibs += this->LocalGenerator->ConvertToOutputFormat( - link_rsp, cmOutputConverter::SHELL); + linkLibs = cmStrCat(responseFlag, + this->LocalGenerator->ConvertToOutputFormat( + link_rsp, cmOutputConverter::SHELL)); } } @@ -1664,10 +1639,9 @@ void cmMakefileTargetGenerator::CreateObjectLists( this->WriteObjectsStrings(object_strings, responseFileLimit); // Lookup the response file reference flag. - std::string responseFlagVar = "CMAKE_"; - responseFlagVar += - this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); - responseFlagVar += "_RESPONSE_FILE_LINK_FLAG"; + std::string responseFlagVar = cmStrCat( + "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName), + "_RESPONSE_FILE_LINK_FLAG"); const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar); if (!responseFlag) { responseFlag = "@"; @@ -1700,20 +1674,16 @@ void cmMakefileTargetGenerator::CreateObjectLists( buildObjs = objStrings[0]; } } else { - buildObjs = "$("; - buildObjs += variableName; - buildObjs += ") $("; - buildObjs += variableNameExternal; - buildObjs += ")"; + buildObjs = + cmStrCat("$(", variableName, ") $(", variableNameExternal, ')'); } } void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, const std::string& lang) { - std::string responseVar = "CMAKE_"; - responseVar += lang; - responseVar += "_USE_RESPONSE_FILE_FOR_INCLUDES"; + std::string responseVar = + cmStrCat("CMAKE_", lang, "_USE_RESPONSE_FILE_FOR_INCLUDES"); bool useResponseFile = this->Makefile->IsOn(responseVar); std::vector<std::string> includes; @@ -1736,9 +1706,7 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, if (responseFlag.empty()) { responseFlag = "@"; } - std::string name = "includes_"; - name += lang; - name += ".rsp"; + std::string name = cmStrCat("includes_", lang, ".rsp"); std::string arg = std::move(responseFlag) + this->CreateResponseFile(name.c_str(), includeFlags, this->FlagFileDepends[lang]); @@ -1757,14 +1725,14 @@ void cmMakefileTargetGenerator::GenDefFile( return; } std::string cmd = cmSystemTools::GetCMakeCommand(); - cmd = - this->LocalGenerator->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL); - cmd += " -E __create_def "; - cmd += this->LocalGenerator->ConvertToOutputFormat( - this->LocalGenerator->MaybeConvertToRelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), mdi->DefFile), - cmOutputConverter::SHELL); - cmd += " "; + cmd = cmStrCat( + this->LocalGenerator->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL), + " -E __create_def ", + this->LocalGenerator->ConvertToOutputFormat( + this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetCurrentBinaryDirectory(), mdi->DefFile), + cmOutputConverter::SHELL), + ' '); std::string objlist_file = mdi->DefFile + ".objs"; cmd += this->LocalGenerator->ConvertToOutputFormat( this->LocalGenerator->MaybeConvertToRelativePath( diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index c570a7c..9eeeed0 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -7,6 +7,7 @@ #include <iosfwd> #include <map> +#include <memory> #include <set> #include <string> #include <vector> diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index 4236995..8ed6be5 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/Source/cmMakefileUtilityTargetGenerator.cxx @@ -7,7 +7,8 @@ #include <utility> #include <vector> -#include "cmAlgorithms.h" +#include "cm_memory.hxx" + #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmGlobalUnixMakefileGenerator3.h" diff --git a/Source/cmMarkAsAdvancedCommand.cxx b/Source/cmMarkAsAdvancedCommand.cxx index 45c59b9..ca46e14 100644 --- a/Source/cmMarkAsAdvancedCommand.cxx +++ b/Source/cmMarkAsAdvancedCommand.cxx @@ -2,20 +2,19 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMarkAsAdvancedCommand.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmake.h" -class cmExecutionStatus; - // cmMarkAsAdvancedCommand -bool cmMarkAsAdvancedCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmMarkAsAdvancedCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } @@ -31,9 +30,9 @@ bool cmMarkAsAdvancedCommand::InitialPass(std::vector<std::string> const& args, } for (; i < args.size(); ++i) { std::string const& variable = args[i]; - cmState* state = this->Makefile->GetState(); + cmState* state = status.GetMakefile().GetState(); if (!state->GetCacheEntryValue(variable)) { - this->Makefile->GetCMakeInstance()->AddCacheEntry( + status.GetMakefile().GetCMakeInstance()->AddCacheEntry( variable, nullptr, nullptr, cmStateEnums::UNINITIALIZED); overwrite = true; } diff --git a/Source/cmMarkAsAdvancedCommand.h b/Source/cmMarkAsAdvancedCommand.h index 5dd198f..de7bf08 100644 --- a/Source/cmMarkAsAdvancedCommand.h +++ b/Source/cmMarkAsAdvancedCommand.h @@ -8,29 +8,14 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmMarkAsAdvancedCommand +/** * \brief mark_as_advanced command * * cmMarkAsAdvancedCommand implements the mark_as_advanced CMake command */ -class cmMarkAsAdvancedCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmMarkAsAdvancedCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmMarkAsAdvancedCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmMathCommand.cxx b/Source/cmMathCommand.cxx index 48b9a27..83c22aa 100644 --- a/Source/cmMathCommand.cxx +++ b/Source/cmMathCommand.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMathCommand.h" +#include "cmExecutionStatus.h" #include "cmExprParserHelper.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -9,28 +10,33 @@ #include <stdio.h> -class cmExecutionStatus; +namespace { +bool HandleExprCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); +} -bool cmMathCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmMathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("must be called with at least one argument."); + status.SetError("must be called with at least one argument."); return false; } const std::string& subCommand = args[0]; if (subCommand == "EXPR") { - return this->HandleExprCommand(args); + return HandleExprCommand(args, status); } std::string e = "does not recognize sub-command " + subCommand; - this->SetError(e); + status.SetError(e); return false; } -bool cmMathCommand::HandleExprCommand(std::vector<std::string> const& args) +namespace { +bool HandleExprCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if ((args.size() != 3) && (args.size() != 5)) { - this->SetError("EXPR called with incorrect arguments."); + status.SetError("EXPR called with incorrect arguments."); return false; } @@ -46,7 +52,7 @@ bool cmMathCommand::HandleExprCommand(std::vector<std::string> const& args) size_t argumentIndex = 3; NumericFormat outputFormat = NumericFormat::UNINITIALIZED; - this->Makefile->AddDefinition(outputVariable, "ERROR"); + status.GetMakefile().AddDefinition(outputVariable, "ERROR"); if (argumentIndex < args.size()) { const std::string messageHint = "sub-command EXPR "; @@ -61,19 +67,19 @@ bool cmMathCommand::HandleExprCommand(std::vector<std::string> const& args) } else { std::string error = messageHint + "value \"" + argument + "\" for option \"" + option + "\" is invalid."; - this->SetError(error); + status.SetError(error); return false; } } else { std::string error = messageHint + "missing argument for option \"" + option + "\"."; - this->SetError(error); + status.SetError(error); return false; } } else { std::string error = messageHint + "option \"" + option + "\" is unknown."; - this->SetError(error); + status.SetError(error); return false; } } @@ -84,7 +90,7 @@ bool cmMathCommand::HandleExprCommand(std::vector<std::string> const& args) cmExprParserHelper helper; if (!helper.ParseString(expression.c_str(), 0)) { - this->SetError(helper.GetError()); + status.SetError(helper.GetError()); return false; } @@ -104,9 +110,10 @@ bool cmMathCommand::HandleExprCommand(std::vector<std::string> const& args) std::string const& w = helper.GetWarning(); if (!w.empty()) { - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w); + status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, w); } - this->Makefile->AddDefinition(outputVariable, buffer); + status.GetMakefile().AddDefinition(outputVariable, buffer); return true; } +} diff --git a/Source/cmMathCommand.h b/Source/cmMathCommand.h index 0c6c76b..ac1957c 100644 --- a/Source/cmMathCommand.h +++ b/Source/cmMathCommand.h @@ -8,28 +8,10 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; /// Mathematical expressions: math(EXPR ...) command. -class cmMathCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmMathCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -protected: - bool HandleExprCommand(std::vector<std::string> const& args); -}; +bool cmMathCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx index 5320ec5..39b40b8 100644 --- a/Source/cmMessageCommand.cxx +++ b/Source/cmMessageCommand.cxx @@ -2,30 +2,28 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMessageCommand.h" -#include "cmAlgorithms.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmMessenger.h" #include "cmRange.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" #include <cassert> -class cmExecutionStatus; - // cmLibraryCommand -bool cmMessageCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmMessageCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } auto i = args.cbegin(); auto type = MessageType::MESSAGE; - auto status = false; auto fatal = false; auto level = cmake::LogLevel::LOG_UNDEFINED; if (*i == "SEND_ERROR") { @@ -42,12 +40,13 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args, level = cmake::LogLevel::LOG_WARNING; ++i; } else if (*i == "AUTHOR_WARNING") { - if (this->Makefile->IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") && - !this->Makefile->IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) { + if (status.GetMakefile().IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") && + !status.GetMakefile().IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) { fatal = true; type = MessageType::AUTHOR_ERROR; level = cmake::LogLevel::LOG_ERROR; - } else if (!this->Makefile->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) { + } else if (!status.GetMakefile().IsOn( + "CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) { type = MessageType::AUTHOR_WARNING; level = cmake::LogLevel::LOG_WARNING; } else { @@ -55,28 +54,24 @@ 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") { - if (this->Makefile->IsOn("CMAKE_ERROR_DEPRECATED")) { + if (status.GetMakefile().IsOn("CMAKE_ERROR_DEPRECATED")) { fatal = true; type = MessageType::DEPRECATION_ERROR; level = cmake::LogLevel::LOG_ERROR; - } else if ((!this->Makefile->IsSet("CMAKE_WARN_DEPRECATED") || - this->Makefile->IsOn("CMAKE_WARN_DEPRECATED"))) { + } else if (!status.GetMakefile().IsSet("CMAKE_WARN_DEPRECATED") || + status.GetMakefile().IsOn("CMAKE_WARN_DEPRECATED")) { type = MessageType::DEPRECATION_WARNING; level = cmake::LogLevel::LOG_WARNING; } else { @@ -94,7 +89,7 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args, assert("Message log level expected to be set" && level != cmake::LogLevel::LOG_UNDEFINED); - auto desiredLevel = this->Makefile->GetCMakeInstance()->GetLogLevel(); + auto desiredLevel = status.GetMakefile().GetCMakeInstance()->GetLogLevel(); assert("Expected a valid log level here" && desiredLevel != cmake::LogLevel::LOG_UNDEFINED); @@ -105,17 +100,45 @@ 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(cmExpandedList(status.GetMakefile().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 + status.GetMakefile().GetMessenger()->DisplayMessage( + type, message, status.GetMakefile().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: + status.GetMakefile().DisplayStatus(message, -1); + break; + + default: + assert("Unexpected log level! Review the `cmMessageCommand.cxx`." && + false); + break; } + if (fatal) { cmSystemTools::SetFatalErrorOccured(); } diff --git a/Source/cmMessageCommand.h b/Source/cmMessageCommand.h index 819ebda..7d544c4 100644 --- a/Source/cmMessageCommand.h +++ b/Source/cmMessageCommand.h @@ -8,28 +8,13 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmMessageCommand +/** * \brief Displays a message to the user * */ -class cmMessageCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmMessageCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmMessageCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx index 1d790e2..af83478 100644 --- a/Source/cmMessenger.cxx +++ b/Source/cmMessenger.cxx @@ -2,11 +2,11 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMessenger.h" -#include "cmAlgorithms.h" #include "cmDocumentationFormatter.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) # include "cmsys/SystemInformation.hxx" #endif @@ -100,14 +100,13 @@ void displayMessage(MessageType t, std::ostringstream& msg) "it."; } else if (t == MessageType::AUTHOR_ERROR) { msg << "This error is for project developers. Use -Wno-error=dev to " - "suppress " - "it."; + "suppress it."; } // Add a terminating blank line. msg << "\n"; -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) // Add a C++ stack trace to internal errors. if (t == MessageType::INTERNAL_ERROR) { std::string stack = cmsys::SystemInformation::GetProgramStack(0, 0); diff --git a/Source/cmNewLineStyle.cxx b/Source/cmNewLineStyle.cxx index 3f6523e..1ff741e 100644 --- a/Source/cmNewLineStyle.cxx +++ b/Source/cmNewLineStyle.cxx @@ -41,7 +41,7 @@ bool cmNewLineStyle::ReadFromArguments(const std::vector<std::string>& args, return true; } -const std::string cmNewLineStyle::GetCharacters() const +std::string cmNewLineStyle::GetCharacters() const { switch (NewLineStyle) { case Invalid: diff --git a/Source/cmNewLineStyle.h b/Source/cmNewLineStyle.h index f1a7bc6..ab9002e 100644 --- a/Source/cmNewLineStyle.h +++ b/Source/cmNewLineStyle.h @@ -30,7 +30,7 @@ public: bool ReadFromArguments(const std::vector<std::string>& args, std::string& errorString); - const std::string GetCharacters() const; + std::string GetCharacters() const; private: Style NewLineStyle = Invalid; diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index f65abc8..17a5527 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -6,11 +6,12 @@ #include <assert.h> #include <iterator> #include <map> -#include <memory> // IWYU pragma: keep #include <set> #include <sstream> #include <utility> +#include "cm_memory.hxx" + #include "cmAlgorithms.h" #include "cmCustomCommand.h" // IWYU pragma: keep #include "cmCustomCommandGenerator.h" @@ -32,6 +33,7 @@ #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator( @@ -85,6 +87,7 @@ void cmNinjaNormalTargetGenerator::Generate() this->WriteLinkStatement(); } + // Find ADDITIONAL_CLEAN_FILES this->AdditionalCleanFiles(); } @@ -216,8 +219,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile) const char* val = this->GetLocalGenerator()->GetRuleLauncher( this->GetGeneratorTarget(), "RULE_LAUNCH_LINK"); if (val && *val) { - launcher = val; - launcher += " "; + launcher = cmStrCat(val, ' '); } std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( @@ -226,7 +228,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile) // Rule for linking library/executable. std::vector<std::string> linkCmds = this->ComputeDeviceLinkCmd(); for (std::string& linkCmd : linkCmds) { - linkCmd = launcher + linkCmd; + linkCmd = cmStrCat(launcher, linkCmd); rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), linkCmd, vars); } @@ -237,16 +239,10 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile) rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds); // Write the linker rule with response file if needed. - rule.Comment = "Rule for linking "; - rule.Comment += this->TargetLinkLanguage; - rule.Comment += " "; - rule.Comment += this->GetVisibleTypeName(); - rule.Comment += "."; - rule.Description = "Linking "; - rule.Description += this->TargetLinkLanguage; - rule.Description += " "; - rule.Description += this->GetVisibleTypeName(); - rule.Description += " $TARGET_FILE"; + rule.Comment = cmStrCat("Rule for linking ", this->TargetLinkLanguage, ' ', + this->GetVisibleTypeName(), '.'); + rule.Description = cmStrCat("Linking ", this->TargetLinkLanguage, ' ', + this->GetVisibleTypeName(), " $TARGET_FILE"); rule.Restat = "$RESTAT"; this->GetGlobalGenerator()->AddRule(rule); @@ -280,8 +276,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) std::string responseFlag; - std::string cmakeVarLang = "CMAKE_"; - cmakeVarLang += this->TargetLinkLanguage; + std::string cmakeVarLang = cmStrCat("CMAKE_", this->TargetLinkLanguage); // build response file name std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG"; @@ -355,8 +350,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) const char* val = this->GetLocalGenerator()->GetRuleLauncher( this->GetGeneratorTarget(), "RULE_LAUNCH_LINK"); if (val && *val) { - launcher = val; - launcher += " "; + launcher = cmStrCat(val, ' '); } std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( @@ -365,7 +359,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) // Rule for linking library/executable. std::vector<std::string> linkCmds = this->ComputeLinkCmd(); for (std::string& linkCmd : linkCmds) { - linkCmd = launcher + linkCmd; + linkCmd = cmStrCat(launcher, linkCmd); rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), linkCmd, vars); } @@ -378,16 +372,10 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds); // Write the linker rule with response file if needed. - rule.Comment = "Rule for linking "; - rule.Comment += this->TargetLinkLanguage; - rule.Comment += " "; - rule.Comment += this->GetVisibleTypeName(); - rule.Comment += "."; - rule.Description = "Linking "; - rule.Description += this->TargetLinkLanguage; - rule.Description += " "; - rule.Description += this->GetVisibleTypeName(); - rule.Description += " $TARGET_FILE"; + rule.Comment = cmStrCat("Rule for linking ", this->TargetLinkLanguage, ' ', + this->GetVisibleTypeName(), '.'); + rule.Description = cmStrCat("Linking ", this->TargetLinkLanguage, ' ', + this->GetVisibleTypeName(), " $TARGET_FILE"); rule.Restat = "$RESTAT"; this->GetGlobalGenerator()->AddRule(rule); } @@ -438,12 +426,12 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeDeviceLinkCmd() case cmStateEnums::MODULE_LIBRARY: { const std::string cudaLinkCmd( this->GetMakefile()->GetDefinition("CMAKE_CUDA_DEVICE_LINK_LIBRARY")); - cmSystemTools::ExpandListArgument(cudaLinkCmd, linkCmds); + cmExpandList(cudaLinkCmd, linkCmds); } break; case cmStateEnums::EXECUTABLE: { const std::string cudaLinkCmd(this->GetMakefile()->GetDefinition( "CMAKE_CUDA_DEVICE_LINK_EXECUTABLE")); - cmSystemTools::ExpandListArgument(cudaLinkCmd, linkCmds); + cmExpandList(cudaLinkCmd, linkCmds); } break; default: break; @@ -465,19 +453,19 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() if (linkCmd) { std::string linkCmdStr = linkCmd; if (this->GetGeneratorTarget()->HasImplibGNUtoMS(this->ConfigName)) { - std::string ruleVar = "CMAKE_"; - ruleVar += this->GeneratorTarget->GetLinkerLanguage(this->ConfigName); - ruleVar += "_GNUtoMS_RULE"; + std::string ruleVar = cmStrCat( + "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName), + "_GNUtoMS_RULE"); if (const char* rule = this->Makefile->GetDefinition(ruleVar)) { linkCmdStr += rule; } } - cmSystemTools::ExpandListArgument(linkCmdStr, linkCmds); + cmExpandList(linkCmdStr, linkCmds); if (this->GetGeneratorTarget()->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { - std::string cmakeCommand = + std::string cmakeCommand = cmStrCat( this->GetLocalGenerator()->ConvertToOutputFormat( - cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); - cmakeCommand += " -E __run_co_compile --lwyu="; + cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), + " -E __run_co_compile --lwyu="); cmGeneratorTarget& gt = *this->GetGeneratorTarget(); const std::string cfgName = this->GetConfigName(); std::string targetOutputReal = this->ConvertToNinjaPath( @@ -500,26 +488,24 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() } // TODO: Use ARCHIVE_APPEND for archives over a certain size. { - std::string linkCmdVar = "CMAKE_"; - linkCmdVar += this->TargetLinkLanguage; - linkCmdVar += "_ARCHIVE_CREATE"; + std::string linkCmdVar = + cmStrCat("CMAKE_", this->TargetLinkLanguage, "_ARCHIVE_CREATE"); linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( linkCmdVar, this->TargetLinkLanguage, this->GetConfigName()); std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar); - cmSystemTools::ExpandListArgument(linkCmd, linkCmds); + cmExpandList(linkCmd, linkCmds); } { - std::string linkCmdVar = "CMAKE_"; - linkCmdVar += this->TargetLinkLanguage; - linkCmdVar += "_ARCHIVE_FINISH"; + std::string linkCmdVar = + cmStrCat("CMAKE_", this->TargetLinkLanguage, "_ARCHIVE_FINISH"); linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable( linkCmdVar, this->TargetLinkLanguage, this->GetConfigName()); std::string const& linkCmd = mf->GetRequiredDefinition(linkCmdVar); - cmSystemTools::ExpandListArgument(linkCmd, linkCmds); + cmExpandList(linkCmd, linkCmds); } #ifdef __APPLE__ // On macOS ranlib truncates the fractional part of the static archive @@ -588,10 +574,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement() // Compute the comment. cmNinjaBuild build(this->LanguageLinkerDeviceRule()); - build.Comment = "Link the "; - build.Comment += this->GetVisibleTypeName(); - build.Comment += " "; - build.Comment += targetOutputReal; + build.Comment = + cmStrCat("Link the ", this->GetVisibleTypeName(), ' ', targetOutputReal); cmNinjaVars& vars = build.Variables; @@ -726,13 +710,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() outpath); // Calculate the output path - targetOutput = outpath; - targetOutput += "/"; - targetOutput += this->TargetNames.Output; + targetOutput = cmStrCat(outpath, '/', this->TargetNames.Output); targetOutput = this->ConvertToNinjaPath(targetOutput); - targetOutputReal = outpath; - targetOutputReal += "/"; - targetOutputReal += this->TargetNames.Real; + targetOutputReal = cmStrCat(outpath, '/', this->TargetNames.Real); targetOutputReal = this->ConvertToNinjaPath(targetOutputReal); } else if (gt->IsFrameworkOnApple()) { // Create the library framework. @@ -755,10 +735,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() cmNinjaVars& vars = linkBuild.Variables; // Compute the comment. - linkBuild.Comment = "Link the "; - linkBuild.Comment += this->GetVisibleTypeName(); - linkBuild.Comment += " "; - linkBuild.Comment += targetOutputReal; + linkBuild.Comment = + cmStrCat("Link the ", this->GetVisibleTypeName(), ' ', targetOutputReal); // Compute outputs. linkBuild.Outputs.push_back(targetOutputReal); @@ -965,7 +943,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() >->GetPostBuildCommands() }; - std::vector<std::string> preLinkCmdLines, postBuildCmdLines; + std::vector<std::string> preLinkCmdLines; + std::vector<std::string> postBuildCmdLines; std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines, &preLinkCmdLines, &postBuildCmdLines }; @@ -987,11 +966,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() std::string cmakeCommand = this->GetLocalGenerator()->ConvertToOutputFormat( cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL); - std::string cmd = cmakeCommand; - cmd += " -E __create_def "; - cmd += this->GetLocalGenerator()->ConvertToOutputFormat( - mdi->DefFile, cmOutputConverter::SHELL); - cmd += " "; + std::string cmd = + cmStrCat(cmakeCommand, " -E __create_def ", + this->GetLocalGenerator()->ConvertToOutputFormat( + mdi->DefFile, cmOutputConverter::SHELL), + ' '); std::string obj_list_file = mdi->DefFile + ".objs"; cmd += this->GetLocalGenerator()->ConvertToOutputFormat( obj_list_file, cmOutputConverter::SHELL); @@ -1036,8 +1015,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() symlinkVars["POST_BUILD"] = postBuildCmdLine; } - std::string cmakeVarLang = "CMAKE_"; - cmakeVarLang += this->TargetLinkLanguage; + std::string cmakeVarLang = cmStrCat("CMAKE_", this->TargetLinkLanguage); // build response file name std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG"; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 2139a45..3d3d80d 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -8,10 +8,11 @@ #include <assert.h> #include <iterator> #include <map> -#include <memory> // IWYU pragma: keep #include <ostream> #include <utility> +#include "cm_memory.hxx" + #include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" #include "cmCustomCommandGenerator.h" @@ -30,6 +31,7 @@ #include "cmSourceFile.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" @@ -217,8 +219,8 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source, defines, genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS)); } - std::string defPropName = "COMPILE_DEFINITIONS_"; - defPropName += cmSystemTools::UpperCase(config); + std::string defPropName = + cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config)); if (const char* config_compile_defs = source->GetProperty(defPropName)) { this->LocalGenerator->AppendDefines( defines, @@ -372,10 +374,10 @@ std::string cmNinjaTargetGenerator::GetDyndepFilePath( std::string cmNinjaTargetGenerator::GetTargetDependInfoPath( std::string const& lang) const { - std::string path = this->Makefile->GetCurrentBinaryDirectory(); - path += "/"; - path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); - path += "/" + lang + "DependInfo.json"; + std::string path = + cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), + '/', lang, "DependInfo.json"); return path; } @@ -414,9 +416,9 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY || this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) { - pdbPath = this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()); - pdbPath += "/"; - pdbPath += this->GeneratorTarget->GetPDBName(this->GetConfigName()); + pdbPath = cmStrCat( + this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()), '/', + this->GeneratorTarget->GetPDBName(this->GetConfigName())); } vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat( @@ -486,8 +488,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) const char* val = this->GetLocalGenerator()->GetRuleLauncher( this->GetGeneratorTarget(), "RULE_LAUNCH_COMPILE"); if (val && *val) { - launcher = val; - launcher += " "; + launcher = cmStrCat(val, ' '); } std::string const cmakeCmd = @@ -527,12 +528,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) // If using a response file, move defines, includes, and flags into it. if (!responseFlag.empty()) { rule.RspFile = "$RSP_FILE"; - rule.RspContent = " "; - rule.RspContent += ppVars.Defines; - rule.RspContent += " "; - rule.RspContent += ppVars.Includes; - rule.RspContent += " "; - rule.RspContent += ppFlags; + rule.RspContent = + cmStrCat(' ', ppVars.Defines, ' ', ppVars.Includes, ' ', ppFlags); ppFlags = responseFlag + rule.RspFile; ppVars.Defines = ""; ppVars.Includes = ""; @@ -544,26 +541,21 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) std::vector<std::string> ppCmds; { // Lookup the explicit preprocessing rule. - std::string ppVar = "CMAKE_" + lang; - ppVar += "_PREPROCESS_SOURCE"; - cmSystemTools::ExpandListArgument( - this->GetMakefile()->GetRequiredDefinition(ppVar), ppCmds); + std::string ppVar = cmStrCat("CMAKE_", lang, "_PREPROCESS_SOURCE"); + cmExpandList(this->GetMakefile()->GetRequiredDefinition(ppVar), ppCmds); } for (std::string& i : ppCmds) { - i = launcher + i; + i = cmStrCat(launcher, i); rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), i, ppVars); } // Run CMake dependency scanner on preprocessed output. { - std::string ccmd = cmakeCmd; - ccmd += " -E cmake_ninja_depends --tdi="; - ccmd += tdi; - ccmd += " --lang="; - ccmd += lang; - ccmd += " --pp=$out --dep=$DEP_FILE"; + std::string ccmd = + cmStrCat(cmakeCmd, " -E cmake_ninja_depends --tdi=", tdi, + " --lang=", lang, " --pp=$out --dep=$DEP_FILE"); if (needDyndep) { ccmd += " --obj=$OBJ_FILE --ddi=$DYNDEP_INTERMEDIATE_FILE"; } @@ -572,12 +564,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) rule.Command = this->GetLocalGenerator()->BuildCommandLine(ppCmds); // Write the rule for preprocessing file of the given language. - rule.Comment = "Rule for preprocessing "; - rule.Comment += lang; - rule.Comment += " files."; - rule.Description = "Building "; - rule.Description += lang; - rule.Description += " preprocessed $out"; + rule.Comment = cmStrCat("Rule for preprocessing ", lang, " files."); + rule.Description = cmStrCat("Building ", lang, " preprocessed $out"); this->GetGlobalGenerator()->AddRule(rule); } @@ -594,24 +582,16 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) { std::vector<std::string> ddCmds; { - std::string ccmd = cmakeCmd; - ccmd += " -E cmake_ninja_dyndep --tdi="; - ccmd += tdi; - ccmd += " --lang="; - ccmd += lang; - ccmd += " --dd=$out "; - ccmd += "@"; - ccmd += rule.RspFile; + std::string ccmd = + cmStrCat(cmakeCmd, " -E cmake_ninja_dyndep --tdi=", tdi, + " --lang=", lang, " --dd=$out @", rule.RspFile); ddCmds.emplace_back(std::move(ccmd)); } rule.Command = this->GetLocalGenerator()->BuildCommandLine(ddCmds); } - rule.Comment = "Rule to generate ninja dyndep files for "; - rule.Comment += lang; - rule.Comment += "."; - rule.Description = "Generating "; - rule.Description += lang; - rule.Description += " dyndep file $out"; + rule.Comment = + cmStrCat("Rule to generate ninja dyndep files for ", lang, '.'); + rule.Description = cmStrCat("Generating ", lang, " dyndep file $out"); this->GetGlobalGenerator()->AddRule(rule); } @@ -619,12 +599,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) // If using a response file, move defines, includes, and flags into it. if (!responseFlag.empty()) { rule.RspFile = "$RSP_FILE"; - rule.RspContent = " "; - rule.RspContent += vars.Defines; - rule.RspContent += " "; - rule.RspContent += vars.Includes; - rule.RspContent += " "; - rule.RspContent += flags; + rule.RspContent = + cmStrCat(' ', vars.Defines, ' ', vars.Includes, ' ', flags); flags = responseFlag + rule.RspFile; vars.Defines = ""; vars.Includes = ""; @@ -647,11 +623,10 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) const std::string cl = mf->GetDefinition("CMAKE_C_COMPILER") ? mf->GetSafeDefinition("CMAKE_C_COMPILER") : mf->GetSafeDefinition("CMAKE_CXX_COMPILER"); - cldeps = "\""; - cldeps += cmSystemTools::GetCMClDepsCommand(); - cldeps += "\" " + lang + " " + vars.Source + " $DEP_FILE $out \""; - cldeps += mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX"); - cldeps += "\" \"" + cl + "\" "; + cldeps = cmStrCat('"', cmSystemTools::GetCMClDepsCommand(), "\" ", lang, + ' ', vars.Source, " $DEP_FILE $out \"", + mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX"), + "\" \"", cl, "\" "); } } else { rule.DepType = "gcc"; @@ -684,11 +659,11 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) cmdVar = "CMAKE_CUDA_COMPILE_WHOLE_COMPILATION"; } const std::string& compileCmd = mf->GetRequiredDefinition(cmdVar); - cmSystemTools::ExpandListArgument(compileCmd, compileCmds); + cmExpandList(compileCmd, compileCmds); } else { const std::string cmdVar = "CMAKE_" + lang + "_COMPILE_OBJECT"; const std::string& compileCmd = mf->GetRequiredDefinition(cmdVar); - cmSystemTools::ExpandListArgument(compileCmd, compileCmds); + cmExpandList(compileCmd, compileCmds); } // See if we need to use a compiler launcher like ccache or distcc @@ -714,8 +689,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) const char* cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop); if ((iwyu && *iwyu) || (tidy && *tidy) || (cpplint && *cpplint) || (cppcheck && *cppcheck)) { - std::string run_iwyu = cmakeCmd; - run_iwyu += " -E __run_co_compile"; + std::string run_iwyu = cmStrCat(cmakeCmd, " -E __run_co_compile"); if (!compilerLauncher.empty()) { // In __run_co_compile case the launcher command is supplied // via --launcher=<maybe-list> and consumed @@ -751,8 +725,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) // If compiler launcher was specified and not consumed above, it // goes to the beginning of the command line. if (!compileCmds.empty() && !compilerLauncher.empty()) { - std::vector<std::string> args; - cmSystemTools::ExpandListArgument(compilerLauncher, args, true); + std::vector<std::string> args = cmExpandedList(compilerLauncher, true); if (!args.empty()) { args[0] = this->LocalGenerator->ConvertToOutputFormat( args[0], cmOutputConverter::SHELL); @@ -768,7 +741,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) } for (std::string& i : compileCmds) { - i = launcher + i; + i = cmStrCat(launcher, i); rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), i, vars); } @@ -776,12 +749,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) rule.Command = this->GetLocalGenerator()->BuildCommandLine(compileCmds); // Write the rule for compiling file of the given language. - rule.Comment = "Rule for compiling "; - rule.Comment += lang; - rule.Comment += " files."; - rule.Description = "Building "; - rule.Description += lang; - rule.Description += " object $out"; + rule.Comment = cmStrCat("Rule for compiling ", lang, " files."); + rule.Description = cmStrCat("Building ", lang, " object $out"); this->GetGlobalGenerator()->AddRule(rule); } @@ -863,11 +832,9 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() if (orderOnlyDeps.empty()) { // Any path that always exists will work here. It would be nice to // use just "." but that is not supported by Ninja < 1.7. - std::string tgtDir; - tgtDir += this->LocalGenerator->GetCurrentBinaryDirectory(); - tgtDir += "/"; - tgtDir += - this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); + std::string tgtDir = cmStrCat( + this->LocalGenerator->GetCurrentBinaryDirectory(), '/', + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget)); orderOnlyDeps.push_back(this->ConvertToNinjaPath(tgtDir)); } @@ -909,8 +876,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements() this->GetBuildFileStream() << "\n"; if (!this->SwiftOutputMap.empty()) { - std::string const mapFilePath = this->ConvertToNinjaPath( - this->GeneratorTarget->GetSupportDirectory() + "/output-file-map.json"); + std::string const mapFilePath = + this->GeneratorTarget->GetSupportDirectory() + "/output-file-map.json"; std::string const targetSwiftDepsPath = [this]() -> std::string { cmGeneratorTarget const* target = this->GeneratorTarget; if (const char* name = target->GetProperty("Swift_DEPENDENCIES_FILE")) { @@ -944,8 +911,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::string const objectFileDir = cmSystemTools::GetFilenamePath(objectFileName); - std::string cmakeVarLang = "CMAKE_"; - cmakeVarLang += language; + std::string cmakeVarLang = cmStrCat("CMAKE_", language); // build response file name std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_FLAG"; @@ -966,9 +932,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( if (!this->NeedDepTypeMSVC(language)) { bool replaceExt(false); if (!language.empty()) { - std::string repVar = "CMAKE_"; - repVar += language; - repVar += "_DEPFILE_EXTENSION_REPLACE"; + std::string repVar = + cmStrCat("CMAKE_", language, "_DEPFILE_EXTENSION_REPLACE"); replaceExt = this->Makefile->IsOn(repVar); } if (!replaceExt) { @@ -996,8 +961,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( objBuild.ExplicitDeps.push_back(sourceFileName); if (const char* objectDeps = source->GetProperty("OBJECT_DEPENDS")) { - std::vector<std::string> depList = - cmSystemTools::ExpandedListArgument(objectDeps); + std::vector<std::string> depList = cmExpandedList(objectDeps); for (std::string& odi : depList) { if (cmSystemTools::FileIsFullPath(odi)) { odi = cmSystemTools::CollapseFullPath(odi); @@ -1150,7 +1114,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( if (const char* objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) { cmNinjaBuild build("phony"); build.Comment = "Additional output files."; - build.Outputs = cmSystemTools::ExpandedListArgument(objectOutputs); + build.Outputs = cmExpandedList(objectOutputs); std::transform(build.Outputs.begin(), build.Outputs.end(), build.Outputs.begin(), MapToNinjaPath()); build.ExplicitDeps = objBuild.Outputs; @@ -1299,12 +1263,12 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand( } const std::string& compileCmd = this->GetMakefile()->GetRequiredDefinition(cmdVar); - cmSystemTools::ExpandListArgument(compileCmd, compileCmds); + cmExpandList(compileCmd, compileCmds); } else { const std::string cmdVar = "CMAKE_" + language + "_COMPILE_OBJECT"; const std::string& compileCmd = this->GetMakefile()->GetRequiredDefinition(cmdVar); - cmSystemTools::ExpandListArgument(compileCmd, compileCmds); + cmExpandList(compileCmd, compileCmds); } std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( @@ -1331,11 +1295,10 @@ void cmNinjaTargetGenerator::AdditionalCleanFiles() { cmGeneratorExpression ge; auto cge = ge.Parse(prop_value); - cmSystemTools::ExpandListArgument( - cge->Evaluate(lg, - this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"), - false, this->GeneratorTarget, nullptr, nullptr), - cleanFiles); + cmExpandList(cge->Evaluate( + lg, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"), + false, this->GeneratorTarget, nullptr, nullptr), + cleanFiles); } std::string const& binaryDir = lg->GetCurrentBinaryDirectory(); cmGlobalNinjaGenerator* gg = lg->GetGlobalNinjaGenerator(); @@ -1384,9 +1347,8 @@ void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()( input = this->Generator->GetGlobalGenerator()->ConvertToNinjaPath(input); // Get the output file location. - std::string output = macdir; - output += "/"; - output += cmSystemTools::GetFilenameName(input); + std::string output = + cmStrCat(macdir, '/', cmSystemTools::GetFilenameName(input)); output = this->Generator->GetGlobalGenerator()->ConvertToNinjaPath(output); // Write a build statement to copy the content into the bundle. diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 3055e18..a99d8e7 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -13,7 +13,7 @@ #include "cmOSXBundleGenerator.h" #include <map> -#include <memory> // IWYU pragma: keep +#include <memory> #include <set> #include <string> #include <vector> diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index 1225cbd..eea4c93 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -13,6 +13,7 @@ #include "cmOutputConverter.h" #include "cmSourceFile.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include <algorithm> @@ -36,15 +37,15 @@ void cmNinjaUtilityTargetGenerator::Generate() cmLocalNinjaGenerator* lg = this->GetLocalGenerator(); cmGeneratorTarget* genTarget = this->GetGeneratorTarget(); - std::string utilCommandName = lg->GetCurrentBinaryDirectory(); - utilCommandName += "/CMakeFiles"; - utilCommandName += "/"; - utilCommandName += this->GetTargetName() + ".util"; + std::string utilCommandName = + cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles/", + this->GetTargetName(), ".util"); utilCommandName = this->ConvertToNinjaPath(utilCommandName); cmNinjaBuild phonyBuild("phony"); std::vector<std::string> commands; - cmNinjaDeps deps, util_outputs(1, utilCommandName); + cmNinjaDeps deps; + cmNinjaDeps util_outputs(1, utilCommandName); bool uses_terminal = false; { @@ -135,6 +136,9 @@ void cmNinjaUtilityTargetGenerator::Generate() gg->WriteBuild(this->GetBuildFileStream(), phonyBuild); } + // Find ADDITIONAL_CLEAN_FILES + this->AdditionalCleanFiles(); + // Add an alias for the logical target name regardless of what directory // contains it. Skip this for GLOBAL_TARGET because they are meant to // be per-directory and have one at the top-level anyway. diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx index 47a8df4..6175c1e 100644 --- a/Source/cmOSXBundleGenerator.cxx +++ b/Source/cmOSXBundleGenerator.cxx @@ -6,6 +6,7 @@ #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -40,20 +41,20 @@ void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName, } // Compute bundle directory names. - std::string out = outpath; - out += "/"; - out += this->GT->GetAppBundleDirectory(this->ConfigName, - cmGeneratorTarget::FullLevel); + std::string out = + cmStrCat(outpath, '/', + this->GT->GetAppBundleDirectory(this->ConfigName, + cmGeneratorTarget::FullLevel)); cmSystemTools::MakeDirectory(out); this->Makefile->AddCMakeOutputFile(out); // Configure the Info.plist file. Note that it needs the executable name // to be set. - std::string plist = outpath; - plist += "/"; - plist += this->GT->GetAppBundleDirectory(this->ConfigName, - cmGeneratorTarget::ContentLevel); - plist += "/Info.plist"; + std::string plist = + cmStrCat(outpath, '/', + this->GT->GetAppBundleDirectory(this->ConfigName, + cmGeneratorTarget::ContentLevel), + "/Info.plist"); this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName, plist); this->Makefile->AddCMakeOutputFile(plist); outpath = out; @@ -69,10 +70,11 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, assert(this->MacContentFolders); // Compute the location of the top-level foo.framework directory. - std::string contentdir = outpath + "/" + - this->GT->GetFrameworkDirectory(this->ConfigName, - cmGeneratorTarget::ContentLevel); - contentdir += "/"; + std::string contentdir = + cmStrCat(outpath, '/', + this->GT->GetFrameworkDirectory(this->ConfigName, + cmGeneratorTarget::ContentLevel), + '/'); std::string newoutpath = outpath + "/" + this->GT->GetFrameworkDirectory(this->ConfigName, @@ -102,8 +104,7 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, std::string newName; // Make foo.framework/Versions - std::string versions = contentdir; - versions += "Versions"; + std::string versions = cmStrCat(contentdir, "Versions"); cmSystemTools::MakeDirectory(versions); // Make foo.framework/Versions/version @@ -111,17 +112,14 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, // Current -> version oldName = frameworkVersion; - newName = versions; - newName += "/Current"; + newName = cmStrCat(versions, "/Current"); cmSystemTools::RemoveFile(newName); cmSystemTools::CreateSymlink(oldName, newName); this->Makefile->AddCMakeOutputFile(newName); // foo -> Versions/Current/foo - oldName = "Versions/Current/"; - oldName += name; - newName = contentdir; - newName += name; + oldName = cmStrCat("Versions/Current/", name); + newName = cmStrCat(contentdir, name); cmSystemTools::RemoveFile(newName); cmSystemTools::CreateSymlink(oldName, newName); this->Makefile->AddCMakeOutputFile(newName); @@ -130,8 +128,7 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, if (this->MacContentFolders->find("Resources") != this->MacContentFolders->end()) { oldName = "Versions/Current/Resources"; - newName = contentdir; - newName += "Resources"; + newName = cmStrCat(contentdir, "Resources"); cmSystemTools::RemoveFile(newName); cmSystemTools::CreateSymlink(oldName, newName); this->Makefile->AddCMakeOutputFile(newName); @@ -141,8 +138,7 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, if (this->MacContentFolders->find("Headers") != this->MacContentFolders->end()) { oldName = "Versions/Current/Headers"; - newName = contentdir; - newName += "Headers"; + newName = cmStrCat(contentdir, "Headers"); cmSystemTools::RemoveFile(newName); cmSystemTools::CreateSymlink(oldName, newName); this->Makefile->AddCMakeOutputFile(newName); @@ -152,8 +148,7 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName, if (this->MacContentFolders->find("PrivateHeaders") != this->MacContentFolders->end()) { oldName = "Versions/Current/PrivateHeaders"; - newName = contentdir; - newName += "PrivateHeaders"; + newName = cmStrCat(contentdir, "PrivateHeaders"); cmSystemTools::RemoveFile(newName); cmSystemTools::CreateSymlink(oldName, newName); this->Makefile->AddCMakeOutputFile(newName); @@ -168,19 +163,20 @@ void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName, } // Compute bundle directory names. - std::string out = root; - out += "/"; - out += this->GT->GetCFBundleDirectory(this->ConfigName, - cmGeneratorTarget::FullLevel); + std::string out = + cmStrCat(root, '/', + this->GT->GetCFBundleDirectory(this->ConfigName, + cmGeneratorTarget::FullLevel)); cmSystemTools::MakeDirectory(out); this->Makefile->AddCMakeOutputFile(out); // Configure the Info.plist file. Note that it needs the executable name // to be set. - std::string plist = root + "/" + - this->GT->GetCFBundleDirectory(this->ConfigName, - cmGeneratorTarget::ContentLevel); - plist += "/Info.plist"; + std::string plist = + cmStrCat(root, '/', + this->GT->GetCFBundleDirectory(this->ConfigName, + cmGeneratorTarget::ContentLevel), + "/Info.plist"); std::string name = cmSystemTools::GetFilenameName(targetName); this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist); this->Makefile->AddCMakeOutputFile(plist); @@ -208,10 +204,10 @@ std::string cmOSXBundleGenerator::InitMacOSXContentDirectory( { // Construct the full path to the content subdirectory. - std::string macdir = this->GT->GetMacContentDirectory( - this->ConfigName, cmStateEnums::RuntimeBinaryArtifact); - macdir += "/"; - macdir += pkgloc; + std::string macdir = + cmStrCat(this->GT->GetMacContentDirectory( + this->ConfigName, cmStateEnums::RuntimeBinaryArtifact), + '/', pkgloc); cmSystemTools::MakeDirectory(macdir); // Record use of this content location. Only the first level diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx index 52f63a3..a0a0989 100644 --- a/Source/cmOptionCommand.cxx +++ b/Source/cmOptionCommand.cxx @@ -4,36 +4,35 @@ #include <sstream> -#include "cmAlgorithms.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" -#include "cmSystemTools.h" - -class cmExecutionStatus; +#include "cmStringAlgorithms.h" // cmOptionCommand -bool cmOptionCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmOptionCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { const bool argError = (args.size() < 2) || (args.size() > 3); if (argError) { - std::string m = "called with incorrect number of arguments: "; - m += cmJoin(args, " "); - this->SetError(m); + std::string m = cmStrCat("called with incorrect number of arguments: ", + cmJoin(args, " ")); + status.SetError(m); return false; } // Determine the state of the option policy bool checkAndWarn = false; { - auto status = this->Makefile->GetPolicyStatus(cmPolicies::CMP0077); + auto policyStatus = + status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0077); const auto* existsBeforeSet = - this->Makefile->GetStateSnapshot().GetDefinition(args[0]); - switch (status) { + status.GetMakefile().GetStateSnapshot().GetDefinition(args[0]); + switch (policyStatus) { case cmPolicies::WARN: checkAndWarn = (existsBeforeSet != nullptr); break; @@ -54,7 +53,7 @@ bool cmOptionCommand::InitialPass(std::vector<std::string> const& args, // See if a cache variable with this name already exists // If so just make sure the doc state is correct - cmState* state = this->Makefile->GetState(); + cmState* state = status.GetMakefile().GetState(); const char* existingValue = state->GetCacheEntryValue(args[0]); if (existingValue && (state->GetCacheEntryType(args[0]) != cmStateEnums::UNINITIALIZED)) { @@ -67,13 +66,13 @@ bool cmOptionCommand::InitialPass(std::vector<std::string> const& args, if (args.size() == 3) { initialValue = args[2]; } - bool init = cmSystemTools::IsOn(initialValue); - this->Makefile->AddCacheDefinition(args[0], init ? "ON" : "OFF", - args[1].c_str(), cmStateEnums::BOOL); + bool init = cmIsOn(initialValue); + status.GetMakefile().AddCacheDefinition(args[0], init ? "ON" : "OFF", + args[1].c_str(), cmStateEnums::BOOL); if (checkAndWarn) { const auto* existsAfterSet = - this->Makefile->GetStateSnapshot().GetDefinition(args[0]); + status.GetMakefile().GetStateSnapshot().GetDefinition(args[0]); if (!existsAfterSet) { std::ostringstream w; w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0077) @@ -81,7 +80,7 @@ bool cmOptionCommand::InitialPass(std::vector<std::string> const& args, "For compatibility with older versions of CMake, option " "is clearing the normal variable '" << args[0] << "'."; - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); + status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } } return true; diff --git a/Source/cmOptionCommand.h b/Source/cmOptionCommand.h index 34e0e6f..cbd1cb8 100644 --- a/Source/cmOptionCommand.h +++ b/Source/cmOptionCommand.h @@ -8,29 +8,13 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmOptionCommand +/** * \brief Provide an option to the user * * cmOptionCommand provides an option for the user to select */ -class cmOptionCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmOptionCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; - +bool cmOptionCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx index 585db42..21a17e8 100644 --- a/Source/cmOrderDirectories.cxx +++ b/Source/cmOrderDirectories.cxx @@ -6,6 +6,7 @@ #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmMessageType.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" @@ -13,6 +14,7 @@ #include <assert.h> #include <functional> #include <sstream> +#include <vector> /* Directory ordering computation. @@ -116,9 +118,7 @@ bool cmOrderDirectoriesConstraint::FileMayConflict(std::string const& dir, std::string const& name) { // Check if the file exists on disk. - std::string file = dir; - file += "/"; - file += name; + std::string file = cmStrCat(dir, '/', name); if (cmSystemTools::FileExists(file, true)) { // The file conflicts only if it is not the same as the original // file due to a symlink or hardlink. @@ -228,8 +228,7 @@ bool cmOrderDirectoriesConstraintLibrary::FindConflict(std::string const& dir) std::string ext = this->OD->RemoveLibraryExtension.match(2); for (std::string const& LinkExtension : this->OD->LinkExtensions) { if (LinkExtension != ext) { - std::string fname = lib; - fname += LinkExtension; + std::string fname = cmStrCat(lib, LinkExtension); if (this->FileMayConflict(dir, fname)) { return true; } diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index 7d88b08..bf516e3 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -6,10 +6,10 @@ #include <assert.h> #include <ctype.h> #include <set> -#include <string.h> #include <vector> #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmOutputConverter::cmOutputConverter(cmStateSnapshot const& snapshot) @@ -38,10 +38,10 @@ std::string cmOutputConverter::ConvertToOutputForExisting( return this->ConvertToOutputFormat(remote, format); } -std::string cmOutputConverter::ConvertToOutputFormat(const std::string& source, +std::string cmOutputConverter::ConvertToOutputFormat(cm::string_view source, OutputFormat output) const { - std::string result = source; + std::string result(source); // Convert it to an output path. if (output == SHELL || output == WATCOMQUOTE) { result = this->ConvertDirectorySeparatorsForShell(source); @@ -53,9 +53,9 @@ std::string cmOutputConverter::ConvertToOutputFormat(const std::string& source, } std::string cmOutputConverter::ConvertDirectorySeparatorsForShell( - const std::string& source) const + cm::string_view source) const { - std::string result = source; + std::string result(source); // For the MSYS shell convert drive letters to posix paths, so // that c:/some/path becomes /c/some/path. This is needed to // avoid problems with the shell path translation. @@ -71,33 +71,21 @@ std::string cmOutputConverter::ConvertDirectorySeparatorsForShell( return result; } -static bool cmOutputConverterIsShellOperator(const std::string& str) +static bool cmOutputConverterIsShellOperator(cm::string_view str) { - static std::set<std::string> shellOperators; - if (shellOperators.empty()) { - shellOperators.insert("<"); - shellOperators.insert(">"); - shellOperators.insert("<<"); - shellOperators.insert(">>"); - shellOperators.insert("|"); - shellOperators.insert("||"); - shellOperators.insert("&&"); - shellOperators.insert("&>"); - shellOperators.insert("1>"); - shellOperators.insert("2>"); - shellOperators.insert("2>&1"); - shellOperators.insert("1>&2"); - } - return shellOperators.count(str) > 0; + static std::set<cm::string_view> const shellOperators{ + "<", ">", "<<", ">>", "|", "||", "&&", "&>", "1>", "2>", "2>&1", "1>&2" + }; + return (shellOperators.count(str) != 0); } -std::string cmOutputConverter::EscapeForShell(const std::string& str, +std::string cmOutputConverter::EscapeForShell(cm::string_view str, bool makeVars, bool forEcho, bool useWatcomQuote) const { // Do not escape shell operators. if (cmOutputConverterIsShellOperator(str)) { - return str; + return std::string(str); } // Compute the flags for the target shell environment. @@ -129,46 +117,44 @@ std::string cmOutputConverter::EscapeForShell(const std::string& str, flags |= Shell_Flag_IsUnix; } - return Shell__GetArgument(str.c_str(), flags); + return Shell__GetArgument(str, flags); } -std::string cmOutputConverter::EscapeForCMake(const std::string& str) +std::string cmOutputConverter::EscapeForCMake(cm::string_view str) { // Always double-quote the argument to take care of most escapes. std::string result = "\""; - for (const char* c = str.c_str(); *c; ++c) { - if (*c == '"') { + for (const char c : str) { + if (c == '"') { // Escape the double quote to avoid ending the argument. result += "\\\""; - } else if (*c == '$') { + } else if (c == '$') { // Escape the dollar to avoid expanding variables. result += "\\$"; - } else if (*c == '\\') { + } else if (c == '\\') { // Escape the backslash to avoid other escapes. result += "\\\\"; } else { // Other characters will be parsed correctly. - result += *c; + result += c; } } result += "\""; return result; } -std::string cmOutputConverter::EscapeWindowsShellArgument(const char* arg, +std::string cmOutputConverter::EscapeWindowsShellArgument(cm::string_view arg, int shell_flags) { return Shell__GetArgument(arg, shell_flags); } cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat( - const char* value) + cm::string_view value) { FortranFormat format = FortranFormatNone; - if (value && *value) { - std::vector<std::string> fmt; - cmSystemTools::ExpandListArgument(value, fmt); - for (std::string const& fi : fmt) { + if (!value.empty()) { + for (std::string const& fi : cmExpandedList(value)) { if (fi == "FIXED") { format = FortranFormatFixed; } @@ -180,6 +166,15 @@ cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat( return format; } +cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat( + const char* value) +{ + if (!value) { + return FortranFormatNone; + } + return GetFortranFormat(cm::string_view(value)); +} + void cmOutputConverter::SetLinkScriptShell(bool linkScriptShell) { this->LinkScriptShell = linkScriptShell; @@ -225,12 +220,12 @@ use the caret character itself (^), use two in a row (^^). */ /* Some helpers to identify character classes */ -static int Shell__CharIsWhitespace(char c) +static bool Shell__CharIsWhitespace(char c) { return ((c == ' ') || (c == '\t')); } -static int Shell__CharNeedsQuotesOnUnix(char c) +static bool Shell__CharNeedsQuotesOnUnix(char c) { return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') || (c == '&') || (c == '$') || (c == '(') || (c == ')') || (c == '~') || @@ -238,51 +233,52 @@ static int Shell__CharNeedsQuotesOnUnix(char c) (c == '\\')); } -static int Shell__CharNeedsQuotesOnWindows(char c) +static bool Shell__CharNeedsQuotesOnWindows(char c) { return ((c == '\'') || (c == '#') || (c == '&') || (c == '<') || (c == '>') || (c == '|') || (c == '^')); } -static int Shell__CharIsMakeVariableName(char c) +static bool Shell__CharIsMakeVariableName(char c) { return c && (c == '_' || isalpha((static_cast<int>(c)))); } -int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags) +bool cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags) { /* On Windows the built-in command shell echo never needs quotes. */ if (!(flags & Shell_Flag_IsUnix) && (flags & Shell_Flag_EchoWindows)) { - return 0; + return false; } /* On all platforms quotes are needed to preserve whitespace. */ if (Shell__CharIsWhitespace(c)) { - return 1; + return true; } if (flags & Shell_Flag_IsUnix) { /* On UNIX several special characters need quotes to preserve them. */ if (Shell__CharNeedsQuotesOnUnix(c)) { - return 1; + return true; } } else { /* On Windows several special characters need quotes to preserve them. */ if (Shell__CharNeedsQuotesOnWindows(c)) { - return 1; + return true; } } - return 0; + return false; } -const char* cmOutputConverter::Shell__SkipMakeVariables(const char* c) +cm::string_view::iterator cmOutputConverter::Shell__SkipMakeVariables( + cm::string_view::iterator c, cm::string_view::iterator end) { - while (*c == '$' && *(c + 1) == '(') { - const char* skip = c + 2; - while (Shell__CharIsMakeVariableName(*skip)) { + while ((c != end && (c + 1) != end) && (*c == '$' && *(c + 1) == '(')) { + cm::string_view::iterator skip = c + 2; + while ((skip != end) && Shell__CharIsMakeVariableName(*skip)) { ++skip; } - if (*skip == ')') { + if ((skip != end) && *skip == ')') { c = skip + 1; } else { break; @@ -314,63 +310,60 @@ flag later when we understand applications of this better. */ #define KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES 0 -int cmOutputConverter::Shell__ArgumentNeedsQuotes(const char* in, int flags) +bool cmOutputConverter::Shell__ArgumentNeedsQuotes(cm::string_view in, + int flags) { /* The empty string needs quotes. */ - if (!*in) { - return 1; + if (in.empty()) { + return true; } /* Scan the string for characters that require quoting. */ - { - const char* c; - for (c = in; *c; ++c) { - /* Look for $(MAKEVAR) syntax if requested. */ - if (flags & Shell_Flag_AllowMakeVariables) { + for (cm::string_view::iterator cit = in.begin(), cend = in.end(); + cit != cend; ++cit) { + /* Look for $(MAKEVAR) syntax if requested. */ + if (flags & Shell_Flag_AllowMakeVariables) { #if KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES - const char* skip = Shell__SkipMakeVariables(c); - if (skip != c) { - /* We need to quote make variable references to preserve the - string with contents substituted in its place. */ - return 1; - } + cm::string_view::iterator skip = Shell__SkipMakeVariables(cit, cend); + if (skip != cit) { + /* We need to quote make variable references to preserve the + string with contents substituted in its place. */ + return true; + } #else - /* Skip over the make variable references if any are present. */ - c = Shell__SkipMakeVariables(c); + /* Skip over the make variable references if any are present. */ + cit = Shell__SkipMakeVariables(cit, cend); - /* Stop if we have reached the end of the string. */ - if (!*c) { - break; - } -#endif + /* Stop if we have reached the end of the string. */ + if (cit == cend) { + break; } +#endif + } - /* Check whether this character needs quotes. */ - if (Shell__CharNeedsQuotes(*c, flags)) { - return 1; - } + /* Check whether this character needs quotes. */ + if (Shell__CharNeedsQuotes(*cit, flags)) { + return true; } } /* On Windows some single character arguments need quotes. */ - if (flags & Shell_Flag_IsUnix && *in && !*(in + 1)) { - char c = *in; + if (flags & Shell_Flag_IsUnix && in.size() == 1) { + char c = in[0]; if ((c == '?') || (c == '&') || (c == '^') || (c == '|') || (c == '#')) { - return 1; + return true; } } - return 0; + return false; } -std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) +std::string cmOutputConverter::Shell__GetArgument(cm::string_view in, + int flags) { /* Output will be at least as long as input string. */ std::string out; - out.reserve(strlen(in)); - - /* String iterator. */ - const char* c; + out.reserve(in.size()); /* Keep track of how many backslashes have been encountered in a row. */ int windows_backslashes = 0; @@ -390,14 +383,15 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) } /* Scan the string for characters that require escaping or quoting. */ - for (c = in; *c; ++c) { + for (cm::string_view::iterator cit = in.begin(), cend = in.end(); + cit != cend; ++cit) { /* Look for $(MAKEVAR) syntax if requested. */ if (flags & Shell_Flag_AllowMakeVariables) { - const char* skip = Shell__SkipMakeVariables(c); - if (skip != c) { + cm::string_view::iterator skip = Shell__SkipMakeVariables(cit, cend); + if (skip != cit) { /* Copy to the end of the make variable references. */ - while (c != skip) { - out += *c++; + while (cit != skip) { + out += *cit++; } /* The make variable reference eliminates any escaping needed @@ -405,7 +399,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) windows_backslashes = 0; /* Stop if we have reached the end of the string. */ - if (!*c) { + if (cit == cend) { break; } } @@ -415,7 +409,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) if (flags & Shell_Flag_IsUnix) { /* On Unix a few special characters need escaping even inside a quoted argument. */ - if (*c == '\\' || *c == '"' || *c == '`' || *c == '$') { + if (*cit == '\\' || *cit == '"' || *cit == '`' || *cit == '$') { /* This character needs a backslash to escape it. */ out += '\\'; } @@ -423,10 +417,10 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) /* On Windows the built-in command shell echo never needs escaping. */ } else { /* On Windows only backslashes and double-quotes need escaping. */ - if (*c == '\\') { + if (*cit == '\\') { /* Found a backslash. It may need to be escaped later. */ ++windows_backslashes; - } else if (*c == '"') { + } else if (*cit == '"') { /* Found a double-quote. Escape all immediately preceding backslashes. */ while (windows_backslashes > 0) { @@ -444,7 +438,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) } /* Check whether this character needs escaping for a make tool. */ - if (*c == '$') { + if (*cit == '$') { if (flags & Shell_Flag_Make) { /* In Makefiles a dollar is written $$. The make tool will replace it with just $ before passing it to the shell. */ @@ -461,7 +455,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) /* Otherwise a dollar is written just $. */ out += '$'; } - } else if (*c == '#') { + } else if (*cit == '#') { if ((flags & Shell_Flag_Make) && (flags & Shell_Flag_WatcomWMake)) { /* In Watcom WMake makefiles a pound is written $#. The make tool will replace it with just # before passing it to the @@ -471,7 +465,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) /* Otherwise a pound is written just #. */ out += '#'; } - } else if (*c == '%') { + } else if (*cit == '%') { if ((flags & Shell_Flag_VSIDE) || ((flags & Shell_Flag_Make) && ((flags & Shell_Flag_MinGWMake) || (flags & Shell_Flag_NMake)))) { @@ -481,7 +475,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) /* Otherwise a percent is written just %. */ out += '%'; } - } else if (*c == ';') { + } else if (*cit == ';') { if (flags & Shell_Flag_VSIDE) { /* In a VS IDE a semicolon is written ";". If this is written in an un-quoted argument it starts a quoted segment, @@ -495,7 +489,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) } } else { /* Store this character. */ - out += *c; + out += *cit; } } diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h index deca767..671efe7 100644 --- a/Source/cmOutputConverter.h +++ b/Source/cmOutputConverter.h @@ -5,9 +5,10 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <string> - #include "cmStateSnapshot.h" +#include "cm_string_view.hxx" + +#include <string> class cmState; @@ -22,10 +23,9 @@ public: WATCOMQUOTE, RESPONSE }; - std::string ConvertToOutputFormat(const std::string& source, + std::string ConvertToOutputFormat(cm::string_view source, OutputFormat output) const; - std::string ConvertDirectorySeparatorsForShell( - const std::string& source) const; + std::string ConvertDirectorySeparatorsForShell(cm::string_view source) const; //! for existing files convert to output path and short path if spaces std::string ConvertToOutputForExisting(const std::string& remote, @@ -72,15 +72,15 @@ public: Shell_Flag_IsUnix = (1 << 8) }; - std::string EscapeForShell(const std::string& str, bool makeVars = false, + std::string EscapeForShell(cm::string_view str, bool makeVars = false, bool forEcho = false, bool useWatcomQuote = false) const; - static std::string EscapeForCMake(const std::string& str); + static std::string EscapeForCMake(cm::string_view str); /** Compute an escaped version of the given argument for use in a windows shell. */ - static std::string EscapeWindowsShellArgument(const char* arg, + static std::string EscapeWindowsShellArgument(cm::string_view arg, int shell_flags); enum FortranFormat @@ -89,15 +89,17 @@ public: FortranFormatFixed, FortranFormatFree }; + static FortranFormat GetFortranFormat(cm::string_view value); static FortranFormat GetFortranFormat(const char* value); private: cmState* GetState() const; - static int Shell__CharNeedsQuotes(char c, int flags); - static const char* Shell__SkipMakeVariables(const char* c); - static int Shell__ArgumentNeedsQuotes(const char* in, int flags); - static std::string Shell__GetArgument(const char* in, int flags); + static bool Shell__CharNeedsQuotes(char c, int flags); + static cm::string_view::iterator Shell__SkipMakeVariables( + cm::string_view::iterator begin, cm::string_view::iterator end); + static bool Shell__ArgumentNeedsQuotes(cm::string_view in, int flags); + static std::string Shell__GetArgument(cm::string_view in, int flags); private: cmStateSnapshot StateSnapshot; diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx index f3276ec..dbb7111 100644 --- a/Source/cmOutputRequiredFilesCommand.cxx +++ b/Source/cmOutputRequiredFilesCommand.cxx @@ -11,6 +11,7 @@ #include "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmSourceFile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -121,8 +122,7 @@ public: std::string incDirs = cmGeneratorExpression::Preprocess( incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions); - std::vector<std::string> includes; - cmSystemTools::ExpandListArgument(incDirs, includes); + std::vector<std::string> includes = cmExpandedList(incDirs); for (std::string& path : includes) { this->Makefile->ExpandVariablesInString(path); @@ -192,10 +192,8 @@ protected: // see if the include matches the regular expression if (!this->IncludeFileRegularExpression.find(includeFile)) { if (this->Verbose) { - std::string message = "Skipping "; - message += includeFile; - message += " for file "; - message += info->FullPath; + std::string message = + cmStrCat("Skipping ", includeFile, " for file ", info->FullPath); cmSystemTools::Error(message); } continue; @@ -214,10 +212,8 @@ protected: if (cmSystemTools::FileExists(cxxFile)) { found = true; } - for (std::string path : this->IncludeDirectories) { - path = path + "/"; - path = path + cxxFile; - if (cmSystemTools::FileExists(path)) { + for (std::string const& path : this->IncludeDirectories) { + if (cmSystemTools::FileExists(cmStrCat(path, "/", cxxFile))) { found = true; } } @@ -226,10 +222,8 @@ protected: if (cmSystemTools::FileExists(cxxFile)) { found = true; } - for (std::string path : this->IncludeDirectories) { - path = path + "/"; - path = path + cxxFile; - if (cmSystemTools::FileExists(path)) { + for (std::string const& path : this->IncludeDirectories) { + if (cmSystemTools::FileExists(cmStrCat(path, "/", cxxFile))) { found = true; } } @@ -239,10 +233,8 @@ protected: if (cmSystemTools::FileExists(cxxFile)) { found = true; } - for (std::string path : this->IncludeDirectories) { - path = path + "/"; - path = path + cxxFile; - if (cmSystemTools::FileExists(path)) { + for (std::string const& path : this->IncludeDirectories) { + if (cmSystemTools::FileExists(cmStrCat(path, "/", cxxFile))) { found = true; } } @@ -252,10 +244,8 @@ protected: if (cmSystemTools::FileExists(cxxFile)) { found = true; } - for (std::string path : this->IncludeDirectories) { - path = path + "/"; - path = path + cxxFile; - if (cmSystemTools::FileExists(path)) { + for (std::string const& path : this->IncludeDirectories) { + if (cmSystemTools::FileExists(cmStrCat(path, "/", cxxFile))) { found = true; } } @@ -339,9 +329,9 @@ protected: // try to guess which include path to use for (std::string incpath : this->IncludeDirectories) { if (!incpath.empty() && incpath.back() != '/') { - incpath = incpath + "/"; + incpath += "/"; } - incpath = incpath + path; + incpath += path; if (srcFile->GetFullPath() == incpath) { // set the path to the guessed path info->FullPath = incpath; @@ -420,9 +410,9 @@ protected: for (std::string path : this->IncludeDirectories) { if (!path.empty() && path.back() != '/') { - path = path + "/"; + path += "/"; } - path = path + fname; + path += fname; if (cmSystemTools::FileExists(path, true) && !cmSystemTools::FileIsDirectory(path)) { std::string fp = cmSystemTools::CollapseFullPath(path); @@ -485,9 +475,7 @@ bool cmOutputRequiredFilesCommand::InitialPass( // write them out FILE* fout = cmsys::SystemTools::Fopen(this->OutputFile, "w"); if (!fout) { - std::string err = "Can not open output file: "; - err += this->OutputFile; - this->SetError(err); + this->SetError(cmStrCat("Can not open output file: ", this->OutputFile)); return false; } std::set<cmDependInformation const*> visited; diff --git a/Source/cmOutputRequiredFilesCommand.h b/Source/cmOutputRequiredFilesCommand.h index 09e622b..faffabd 100644 --- a/Source/cmOutputRequiredFilesCommand.h +++ b/Source/cmOutputRequiredFilesCommand.h @@ -10,6 +10,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmDependInformation; @@ -18,7 +20,10 @@ class cmExecutionStatus; class cmOutputRequiredFilesCommand : public cmCommand { public: - cmCommand* Clone() override { return new cmOutputRequiredFilesCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmOutputRequiredFilesCommand>(); + } bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx index 5213432..aad9f74 100644 --- a/Source/cmParseArgumentsCommand.cxx +++ b/Source/cmParseArgumentsCommand.cxx @@ -7,16 +7,15 @@ #include <sstream> #include <utility> -#include "cmAlgorithms.h" #include "cmArgumentParser.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmRange.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cm_string_view.hxx" -class cmExecutionStatus; - static std::string EscapeArg(const std::string& arg) { // replace ";" with "\;" so output argument lists will split correctly @@ -75,7 +74,7 @@ static void PassParsedArguments( for (auto const& iter : singleValArgs) { if (!iter.second.empty()) { - makefile.AddDefinition(prefix + iter.first, iter.second.c_str()); + makefile.AddDefinition(prefix + iter.first, iter.second); } else { makefile.RemoveDefinition(prefix + iter.first); } @@ -84,7 +83,7 @@ static void PassParsedArguments( for (auto const& iter : multiValArgs) { if (!iter.second.empty()) { makefile.AddDefinition(prefix + iter.first, - JoinList(iter.second, parseFromArgV).c_str()); + JoinList(iter.second, parseFromArgV)); } else { makefile.RemoveDefinition(prefix + iter.first); } @@ -92,39 +91,38 @@ static void PassParsedArguments( if (!unparsed.empty()) { makefile.AddDefinition(prefix + "UNPARSED_ARGUMENTS", - JoinList(unparsed, parseFromArgV).c_str()); + JoinList(unparsed, parseFromArgV)); } else { makefile.RemoveDefinition(prefix + "UNPARSED_ARGUMENTS"); } if (!keywordsMissingValues.empty()) { - makefile.AddDefinition( - prefix + "KEYWORDS_MISSING_VALUES", - cmJoin(cmMakeRange(keywordsMissingValues), ";").c_str()); + makefile.AddDefinition(prefix + "KEYWORDS_MISSING_VALUES", + cmJoin(cmMakeRange(keywordsMissingValues), ";")); } else { makefile.RemoveDefinition(prefix + "KEYWORDS_MISSING_VALUES"); } } -bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmParseArgumentsCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { // cmake_parse_arguments(prefix options single multi <ARGN>) // 1 2 3 4 // or // cmake_parse_arguments(PARSE_ARGV N prefix options single multi) if (args.size() < 4) { - this->SetError("must be called with at least 4 arguments."); + status.SetError("must be called with at least 4 arguments."); return false; } - std::vector<std::string>::const_iterator argIter = args.begin(), - argEnd = args.end(); + std::vector<std::string>::const_iterator argIter = args.begin(); + std::vector<std::string>::const_iterator argEnd = args.end(); bool parseFromArgV = false; unsigned long argvStart = 0; if (*argIter == "PARSE_ARGV") { if (args.size() != 6) { - this->Makefile->IssueMessage( + status.GetMakefile().IssueMessage( MessageType::FATAL_ERROR, "PARSE_ARGV must be called with exactly 6 arguments."); cmSystemTools::SetFatalErrorOccured(); @@ -132,10 +130,10 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, } parseFromArgV = true; argIter++; // move past PARSE_ARGV - if (!cmSystemTools::StringToULong(argIter->c_str(), &argvStart)) { - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, - "PARSE_ARGV index '" + *argIter + - "' is not an unsigned integer"); + if (!cmStrToULong(*argIter, &argvStart)) { + status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, + "PARSE_ARGV index '" + *argIter + + "' is not an unsigned integer"); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -155,24 +153,23 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, // anything else is put into a vector of unparsed strings std::vector<std::string> unparsed; - auto const duplicateKey = [this](std::string const& key) { - this->GetMakefile()->IssueMessage( + auto const duplicateKey = [&status](std::string const& key) { + status.GetMakefile().IssueMessage( MessageType::WARNING, "keyword defined more than once: " + key); }; // the second argument is a (cmake) list of options without argument - std::vector<std::string> list; - cmSystemTools::ExpandListArgument(*argIter++, list); + std::vector<std::string> list = cmExpandedList(*argIter++); parser.Bind(list, options, duplicateKey); // the third argument is a (cmake) list of single argument options list.clear(); - cmSystemTools::ExpandListArgument(*argIter++, list); + cmExpandList(*argIter++, list); parser.Bind(list, singleValArgs, duplicateKey); // the fourth argument is a (cmake) list of multi argument options list.clear(); - cmSystemTools::ExpandListArgument(*argIter++, list); + cmExpandList(*argIter++, list); parser.Bind(list, multiValArgs, duplicateKey); list.clear(); @@ -180,27 +177,28 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, // Flatten ;-lists in the arguments into a single list as was done // by the original function(CMAKE_PARSE_ARGUMENTS). for (; argIter != argEnd; ++argIter) { - cmSystemTools::ExpandListArgument(*argIter, list); + cmExpandList(*argIter, list); } } else { // in the PARSE_ARGV move read the arguments from ARGC and ARGV# - std::string argc = this->Makefile->GetSafeDefinition("ARGC"); + std::string argc = status.GetMakefile().GetSafeDefinition("ARGC"); unsigned long count; - if (!cmSystemTools::StringToULong(argc.c_str(), &count)) { - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, - "PARSE_ARGV called with ARGC='" + argc + - "' that is not an unsigned integer"); + if (!cmStrToULong(argc, &count)) { + status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, + "PARSE_ARGV called with ARGC='" + + argc + + "' that is not an unsigned integer"); cmSystemTools::SetFatalErrorOccured(); return true; } for (unsigned long i = argvStart; i < count; ++i) { std::ostringstream argName; argName << "ARGV" << i; - const char* arg = this->Makefile->GetDefinition(argName.str()); + const char* arg = status.GetMakefile().GetDefinition(argName.str()); if (!arg) { - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, - "PARSE_ARGV called with " + - argName.str() + " not set"); + status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, + "PARSE_ARGV called with " + + argName.str() + " not set"); cmSystemTools::SetFatalErrorOccured(); return true; } @@ -213,7 +211,8 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args, parser.Parse(list, &unparsed, &keywordsMissingValues); PassParsedArguments( - prefix, *this->Makefile, options, singleValArgs, multiValArgs, unparsed, + prefix, status.GetMakefile(), options, singleValArgs, multiValArgs, + unparsed, options_set(keywordsMissingValues.begin(), keywordsMissingValues.end()), parseFromArgV); diff --git a/Source/cmParseArgumentsCommand.h b/Source/cmParseArgumentsCommand.h index b8ba61d..b2e436d 100644 --- a/Source/cmParseArgumentsCommand.h +++ b/Source/cmParseArgumentsCommand.h @@ -8,27 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmParseArgumentsCommand - * - */ -class cmParseArgumentsCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmParseArgumentsCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmParseArgumentsCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index ec40136..d33cd32 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -1,10 +1,10 @@ #include "cmPolicies.h" -#include "cmAlgorithms.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVersion.h" @@ -34,7 +34,7 @@ static bool stringToId(const char* input, cmPolicies::PolicyID& pid) } } long id; - if (!cmSystemTools::StringToLong(input + 3, &id)) { + if (!cmStrToLong(input + 3, &id)) { return false; } if (id >= cmPolicies::CMPCOUNT) { diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index b705119..92c80bb 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -279,7 +279,18 @@ class cmMakefile; SELECT(POLICY, CMP0094, \ "FindPython3, FindPython2 and FindPyton use " \ "LOCATION for lookup strategy.", \ - 3, 15, 0, cmPolicies::WARN) + 3, 15, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0095, \ + "RPATH entries are properly escaped in the intermediary CMake " \ + "install script.", \ + 3, 16, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0096, \ + "project() preserves leading zeros in version components.", 3, 16, \ + 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0097, \ + "ExternalProject_Add with GIT_SUBMODULES \"\" initializes no " \ + "submodules.", \ + 3, 16, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ @@ -307,7 +318,8 @@ class cmMakefile; F(CMP0073) \ F(CMP0076) \ F(CMP0081) \ - F(CMP0083) + F(CMP0083) \ + F(CMP0095) /** \class cmPolicies * \brief Handles changes in CMake behavior and policies diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index 8615ecc..f8c5ada 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -3,15 +3,18 @@ #include "cmProjectCommand.h" #include "cmsys/RegularExpression.hxx" +#include <array> +#include <cstdio> #include <functional> +#include <limits> #include <sstream> -#include <stdio.h> +#include <utility> -#include "cmAlgorithms.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmExecutionStatus; @@ -33,27 +36,21 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, this->Makefile->SetProjectName(projectName); - std::string bindir = projectName; - bindir += "_BINARY_DIR"; - std::string srcdir = projectName; - srcdir += "_SOURCE_DIR"; - this->Makefile->AddCacheDefinition( - bindir, this->Makefile->GetCurrentBinaryDirectory().c_str(), + projectName + "_BINARY_DIR", + this->Makefile->GetCurrentBinaryDirectory().c_str(), "Value Computed by CMake", cmStateEnums::STATIC); this->Makefile->AddCacheDefinition( - srcdir, this->Makefile->GetCurrentSourceDirectory().c_str(), + projectName + "_SOURCE_DIR", + this->Makefile->GetCurrentSourceDirectory().c_str(), "Value Computed by CMake", cmStateEnums::STATIC); - bindir = "PROJECT_BINARY_DIR"; - srcdir = "PROJECT_SOURCE_DIR"; - - this->Makefile->AddDefinition( - bindir, this->Makefile->GetCurrentBinaryDirectory().c_str()); - this->Makefile->AddDefinition( - srcdir, this->Makefile->GetCurrentSourceDirectory().c_str()); + this->Makefile->AddDefinition("PROJECT_BINARY_DIR", + this->Makefile->GetCurrentBinaryDirectory()); + this->Makefile->AddDefinition("PROJECT_SOURCE_DIR", + this->Makefile->GetCurrentSourceDirectory()); - this->Makefile->AddDefinition("PROJECT_NAME", projectName.c_str()); + this->Makefile->AddDefinition("PROJECT_NAME", projectName); // Set the CMAKE_PROJECT_NAME variable to be the highest-level // project name in the tree. If there are two project commands @@ -63,7 +60,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, // will work. if (!this->Makefile->GetDefinition("CMAKE_PROJECT_NAME") || (this->Makefile->IsRootMakefile())) { - this->Makefile->AddDefinition("CMAKE_PROJECT_NAME", projectName.c_str()); + this->Makefile->AddDefinition("CMAKE_PROJECT_NAME", projectName); this->Makefile->AddCacheDefinition( "CMAKE_PROJECT_NAME", projectName.c_str(), "Value Computed by CMake", cmStateEnums::STATIC); @@ -105,11 +102,10 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, } doing = DoingLanguages; if (!languages.empty()) { - std::string msg = + std::string msg = cmStrCat( "the following parameters must be specified after LANGUAGES " - "keyword: "; - msg += cmJoin(languages, ", "); - msg += '.'; + "keyword: ", + cmJoin(languages, ", "), '.'); this->Makefile->IssueMessage(MessageType::WARNING, msg); } } else if (args[i] == "VERSION") { @@ -205,7 +201,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, languages.emplace_back("NONE"); } - cmPolicies::PolicyStatus cmp0048 = + cmPolicies::PolicyStatus const cmp0048 = this->Makefile->GetPolicyStatus(cmPolicies::CMP0048); if (haveVersion) { // Set project VERSION variables to given values @@ -220,64 +216,87 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, cmsys::RegularExpression vx( R"(^([0-9]+(\.[0-9]+(\.[0-9]+(\.[0-9]+)?)?)?)?$)"); if (!vx.find(version)) { - std::string e = "VERSION \"" + version + "\" format invalid."; + std::string e = R"(VERSION ")" + version + R"(" format invalid.)"; this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e); cmSystemTools::SetFatalErrorOccured(); return true; } - std::string vs; - const char* sep = ""; - char vb[4][64]; - unsigned int v[4] = { 0, 0, 0, 0 }; - int vc = - sscanf(version.c_str(), "%u.%u.%u.%u", &v[0], &v[1], &v[2], &v[3]); - for (int i = 0; i < 4; ++i) { - if (i < vc) { - sprintf(vb[i], "%u", v[i]); - vs += sep; - vs += vb[i]; - sep = "."; - } else { - vb[i][0] = 0; + cmPolicies::PolicyStatus const cmp0096 = + this->Makefile->GetPolicyStatus(cmPolicies::CMP0096); + + constexpr std::size_t MAX_VERSION_COMPONENTS = 4u; + std::string version_string; + std::array<std::string, MAX_VERSION_COMPONENTS> version_components; + + if (cmp0096 == cmPolicies::OLD || cmp0096 == cmPolicies::WARN) { + char vb[MAX_VERSION_COMPONENTS][std::numeric_limits<unsigned>::digits10]; + unsigned v[MAX_VERSION_COMPONENTS] = { 0, 0, 0, 0 }; + const int vc = std::sscanf(version.c_str(), "%u.%u.%u.%u", &v[0], &v[1], + &v[2], &v[3]); + for (auto i = 0u; i < MAX_VERSION_COMPONENTS; ++i) { + if (int(i) < vc) { + std::sprintf(vb[i], "%u", v[i]); + version_string += &"."[std::size_t(i == 0)]; + version_string += vb[i]; + version_components[i] = vb[i]; + } else { + vb[i][0] = '\x00'; + } + } + } else { + // The regex above verified that we have a .-separated string of + // non-negative integer components. Keep the original string. + version_string = std::move(version); + // Split the integer components. + auto components = cmSystemTools::SplitString(version_string, '.'); + for (auto i = 0u; i < components.size(); ++i) { + version_components[i] = std::move(components[i]); } } std::string vv; vv = projectName + "_VERSION"; - this->Makefile->AddDefinition("PROJECT_VERSION", vs.c_str()); - this->Makefile->AddDefinition(vv, vs.c_str()); + this->Makefile->AddDefinition("PROJECT_VERSION", version_string); + this->Makefile->AddDefinition(vv, version_string); vv = projectName + "_VERSION_MAJOR"; - this->Makefile->AddDefinition("PROJECT_VERSION_MAJOR", vb[0]); - this->Makefile->AddDefinition(vv, vb[0]); + this->Makefile->AddDefinition("PROJECT_VERSION_MAJOR", + version_components[0]); + this->Makefile->AddDefinition(vv, version_components[0]); vv = projectName + "_VERSION_MINOR"; - this->Makefile->AddDefinition("PROJECT_VERSION_MINOR", vb[1]); - this->Makefile->AddDefinition(vv, vb[1]); + this->Makefile->AddDefinition("PROJECT_VERSION_MINOR", + version_components[1]); + this->Makefile->AddDefinition(vv, version_components[1]); vv = projectName + "_VERSION_PATCH"; - this->Makefile->AddDefinition("PROJECT_VERSION_PATCH", vb[2]); - this->Makefile->AddDefinition(vv, vb[2]); + this->Makefile->AddDefinition("PROJECT_VERSION_PATCH", + version_components[2]); + this->Makefile->AddDefinition(vv, version_components[2]); vv = projectName + "_VERSION_TWEAK"; - this->Makefile->AddDefinition("PROJECT_VERSION_TWEAK", vb[3]); - this->Makefile->AddDefinition(vv, vb[3]); + this->Makefile->AddDefinition("PROJECT_VERSION_TWEAK", + version_components[3]); + this->Makefile->AddDefinition(vv, version_components[3]); // Also, try set top level variables - TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION", vs.c_str()); - TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_MAJOR", vb[0]); - TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_MINOR", vb[1]); - TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_PATCH", vb[2]); - TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_TWEAK", vb[3]); + TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION", version_string.c_str()); + TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_MAJOR", + version_components[0].c_str()); + TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_MINOR", + version_components[1].c_str()); + TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_PATCH", + version_components[2].c_str()); + TopLevelCMakeVarCondSet("CMAKE_PROJECT_VERSION_TWEAK", + version_components[3].c_str()); } else if (cmp0048 != cmPolicies::OLD) { // Set project VERSION variables to empty - std::vector<std::string> vv; - vv.emplace_back("PROJECT_VERSION"); - vv.emplace_back("PROJECT_VERSION_MAJOR"); - vv.emplace_back("PROJECT_VERSION_MINOR"); - vv.emplace_back("PROJECT_VERSION_PATCH"); - vv.emplace_back("PROJECT_VERSION_TWEAK"); - vv.push_back(projectName + "_VERSION"); - vv.push_back(projectName + "_VERSION_MAJOR"); - vv.push_back(projectName + "_VERSION_MINOR"); - vv.push_back(projectName + "_VERSION_PATCH"); - vv.push_back(projectName + "_VERSION_TWEAK"); + std::vector<std::string> vv = { "PROJECT_VERSION", + "PROJECT_VERSION_MAJOR", + "PROJECT_VERSION_MINOR", + "PROJECT_VERSION_PATCH", + "PROJECT_VERSION_TWEAK", + projectName + "_VERSION", + projectName + "_VERSION_MAJOR", + projectName + "_VERSION_MINOR", + projectName + "_VERSION_PATCH", + projectName + "_VERSION_TWEAK" }; if (this->Makefile->IsRootMakefile()) { vv.emplace_back("CMAKE_PROJECT_VERSION"); vv.emplace_back("CMAKE_PROJECT_VERSION_MAJOR"); @@ -287,7 +306,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, } std::string vw; for (std::string const& i : vv) { - const char* v = this->Makefile->GetDefinition(i); + const char* const v = this->Makefile->GetDefinition(i); if (v && *v) { if (cmp0048 == cmPolicies::WARN) { if (!injectedProjectCommand) { @@ -307,20 +326,17 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, } } - this->Makefile->AddDefinition("PROJECT_DESCRIPTION", description.c_str()); - this->Makefile->AddDefinition(projectName + "_DESCRIPTION", - description.c_str()); + this->Makefile->AddDefinition("PROJECT_DESCRIPTION", description); + this->Makefile->AddDefinition(projectName + "_DESCRIPTION", description); TopLevelCMakeVarCondSet("CMAKE_PROJECT_DESCRIPTION", description.c_str()); - this->Makefile->AddDefinition("PROJECT_HOMEPAGE_URL", homepage.c_str()); - this->Makefile->AddDefinition(projectName + "_HOMEPAGE_URL", - homepage.c_str()); + this->Makefile->AddDefinition("PROJECT_HOMEPAGE_URL", homepage); + this->Makefile->AddDefinition(projectName + "_HOMEPAGE_URL", homepage); TopLevelCMakeVarCondSet("CMAKE_PROJECT_HOMEPAGE_URL", homepage.c_str()); if (languages.empty()) { // if no language is specified do c and c++ - languages.emplace_back("C"); - languages.emplace_back("CXX"); + languages = { "C", "CXX" }; } this->Makefile->EnableLanguage(languages, false); @@ -337,7 +353,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args, bool cmProjectCommand::IncludeByVariable(const std::string& variable) { - const char* include = this->Makefile->GetDefinition(variable); + const char* const include = this->Makefile->GetDefinition(variable); if (!include) { return true; } @@ -351,9 +367,9 @@ bool cmProjectCommand::IncludeByVariable(const std::string& variable) return true; } - std::string m = "could not find file:\n" - " "; - m += include; + std::string m = cmStrCat("could not find file:\n" + " ", + include); this->SetError(m); return false; } diff --git a/Source/cmProjectCommand.h b/Source/cmProjectCommand.h index f1d03e7..8b9bcc8 100644 --- a/Source/cmProjectCommand.h +++ b/Source/cmProjectCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -26,7 +28,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmProjectCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmProjectCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmProperty.cxx b/Source/cmProperty.cxx deleted file mode 100644 index 27f0ecd..0000000 --- a/Source/cmProperty.cxx +++ /dev/null @@ -1,26 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmProperty.h" - -void cmProperty::Set(const char* value) -{ - this->Value = value; - this->ValueHasBeenSet = true; -} - -void cmProperty::Append(const char* value, bool asString) -{ - if (!this->Value.empty() && *value && !asString) { - this->Value += ";"; - } - this->Value += value; - this->ValueHasBeenSet = true; -} - -const char* cmProperty::GetValue() const -{ - if (this->ValueHasBeenSet) { - return this->Value.c_str(); - } - return nullptr; -} diff --git a/Source/cmProperty.h b/Source/cmProperty.h index d11c5ef..80f131a 100644 --- a/Source/cmProperty.h +++ b/Source/cmProperty.h @@ -5,8 +5,6 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <string> - class cmProperty { public: @@ -22,22 +20,6 @@ public: CACHED_VARIABLE, INSTALL }; - - // set this property - void Set(const char* value); - - // append to this property - void Append(const char* value, bool asString = false); - - // get the value - const char* GetValue() const; - - // construct with the value not set - cmProperty() { this->ValueHasBeenSet = false; } - -protected: - std::string Value; - bool ValueHasBeenSet; }; #endif diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx index 3f6d7c8..3ed4c05 100644 --- a/Source/cmPropertyMap.cxx +++ b/Source/cmPropertyMap.cxx @@ -3,40 +3,21 @@ #include "cmPropertyMap.h" #include <algorithm> -#include <assert.h> #include <utility> -cmProperty* cmPropertyMap::GetOrCreateProperty(const std::string& name) +void cmPropertyMap::Clear() { - cmPropertyMap::iterator it = this->find(name); - cmProperty* prop; - if (it == this->end()) { - prop = &(*this)[name]; - } else { - prop = &(it->second); - } - return prop; -} - -std::vector<std::string> cmPropertyMap::GetPropertyList() const -{ - std::vector<std::string> keyList; - for (auto const& i : *this) { - keyList.push_back(i.first); - } - std::sort(keyList.begin(), keyList.end()); - return keyList; + Map_.clear(); } void cmPropertyMap::SetProperty(const std::string& name, const char* value) { if (!value) { - this->erase(name); + Map_.erase(name); return; } - cmProperty* prop = this->GetOrCreateProperty(name); - prop->Set(value); + Map_[name] = value; } void cmPropertyMap::AppendProperty(const std::string& name, const char* value, @@ -47,17 +28,53 @@ void cmPropertyMap::AppendProperty(const std::string& name, const char* value, return; } - cmProperty* prop = this->GetOrCreateProperty(name); - prop->Append(value, asString); + { + std::string& pVal = Map_[name]; + if (!pVal.empty() && !asString) { + pVal += ';'; + } + pVal += value; + } +} + +void cmPropertyMap::RemoveProperty(const std::string& name) +{ + Map_.erase(name); } const char* cmPropertyMap::GetPropertyValue(const std::string& name) const { - assert(!name.empty()); + { + auto it = Map_.find(name); + if (it != Map_.end()) { + return it->second.c_str(); + } + } + return nullptr; +} - cmPropertyMap::const_iterator it = this->find(name); - if (it == this->end()) { - return nullptr; +std::vector<std::string> cmPropertyMap::GetKeys() const +{ + std::vector<std::string> keyList; + keyList.reserve(Map_.size()); + for (auto const& item : Map_) { + keyList.push_back(item.first); + } + std::sort(keyList.begin(), keyList.end()); + return keyList; +} + +std::vector<std::pair<std::string, std::string>> cmPropertyMap::GetList() const +{ + typedef std::pair<std::string, std::string> StringPair; + std::vector<StringPair> kvList; + kvList.reserve(Map_.size()); + for (auto const& item : Map_) { + kvList.emplace_back(item.first, item.second); } - return it->second.GetValue(); + std::sort(kvList.begin(), kvList.end(), + [](StringPair const& a, StringPair const& b) { + return a.first < b.first; + }); + return kvList; } diff --git a/Source/cmPropertyMap.h b/Source/cmPropertyMap.h index 5a05150..9aed349 100644 --- a/Source/cmPropertyMap.h +++ b/Source/cmPropertyMap.h @@ -5,25 +5,47 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include "cmProperty.h" - -#include <map> #include <string> +#include <unordered_map> +#include <utility> #include <vector> -class cmPropertyMap : public std::map<std::string, cmProperty> +/** \class cmPropertyMap + * \brief String property map. + */ +class cmPropertyMap { public: - cmProperty* GetOrCreateProperty(const std::string& name); + // -- General + + //! Clear property list + void Clear(); - std::vector<std::string> GetPropertyList() const; + // -- Properties + //! Set the property value void SetProperty(const std::string& name, const char* value); + //! Append to the property value void AppendProperty(const std::string& name, const char* value, bool asString = false); + //! Get the property value const char* GetPropertyValue(const std::string& name) const; + + //! Remove the property @a name from the map + void RemoveProperty(const std::string& name); + + // -- Lists + + //! Get a sorted list of property keys + std::vector<std::string> GetKeys() const; + + //! Get a sorted by key list of property key,value pairs + std::vector<std::pair<std::string, std::string>> GetList() const; + +private: + std::unordered_map<std::string, std::string> Map_; }; #endif diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx index 9a764c6..ba82813 100644 --- a/Source/cmQTWrapCPPCommand.cxx +++ b/Source/cmQTWrapCPPCommand.cxx @@ -6,6 +6,7 @@ #include "cmMakefile.h" #include "cmRange.h" #include "cmSourceFile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include <utility> @@ -37,10 +38,8 @@ bool cmQTWrapCPPCommand::InitialPass(std::vector<std::string> const& args, // Compute the name of the file to generate. std::string srcName = cmSystemTools::GetFilenameWithoutLastExtension(arg); - std::string newName = this->Makefile->GetCurrentBinaryDirectory(); - newName += "/moc_"; - newName += srcName; - newName += ".cxx"; + std::string newName = cmStrCat( + this->Makefile->GetCurrentBinaryDirectory(), "/moc_", srcName, ".cxx"); cmSourceFile* sf = this->Makefile->GetOrCreateSource(newName, true); if (curr) { sf->SetProperty("ABSTRACT", curr->GetProperty("ABSTRACT")); @@ -89,6 +88,6 @@ bool cmQTWrapCPPCommand::InitialPass(std::vector<std::string> const& args, } // Store the final list of source files. - this->Makefile->AddDefinition(sourceList, sourceListValue.c_str()); + this->Makefile->AddDefinition(sourceList, sourceListValue); return true; } diff --git a/Source/cmQTWrapCPPCommand.h b/Source/cmQTWrapCPPCommand.h index c1dcd54..88a2210 100644 --- a/Source/cmQTWrapCPPCommand.h +++ b/Source/cmQTWrapCPPCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -24,7 +26,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmQTWrapCPPCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmQTWrapCPPCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmQTWrapUICommand.cxx b/Source/cmQTWrapUICommand.cxx index 2223e2d..8bc914f 100644 --- a/Source/cmQTWrapUICommand.cxx +++ b/Source/cmQTWrapUICommand.cxx @@ -6,6 +6,7 @@ #include "cmMakefile.h" #include "cmRange.h" #include "cmSourceFile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include <utility> @@ -41,18 +42,12 @@ bool cmQTWrapUICommand::InitialPass(std::vector<std::string> const& args, // Compute the name of the files to generate. std::string srcName = cmSystemTools::GetFilenameWithoutLastExtension(arg); - std::string hName = this->Makefile->GetCurrentBinaryDirectory(); - hName += "/"; - hName += srcName; - hName += ".h"; - std::string cxxName = this->Makefile->GetCurrentBinaryDirectory(); - cxxName += "/"; - cxxName += srcName; - cxxName += ".cxx"; - std::string mocName = this->Makefile->GetCurrentBinaryDirectory(); - mocName += "/moc_"; - mocName += srcName; - mocName += ".cxx"; + std::string hName = cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), + '/', srcName, ".h"); + std::string cxxName = cmStrCat( + this->Makefile->GetCurrentBinaryDirectory(), '/', srcName, ".cxx"); + std::string mocName = cmStrCat( + this->Makefile->GetCurrentBinaryDirectory(), "/moc_", srcName, ".cxx"); // Compute the name of the ui file from which to generate others. std::string uiName; @@ -132,7 +127,7 @@ bool cmQTWrapUICommand::InitialPass(std::vector<std::string> const& args, } // Store the final list of source files and headers. - this->Makefile->AddDefinition(sourceList, sourceListValue.c_str()); - this->Makefile->AddDefinition(headerList, headerListValue.c_str()); + this->Makefile->AddDefinition(sourceList, sourceListValue); + this->Makefile->AddDefinition(headerList, headerListValue); return true; } diff --git a/Source/cmQTWrapUICommand.h b/Source/cmQTWrapUICommand.h index 15cab40..6a346d4 100644 --- a/Source/cmQTWrapUICommand.h +++ b/Source/cmQTWrapUICommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -23,7 +25,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmQTWrapUICommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmQTWrapUICommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index 3683edd..9d29e5c 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -5,6 +5,7 @@ #include "cmAlgorithms.h" #include "cmDuration.h" #include "cmProcessOutput.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" @@ -52,9 +53,7 @@ void MergeOptions(std::vector<std::string>& baseOpts, } } // Test if this is a value option and change the existing value - if (!optName.empty() && - (std::find(valueOpts.begin(), valueOpts.end(), optName) != - valueOpts.end())) { + if (!optName.empty() && cmContains(valueOpts, optName)) { const Iter existItNext(existIt + 1); const CIter fitNext(fit + 1); if ((existItNext != baseOpts.end()) && (fitNext != fitEnd)) { @@ -293,9 +292,8 @@ static bool RccListParseOutput(std::string const& rccStdOut, std::string::size_type pos = eline.find(searchString); if (pos == std::string::npos) { - error = "rcc lists unparsable output:\n"; - error += cmQtAutoGen::Quoted(eline); - error += "\n"; + error = cmStrCat("rcc lists unparsable output:\n", + cmQtAutoGen::Quoted(eline), '\n'); return false; } pos += searchString.length(); @@ -324,9 +322,8 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile, error.clear(); if (!cmSystemTools::FileExists(qrcFile, true)) { - error = "The resource file "; - error += Quoted(qrcFile); - error += " does not exist."; + error = + cmStrCat("The resource file ", Quoted(qrcFile), " does not exist."); return false; } @@ -352,9 +349,8 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile, // Log command if (verbose) { - std::string msg = "Running command:\n"; - msg += QuotedCommand(cmd); - msg += '\n'; + std::string msg = + cmStrCat("Running command:\n", QuotedCommand(cmd), '\n'); cmSystemTools::Stdout(msg); } @@ -363,9 +359,8 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile, cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto); } if (!result || retVal) { - error = "The rcc list process failed for "; - error += Quoted(qrcFile); - error += "\n"; + error = + cmStrCat("The rcc list process failed for ", Quoted(qrcFile), '\n'); if (!rccStdOut.empty()) { error += rccStdOut; error += "\n"; @@ -391,9 +386,8 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile, osst << ifs.rdbuf(); qrcContents = osst.str(); } else { - error = "The resource file "; - error += Quoted(qrcFile); - error += " is not readable\n"; + error = cmStrCat("The resource file ", Quoted(qrcFile), + " is not readable\n"); return false; } } diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index 9c52129..619fff1 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -5,7 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <memory> // IWYU pragma: keep +#include <memory> #include <string> #include <vector> diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx index ef8a56b..abc69d0 100644 --- a/Source/cmQtAutoGenGlobalInitializer.cxx +++ b/Source/cmQtAutoGenGlobalInitializer.cxx @@ -1,10 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQtAutoGenGlobalInitializer.h" -#include "cmQtAutoGen.h" -#include "cmQtAutoGenInitializer.h" -#include "cmAlgorithms.h" #include "cmCustomCommandLines.h" #include "cmDuration.h" #include "cmGeneratorTarget.h" @@ -12,12 +9,16 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmProcessOutput.h" +#include "cmQtAutoGen.h" +#include "cmQtAutoGenInitializer.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" -#include <memory> +#include "cm_memory.hxx" + #include <utility> cmQtAutoGenGlobalInitializer::Keywords::Keywords() @@ -48,8 +49,7 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( { cmMakefile* makefile = localGen->GetMakefile(); // Detect global autogen target name - if (cmSystemTools::IsOn( - makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTOGEN_TARGET"))) { + if (cmIsOn(makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTOGEN_TARGET"))) { std::string targetName = makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTOGEN_TARGET_NAME"); if (targetName.empty()) { @@ -60,8 +60,7 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( } // Detect global autorcc target name - if (cmSystemTools::IsOn( - makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTORCC_TARGET"))) { + if (cmIsOn(makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTORCC_TARGET"))) { std::string targetName = makefile->GetSafeDefinition("CMAKE_GLOBAL_AUTORCC_TARGET_NAME"); if (targetName.empty()) { @@ -119,23 +118,17 @@ cmQtAutoGenGlobalInitializer::cmQtAutoGenGlobalInitializer( bool const uicDisabled = (uic && !uicAvailable); bool const rccDisabled = (rcc && !rccAvailable); if (mocDisabled || uicDisabled || rccDisabled) { - std::string msg = "AUTOGEN: No valid Qt version found for target "; - msg += target->GetName(); - msg += ". "; - msg += cmQtAutoGen::Tools(mocDisabled, uicDisabled, rccDisabled); - msg += " disabled. Consider adding:\n"; - { - std::string version = (qtVersion.second == 0) - ? std::string("<QTVERSION>") - : std::to_string(qtVersion.second); - std::string comp = uicDisabled ? "Widgets" : "Core"; - msg += " find_package(Qt"; - msg += version; - msg += " COMPONENTS "; - msg += comp; - msg += ")\n"; - } - msg += "to your CMakeLists.txt file."; + cmAlphaNum version = (qtVersion.second == 0) + ? cmAlphaNum("<QTVERSION>") + : cmAlphaNum(qtVersion.second); + cmAlphaNum component = uicDisabled ? "Widgets" : "Core"; + + std::string const msg = cmStrCat( + "AUTOGEN: No valid Qt version found for target ", + target->GetName(), ". ", + cmQtAutoGen::Tools(mocDisabled, uicDisabled, rccDisabled), + " disabled. Consider adding:\n", " find_package(Qt", version, + " COMPONENTS ", component, ")\n", "to your CMakeLists.txt file."); target->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, msg); } if (mocIsValid || uicIsValid || rccIsValid) { @@ -218,11 +211,8 @@ cmQtAutoGenGlobalInitializer::GetCompilerFeatures( // Check if the executable exists if (!cmSystemTools::FileExists(executable, true)) { - error = "The \""; - error += generator; - error += "\" executable "; - error += cmQtAutoGen::Quoted(executable); - error += " does not exist."; + error = cmStrCat("The \"", generator, "\" executable ", + cmQtAutoGen::Quoted(executable), " does not exist."); return cmQtAutoGen::CompilerFeaturesHandle(); } @@ -238,15 +228,10 @@ cmQtAutoGenGlobalInitializer::GetCompilerFeatures( command, &stdOut, &stdErr, &retVal, nullptr, cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto); if (!runResult) { - error = "Test run of \""; - error += generator; - error += "\" executable "; - error += cmQtAutoGen::Quoted(executable) + " failed.\n"; - error += cmQtAutoGen::QuotedCommand(command); - error += "\n"; - error += stdOut; - error += "\n"; - error += stdErr; + error = cmStrCat("Test run of \"", generator, "\" executable ", + cmQtAutoGen::Quoted(executable), " failed.\n", + cmQtAutoGen::QuotedCommand(command), '\n', stdOut, '\n', + stdErr); return cmQtAutoGen::CompilerFeaturesHandle(); } } diff --git a/Source/cmQtAutoGenGlobalInitializer.h b/Source/cmQtAutoGenGlobalInitializer.h index d56153a..d7f4cc6 100644 --- a/Source/cmQtAutoGenGlobalInitializer.h +++ b/Source/cmQtAutoGenGlobalInitializer.h @@ -8,7 +8,7 @@ #include "cmQtAutoGen.h" #include <map> -#include <memory> // IWYU pragma: keep +#include <memory> #include <string> #include <unordered_map> #include <vector> diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 9985f93..c355a5f 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -4,7 +4,6 @@ #include "cmQtAutoGen.h" #include "cmQtAutoGenGlobalInitializer.h" -#include "cmAlgorithms.h" #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" #include "cmFilePathChecksum.h" @@ -23,6 +22,7 @@ #include "cmSourceGroup.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmake.h" @@ -38,6 +38,8 @@ #include <utility> #include <vector> +#include "cm_memory.hxx" + static std::size_t GetParallelCPUCount() { static std::size_t count = 0; @@ -154,30 +156,27 @@ std::string cmQtAutoGenInitializer::InfoWriter::ListJoin(IT it_begin, return res; } -std::string cmQtAutoGenInitializer::InfoWriter::ConfigKey( - const char* key, std::string const& config) +inline std::string cmQtAutoGenInitializer::InfoWriter::ConfigKey( + cm::string_view key, std::string const& config) { - std::string ckey = key; - ckey += '_'; - ckey += config; - return ckey; + return cmStrCat(key, "_", config); } -void cmQtAutoGenInitializer::InfoWriter::Write(const char* key, +void cmQtAutoGenInitializer::InfoWriter::Write(cm::string_view key, std::string const& value) { Ofs_ << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value) << ")\n"; }; -void cmQtAutoGenInitializer::InfoWriter::WriteUInt(const char* key, +void cmQtAutoGenInitializer::InfoWriter::WriteUInt(cm::string_view key, unsigned int value) { Ofs_ << "set(" << key << " " << value << ")\n"; }; template <class C> -void cmQtAutoGenInitializer::InfoWriter::WriteStrings(const char* key, +void cmQtAutoGenInitializer::InfoWriter::WriteStrings(cm::string_view key, C const& container) { Ofs_ << "set(" << key << " \"" @@ -185,31 +184,29 @@ void cmQtAutoGenInitializer::InfoWriter::WriteStrings(const char* key, } void cmQtAutoGenInitializer::InfoWriter::WriteConfig( - const char* key, std::map<std::string, std::string> const& map) + cm::string_view key, std::map<std::string, std::string> const& map) { for (auto const& item : map) { - Write(ConfigKey(key, item.first).c_str(), item.second); + Write(ConfigKey(key, item.first), item.second); } }; template <class C> void cmQtAutoGenInitializer::InfoWriter::WriteConfigStrings( - const char* key, std::map<std::string, C> const& map) + cm::string_view key, std::map<std::string, C> const& map) { for (auto const& item : map) { - WriteStrings(ConfigKey(key, item.first).c_str(), item.second); + WriteStrings(ConfigKey(key, item.first), item.second); } } void cmQtAutoGenInitializer::InfoWriter::WriteNestedLists( - const char* key, std::vector<std::vector<std::string>> const& lists) + cm::string_view key, std::vector<std::vector<std::string>> const& lists) { std::vector<std::string> seplist; - for (const std::vector<std::string>& list : lists) { - std::string blist = "{"; - blist += ListJoin(list.begin(), list.end()); - blist += "}"; - seplist.push_back(std::move(blist)); + seplist.reserve(lists.size()); + for (std::vector<std::string> const& list : lists) { + seplist.push_back(cmStrCat("{", ListJoin(list.begin(), list.end()), "}")); } Write(key, cmJoin(seplist, cmQtAutoGen::ListSep)); }; @@ -246,9 +243,9 @@ bool cmQtAutoGenInitializer::InitCustomTargets() this->Verbosity = makefile->GetSafeDefinition("CMAKE_AUTOGEN_VERBOSE"); if (!this->Verbosity.empty()) { unsigned long iVerb = 0; - if (!cmSystemTools::StringToULong(this->Verbosity.c_str(), &iVerb)) { + if (!cmStrToULong(this->Verbosity, &iVerb)) { // Non numeric verbosity - this->Verbosity = cmSystemTools::IsOn(this->Verbosity) ? "1" : "0"; + this->Verbosity = cmIsOn(this->Verbosity) ? "1" : "0"; } } @@ -296,21 +293,15 @@ bool cmQtAutoGenInitializer::InitCustomTargets() std::string(), makefile->GetCurrentBinaryDirectory()); // Info directory - this->Dir.Info = cbd; - this->Dir.Info += "/CMakeFiles"; - this->Dir.Info += '/'; - this->Dir.Info += this->Target->GetName(); - this->Dir.Info += "_autogen"; - this->Dir.Info += ".dir"; + this->Dir.Info = + cmStrCat(cbd, "/CMakeFiles/", this->Target->GetName(), "_autogen.dir"); cmSystemTools::ConvertToUnixSlashes(this->Dir.Info); // Build directory this->Dir.Build = this->Target->GetSafeProperty("AUTOGEN_BUILD_DIR"); if (this->Dir.Build.empty()) { - this->Dir.Build = cbd; - this->Dir.Build += '/'; - this->Dir.Build += this->Target->GetName(); - this->Dir.Build += "_autogen"; + this->Dir.Build = + cmStrCat(cbd, '/', this->Target->GetName(), "_autogen"); } cmSystemTools::ConvertToUnixSlashes(this->Dir.Build); // Cleanup build directory @@ -321,8 +312,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets() cmSystemTools::ConvertToUnixSlashes(this->Dir.Work); // Include directory - this->Dir.Include = this->Dir.Build; - this->Dir.Include += "/include"; + this->Dir.Include = cmStrCat(this->Dir.Build, "/include"); if (this->MultiConfig) { this->Dir.Include += "_$<CONFIG>"; } @@ -330,9 +320,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets() if (this->MultiConfig) { for (std::string const& cfg : this->ConfigsList) { std::string& dir = this->Dir.ConfigInclude[cfg]; - dir = this->Dir.Build; - dir += "/include_"; - dir += cfg; + dir = cmStrCat(this->Dir.Build, "/include_", cfg); } } } @@ -350,8 +338,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets() } // Autogen target name - this->AutogenTarget.Name = this->Target->GetName(); - this->AutogenTarget.Name += "_autogen"; + this->AutogenTarget.Name = cmStrCat(this->Target->GetName(), "_autogen"); // Autogen target parallel processing this->AutogenTarget.Parallel = @@ -364,11 +351,11 @@ bool cmQtAutoGenInitializer::InitCustomTargets() // Autogen target info and settings files { - this->AutogenTarget.InfoFile = this->Dir.Info; - this->AutogenTarget.InfoFile += "/AutogenInfo.cmake"; + this->AutogenTarget.InfoFile = + cmStrCat(this->Dir.Info, "/AutogenInfo.cmake"); - this->AutogenTarget.SettingsFile = this->Dir.Info; - this->AutogenTarget.SettingsFile += "/AutogenOldSettings.txt"; + this->AutogenTarget.SettingsFile = + cmStrCat(this->Dir.Info, "/AutogenOldSettings.txt"); if (this->MultiConfig) { for (std::string const& cfg : this->ConfigsList) { @@ -381,8 +368,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets() this->AddCleanFile(this->AutogenTarget.SettingsFile); } - this->AutogenTarget.ParseCacheFile = this->Dir.Info; - this->AutogenTarget.ParseCacheFile += "/ParseCache.txt"; + this->AutogenTarget.ParseCacheFile = + cmStrCat(this->Dir.Info, "/ParseCache.txt"); this->AddCleanFile(this->AutogenTarget.ParseCacheFile); } @@ -394,8 +381,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets() std::string const deps = this->Target->GetSafeProperty("AUTOGEN_TARGET_DEPENDS"); if (!deps.empty()) { - std::vector<std::string> extraDeps; - cmSystemTools::ExpandListArgument(deps, extraDeps); + std::vector<std::string> extraDeps = cmExpandedList(deps); for (std::string const& depName : extraDeps) { // Allow target and file dependencies auto* depTarget = makefile->FindTargetToUse(depName); @@ -410,13 +396,12 @@ bool cmQtAutoGenInitializer::InitCustomTargets() // CMAKE_AUTOMOC_RELAXED_MODE deprecation warning if (this->Moc.Enabled) { - if (cmSystemTools::IsOn( - makefile->GetDefinition("CMAKE_AUTOMOC_RELAXED_MODE"))) { - std::string msg = "AUTOMOC: CMAKE_AUTOMOC_RELAXED_MODE is " - "deprecated an will be removed in the future. "; - msg += "Consider disabling it and converting the target "; - msg += this->Target->GetName(); - msg += " to regular mode."; + if (cmIsOn(makefile->GetDefinition("CMAKE_AUTOMOC_RELAXED_MODE"))) { + std::string msg = + cmStrCat("AUTOMOC: CMAKE_AUTOMOC_RELAXED_MODE is " + "deprecated an will be removed in the future. Consider " + "disabling it and converting the target ", + this->Target->GetName(), " to regular mode."); makefile->IssueMessage(MessageType::AUTHOR_WARNING, msg); } } @@ -456,8 +441,8 @@ bool cmQtAutoGenInitializer::InitMoc() cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); // Mocs compilation file - this->Moc.MocsCompilation = this->Dir.Build; - this->Moc.MocsCompilation += "/mocs_compilation.cpp"; + this->Moc.MocsCompilation = + cmStrCat(this->Dir.Build, "/mocs_compilation.cpp"); // Moc predefs command if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") && @@ -546,7 +531,7 @@ bool cmQtAutoGenInitializer::InitUic() std::string const usp = this->Target->GetSafeProperty("AUTOUIC_SEARCH_PATHS"); if (!usp.empty()) { - cmSystemTools::ExpandListArgument(usp, this->Uic.SearchPaths); + cmExpandList(usp, this->Uic.SearchPaths); std::string const& srcDir = makefile->GetCurrentSourceDirectory(); for (std::string& path : this->Uic.SearchPaths) { path = cmSystemTools::CollapseFullPath(path, srcDir); @@ -620,6 +605,7 @@ bool cmQtAutoGenInitializer::InitRcc() bool cmQtAutoGenInitializer::InitScanFiles() { cmMakefile* makefile = this->Target->Target->GetMakefile(); + cmake const* cm = makefile->GetCMakeInstance(); auto const& kw = this->GlobalInitializer->kw(); auto makeMUFile = [this, &kw](cmSourceFile* sf, std::string const& fullPath, @@ -665,25 +651,21 @@ bool cmQtAutoGenInitializer::InitScanFiles() if (!pathError.empty() || fullPath.empty()) { continue; } - std::string const& ext = sf->GetExtension(); + std::string const& extLower = + cmSystemTools::LowerCase(sf->GetExtension()); // Register files that will be scanned by moc or uic if (this->MocOrUicEnabled()) { - switch (cmSystemTools::GetFileFormat(ext)) { - case cmSystemTools::HEADER_FILE_FORMAT: - addMUFile(makeMUFile(sf, fullPath, true), true); - break; - case cmSystemTools::CXX_FILE_FORMAT: - addMUFile(makeMUFile(sf, fullPath, true), false); - break; - default: - break; + if (cm->IsHeaderExtension(extLower)) { + addMUFile(makeMUFile(sf, fullPath, true), true); + } else if (cm->IsSourceExtension(extLower)) { + addMUFile(makeMUFile(sf, fullPath, true), false); } } // Register rcc enabled files if (this->Rcc.Enabled) { - if ((ext == kw.qrc) && !sf->GetPropertyAsBool(kw.SKIP_AUTOGEN) && + if ((extLower == kw.qrc) && !sf->GetPropertyAsBool(kw.SKIP_AUTOGEN) && !sf->GetPropertyAsBool(kw.SKIP_AUTORCC)) { // Register qrc file Qrc qrc; @@ -695,7 +677,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() { std::string const opts = sf->GetSafeProperty(kw.AUTORCC_OPTIONS); if (!opts.empty()) { - cmSystemTools::ExpandListArgument(opts, qrc.Options); + cmExpandList(opts, qrc.Options); } } this->Rcc.Qrcs.push_back(std::move(qrc)); @@ -715,21 +697,20 @@ bool cmQtAutoGenInitializer::InitScanFiles() extraHeaders.reserve(this->AutogenTarget.Sources.size() * 2); // Header search suffixes and extensions std::array<std::string, 2> const suffixes{ { "", "_p" } }; - auto const& exts = makefile->GetCMakeInstance()->GetHeaderExtensions(); + auto const& exts = cm->GetHeaderExtensions(); // Scan through sources for (auto const& pair : this->AutogenTarget.Sources) { MUFile const& muf = *pair.second; if (muf.MocIt || muf.UicIt) { // Search for the default header file and a private header std::string const& srcPath = muf.SF->GetFullPath(); - std::string basePath = cmQtAutoGen::SubDirPrefix(srcPath); - basePath += cmSystemTools::GetFilenameWithoutLastExtension(srcPath); + std::string basePath = + cmStrCat(cmQtAutoGen::SubDirPrefix(srcPath), + cmSystemTools::GetFilenameWithoutLastExtension(srcPath)); for (auto const& suffix : suffixes) { std::string const suffixedPath = basePath + suffix; for (auto const& ext : exts) { - std::string fullPath = suffixedPath; - fullPath += '.'; - fullPath += ext; + std::string fullPath = cmStrCat(suffixedPath, '.', ext); auto constexpr locationKind = cmSourceFileLocationKind::Known; cmSourceFile* sf = makefile->GetSource(fullPath, locationKind); @@ -784,10 +765,10 @@ bool cmQtAutoGenInitializer::InitScanFiles() if (!pathError.empty() || fullPath.empty()) { continue; } - std::string const& ext = sf->GetExtension(); + std::string const& extLower = + cmSystemTools::LowerCase(sf->GetExtension()); - auto const fileFormat = cmSystemTools::GetFileFormat(ext); - if (fileFormat == cmSystemTools::HEADER_FILE_FORMAT) { + if (cm->IsHeaderExtension(extLower)) { if (this->AutogenTarget.Headers.find(sf) == this->AutogenTarget.Headers.end()) { auto muf = makeMUFile(sf, fullPath, false); @@ -795,7 +776,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() this->AutogenTarget.Headers.emplace(sf, std::move(muf)); } } - } else if (fileFormat == cmSystemTools::CXX_FILE_FORMAT) { + } else if (cm->IsSourceExtension(extLower)) { if (this->AutogenTarget.Sources.find(sf) == this->AutogenTarget.Sources.end()) { auto muf = makeMUFile(sf, fullPath, false); @@ -803,7 +784,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() this->AutogenTarget.Sources.emplace(sf, std::move(muf)); } } - } else if (this->Uic.Enabled && (ext == kw.ui)) { + } else if (this->Uic.Enabled && (extLower == kw.ui)) { // .ui file std::string realPath = cmSystemTools::GetRealPath(fullPath); bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN); @@ -814,8 +795,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() std::string const uicOpts = sf->GetSafeProperty(kw.AUTOUIC_OPTIONS); if (!uicOpts.empty()) { this->Uic.FileFiles.push_back(std::move(realPath)); - std::vector<std::string> optsVec; - cmSystemTools::ExpandListArgument(uicOpts, optsVec); + std::vector<std::string> optsVec = cmExpandedList(uicOpts); this->Uic.FileOptions.push_back(std::move(optsVec)); } } else { @@ -834,9 +814,8 @@ bool cmQtAutoGenInitializer::InitScanFiles() this->AutogenTarget.DependFiles.insert(muf->RealPath); } } else if (this->CMP0071Warn) { - std::string msg; - msg += cmPolicies::GetPolicyWarning(cmPolicies::CMP0071); - msg += '\n'; + std::string msg = + cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0071), '\n'); std::string property; if (this->Moc.Enabled && this->Uic.Enabled) { property = kw.SKIP_AUTOGEN; @@ -869,9 +848,8 @@ bool cmQtAutoGenInitializer::InitScanFiles() if (!this->Rcc.Qrcs.empty()) { const bool modernQt = (this->QtVersion.Major >= 5); // Target rcc options - std::vector<std::string> optionsTarget; - cmSystemTools::ExpandListArgument( - this->Target->GetSafeProperty(kw.AUTORCC_OPTIONS), optionsTarget); + std::vector<std::string> optionsTarget = + cmExpandedList(this->Target->GetSafeProperty(kw.AUTORCC_OPTIONS)); // Check if file name is unique for (Qrc& qrc : this->Rcc.Qrcs) { @@ -889,30 +867,19 @@ bool cmQtAutoGenInitializer::InitScanFiles() for (Qrc& qrc : this->Rcc.Qrcs) { qrc.PathChecksum = fpathCheckSum.getPart(qrc.QrcFile); // RCC output file name + qrc.RccFile = cmStrCat(this->Dir.Build + "/", qrc.PathChecksum, + "/qrc_", qrc.QrcName, ".cpp"); { - std::string rccFile = this->Dir.Build + "/"; - rccFile += qrc.PathChecksum; - rccFile += "/qrc_"; - rccFile += qrc.QrcName; - rccFile += ".cpp"; - qrc.RccFile = std::move(rccFile); - } - { - std::string base = this->Dir.Info; - base += "/RCC"; - base += qrc.QrcName; + std::string base = cmStrCat(this->Dir.Info, "/RCC", qrc.QrcName); if (!qrc.Unique) { base += qrc.PathChecksum; } - qrc.LockFile = base; - qrc.LockFile += ".lock"; + qrc.LockFile = cmStrCat(base, ".lock"); - qrc.InfoFile = base; - qrc.InfoFile += "Info.cmake"; + qrc.InfoFile = cmStrCat(base, "Info.cmake"); - qrc.SettingsFile = base; - qrc.SettingsFile += "Settings.txt"; + qrc.SettingsFile = cmStrCat(base, "Settings.txt"); if (this->MultiConfig) { for (std::string const& cfg : this->ConfigsList) { @@ -933,8 +900,7 @@ bool cmQtAutoGenInitializer::InitScanFiles() // Replace '-' with '_'. The former is not valid for symbol names. std::replace(name.begin(), name.end(), '-', '_'); if (!qrc.Unique) { - name += "_"; - name += qrc.PathChecksum; + name += cmStrCat("_", qrc.PathChecksum); } std::vector<std::string> nameOpts; nameOpts.emplace_back("-name"); @@ -991,10 +957,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() } tools += "UIC"; } - autogenComment = "Automatic "; - autogenComment += tools; - autogenComment += " for target "; - autogenComment += this->Target->GetName(); + autogenComment = + cmStrCat("Automatic ", tools, " for target ", this->Target->GetName()); } // Compose command lines @@ -1158,16 +1122,14 @@ bool cmQtAutoGenInitializer::InitRccTargets() currentLine.push_back("$<CONFIG>"); commandLines.push_back(std::move(currentLine)); } - std::string ccComment = "Automatic RCC for "; - ccComment += FileProjectRelativePath(makefile, qrc.QrcFile); + std::string ccComment = cmStrCat( + "Automatic RCC for ", FileProjectRelativePath(makefile, qrc.QrcFile)); if (qrc.Generated || this->Rcc.GlobalTarget) { // Create custom rcc target std::string ccName; { - ccName = this->Target->GetName(); - ccName += "_arcc_"; - ccName += qrc.QrcName; + ccName = cmStrCat(this->Target->GetName(), "_arcc_", qrc.QrcName); if (!qrc.Unique) { ccName += "_"; ccName += qrc.PathChecksum; @@ -1227,9 +1189,8 @@ bool cmQtAutoGenInitializer::SetupCustomTargets() { // Create info directory on demand if (!cmSystemTools::MakeDirectory(this->Dir.Info)) { - std::string emsg = ("AutoGen: Could not create directory: "); - emsg += Quoted(this->Dir.Info); - cmSystemTools::Error(emsg); + cmSystemTools::Error(cmStrCat("AutoGen: Could not create directory: ", + Quoted(this->Dir.Info))); return false; } @@ -1312,10 +1273,8 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() } if (muf->MocIt || muf->UicIt) { headers.emplace_back(muf->RealPath); - std::string flags; - flags += muf->MocIt ? 'M' : 'm'; - flags += muf->UicIt ? 'U' : 'u'; - headersFlags.emplace_back(std::move(flags)); + headersFlags.emplace_back( + cmStrCat(muf->MocIt ? "M" : "m", muf->UicIt ? "U" : "u")); } } } @@ -1324,14 +1283,13 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() cmFilePathChecksum const fpathCheckSum(makefile); std::unordered_set<std::string> emitted; for (std::string const& hdr : headers) { - std::string basePath = fpathCheckSum.getPart(hdr); - basePath += "/moc_"; - basePath += cmSystemTools::GetFilenameWithoutLastExtension(hdr); - for (unsigned int ii = 1; ii != 1024; ++ii) { + std::string basePath = + cmStrCat(fpathCheckSum.getPart(hdr), "/moc_", + cmSystemTools::GetFilenameWithoutLastExtension(hdr)); + for (int ii = 1; ii != 1024; ++ii) { std::string path = basePath; if (ii > 1) { - path += '_'; - path += std::to_string(ii); + path += cmStrCat("_", ii); } path += ".cpp"; if (emitted.emplace(path).second) { @@ -1370,10 +1328,8 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() } if (muf->MocIt || muf->UicIt) { sources.emplace_back(muf->RealPath); - std::string flags; - flags += muf->MocIt ? 'M' : 'm'; - flags += muf->UicIt ? 'U' : 'u'; - sourcesFlags.emplace_back(std::move(flags)); + sourcesFlags.emplace_back( + cmStrCat(muf->MocIt ? "M" : "m", muf->UicIt ? "U" : "u")); } } } @@ -1427,9 +1383,8 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() ofs.WriteStrings("AM_UIC_SEARCH_PATHS", this->Uic.SearchPaths); } } else { - std::string err = "AutoGen: Could not write file "; - err += this->AutogenTarget.InfoFile; - cmSystemTools::Error(err); + cmSystemTools::Error(cmStrCat("AutoGen: Could not write file ", + this->AutogenTarget.InfoFile)); return false; } @@ -1468,9 +1423,8 @@ bool cmQtAutoGenInitializer::SetupWriteRccInfo() ofs.WriteStrings("ARCC_OPTIONS", qrc.Options); ofs.WriteStrings("ARCC_INPUTS", qrc.Resources); } else { - std::string err = "AutoRcc: Could not write file "; - err += qrc.InfoFile; - cmSystemTools::Error(err); + cmSystemTools::Error( + cmStrCat("AutoRcc: Could not write file ", qrc.InfoFile)); return false; } } @@ -1525,13 +1479,10 @@ bool cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName, if (!groupName.empty()) { sourceGroup = makefile->GetOrCreateSourceGroup(groupName); if (sourceGroup == nullptr) { - std::string err; - err += genNameUpper; - err += " error in "; - err += property; - err += ": Could not find or create the source group "; - err += cmQtAutoGen::Quoted(groupName); - cmSystemTools::Error(err); + cmSystemTools::Error( + cmStrCat(genNameUpper, " error in ", property, + ": Could not find or create the source group ", + cmQtAutoGen::Quoted(groupName))); return false; } } @@ -1551,7 +1502,7 @@ void cmQtAutoGenInitializer::AddCleanFile(std::string const& fileName) static unsigned int CharPtrToUInt(const char* const input) { unsigned long tmp = 0; - if (input != nullptr && cmSystemTools::StringToULong(input, &tmp)) { + if (input != nullptr && cmStrToULong(input, &tmp)) { return static_cast<unsigned int>(tmp); } return 0; @@ -1623,12 +1574,8 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, bool ignoreMissingTarget) const { auto print_err = [this, &genVars](std::string const& err) { - std::string msg = genVars.GenNameUpper; - msg += " for target "; - msg += this->Target->GetName(); - msg += ": "; - msg += err; - cmSystemTools::Error(msg); + cmSystemTools::Error(cmStrCat(genVars.GenNameUpper, " for target ", + this->Target->GetName(), ": ", err)); }; // Custom executable @@ -1688,11 +1635,8 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, std::make_shared<cmQtAutoGen::CompilerFeatures>(); return true; } - std::string err = "Could not find "; - err += executable; - err += " executable target "; - err += targetName; - print_err(err); + print_err(cmStrCat("Could not find ", executable, " executable target ", + targetName)); return false; } } diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index aa073d1..7d72cad 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -6,9 +6,10 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmGeneratedFileStream.h" #include "cmQtAutoGen.h" +#include "cm_string_view.hxx" #include <map> -#include <memory> // IWYU pragma: keep +#include <memory> #include <ostream> #include <set> #include <string> @@ -85,24 +86,24 @@ public: /// @return True if the file is open explicit operator bool() const { return static_cast<bool>(Ofs_); } - void Write(const char* text) { Ofs_ << text; } - void Write(const char* key, std::string const& value); - void WriteUInt(const char* key, unsigned int value); + void Write(cm::string_view text) { Ofs_ << text; } + void Write(cm::string_view, std::string const& value); + void WriteUInt(cm::string_view, unsigned int value); template <class C> - void WriteStrings(const char* key, C const& container); - void WriteConfig(const char* key, + void WriteStrings(cm::string_view, C const& container); + void WriteConfig(cm::string_view, std::map<std::string, std::string> const& map); template <class C> - void WriteConfigStrings(const char* key, + void WriteConfigStrings(cm::string_view, std::map<std::string, C> const& map); - void WriteNestedLists(const char* key, + void WriteNestedLists(cm::string_view, std::vector<std::vector<std::string>> const& lists); private: template <class IT> static std::string ListJoin(IT it_begin, IT it_end); - static std::string ConfigKey(const char* key, std::string const& config); + static std::string ConfigKey(cm::string_view, std::string const& config); private: cmGeneratedFileStream Ofs_; diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx index e1c435b..90361a9 100644 --- a/Source/cmQtAutoGenerator.cxx +++ b/Source/cmQtAutoGenerator.cxx @@ -1,16 +1,17 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQtAutoGenerator.h" -#include "cmQtAutoGen.h" +#include "cm_memory.hxx" #include "cmsys/FStream.hxx" -#include "cmAlgorithms.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmQtAutoGen.h" #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" @@ -21,11 +22,11 @@ cmQtAutoGenerator::Logger::Logger() std::string verbose; if (cmSystemTools::GetEnv("VERBOSE", verbose) && !verbose.empty()) { unsigned long iVerbose = 0; - if (cmSystemTools::StringToULong(verbose.c_str(), &iVerbose)) { + if (cmStrToULong(verbose, &iVerbose)) { SetVerbosity(static_cast<unsigned int>(iVerbose)); } else { // Non numeric verbosity - SetVerbose(cmSystemTools::IsOn(verbose)); + SetVerbose(cmIsOn(verbose)); } } } @@ -33,7 +34,7 @@ cmQtAutoGenerator::Logger::Logger() std::string colorEnv; cmSystemTools::GetEnv("COLOR", colorEnv); if (!colorEnv.empty()) { - SetColorOutput(cmSystemTools::IsOn(colorEnv)); + SetColorOutput(cmIsOn(colorEnv)); } else { SetColorOutput(true); } @@ -45,7 +46,7 @@ cmQtAutoGenerator::Logger::~Logger() = default; void cmQtAutoGenerator::Logger::RaiseVerbosity(std::string const& value) { unsigned long verbosity = 0; - if (cmSystemTools::StringToULong(value.c_str(), &verbosity)) { + if (cmStrToULong(value, &verbosity)) { if (this->Verbosity_ < verbosity) { this->Verbosity_ = static_cast<unsigned int>(verbosity); } @@ -59,19 +60,13 @@ void cmQtAutoGenerator::Logger::SetColorOutput(bool value) std::string cmQtAutoGenerator::Logger::HeadLine(std::string const& title) { - std::string head = title; - head += '\n'; - head.append(head.size() - 1, '-'); - head += '\n'; - return head; + return cmStrCat(title, "\n", std::string(title.size(), '-'), "\n"); } void cmQtAutoGenerator::Logger::Info(GenT genType, std::string const& message) const { - std::string msg = GeneratorName(genType); - msg += ": "; - msg += message; + std::string msg = cmStrCat(GeneratorName(genType), ": ", message); if (msg.back() != '\n') { msg.push_back('\n'); } @@ -109,19 +104,13 @@ void cmQtAutoGenerator::Logger::WarningFile(GenT genType, std::string const& filename, std::string const& message) const { - std::string msg = " "; - msg += Quoted(filename); - msg.push_back('\n'); - // Message - msg += message; - Warning(genType, msg); + Warning(genType, cmStrCat(" ", Quoted(filename), "\n", message)); } void cmQtAutoGenerator::Logger::Error(GenT genType, std::string const& message) const { - std::string msg; - msg += HeadLine(GeneratorName(genType) + " error"); + std::string msg = HeadLine(GeneratorName(genType) + " error"); // Message msg += message; if (msg.back() != '\n') { @@ -138,12 +127,7 @@ void cmQtAutoGenerator::Logger::ErrorFile(GenT genType, std::string const& filename, std::string const& message) const { - std::string emsg = " "; - emsg += Quoted(filename); - emsg += '\n'; - // Message - emsg += message; - Error(genType, emsg); + Error(genType, cmStrCat(" ", Quoted(filename), '\n', message)); } void cmQtAutoGenerator::Logger::ErrorCommand( @@ -279,10 +263,8 @@ bool cmQtAutoGenerator::Run(std::string const& infoFile, InfoFile_ = infoFile; cmSystemTools::ConvertToUnixSlashes(InfoFile_); if (!InfoFileTime_.Load(InfoFile_)) { - std::string msg = "AutoGen: The info file "; - msg += Quoted(InfoFile_); - msg += " is not readable\n"; - cmSystemTools::Stderr(msg); + cmSystemTools::Stderr(cmStrCat("AutoGen: The info file ", + Quoted(InfoFile_), " is not readable\n")); return false; } InfoDir_ = cmSystemTools::GetFilenamePath(infoFile); @@ -316,8 +298,7 @@ bool cmQtAutoGenerator::Run(std::string const& infoFile, std::string cmQtAutoGenerator::SettingsFind(std::string const& content, const char* key) { - std::string prefix(key); - prefix += ':'; + std::string prefix = cmStrCat(key, ':'); std::string::size_type pos = content.find(prefix); if (pos != std::string::npos) { pos += prefix.size(); diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index 889f47d..df190a1 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -5,16 +5,18 @@ #include <algorithm> #include <array> #include <list> -#include <memory> #include <set> #include <sstream> #include <utility> +#include "cm_memory.hxx" + #include "cmAlgorithms.h" #include "cmCryptoHash.h" #include "cmGeneratedFileStream.h" #include "cmMakefile.h" #include "cmQtAutoGen.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" #include "cmsys/FStream.hxx" @@ -300,10 +302,9 @@ void cmQtAutoMocUic::JobMocPredefsT::Process() } // Execute command if (!RunProcess(GenT::MOC, result, cmd, reason.get())) { - std::string msg = "The content generation command for "; - msg += Quoted(predefsFileRel); - msg += " failed.\n"; - msg += result.ErrorMessage; + std::string msg = + cmStrCat("The content generation command for ", + Quoted(predefsFileRel), " failed.\n", result.ErrorMessage); LogCommandError(GenT::MOC, msg, cmd, result.StdOut); return; } @@ -312,9 +313,8 @@ void cmQtAutoMocUic::JobMocPredefsT::Process() // (Re)write predefs file only on demand if (cmQtAutoGenerator::FileDiffers(predefsFileAbs, result.StdOut)) { if (!cmQtAutoGenerator::FileWrite(predefsFileAbs, result.StdOut)) { - std::string msg = "Writing "; - msg += Quoted(predefsFileRel); - msg += " failed."; + std::string msg = + cmStrCat("Writing ", Quoted(predefsFileRel), " failed."); LogFileError(GenT::MOC, predefsFileAbs, msg); return; } @@ -324,9 +324,8 @@ void cmQtAutoMocUic::JobMocPredefsT::Process() Log().Info(GenT::MOC, "Touching " + Quoted(predefsFileRel)); } if (!cmSystemTools::Touch(predefsFileAbs, false)) { - std::string msg = "Touching "; - msg += Quoted(predefsFileAbs); - msg += " failed."; + std::string msg = + cmStrCat("Touching ", Quoted(predefsFileAbs), " failed."); LogFileError(GenT::MOC, predefsFileAbs, msg); return; } @@ -345,9 +344,8 @@ bool cmQtAutoMocUic::JobMocPredefsT::Update(std::string* reason) const // Test if the file exists if (!MocEval().PredefsTime.Load(MocConst().PredefsFileAbs)) { if (reason != nullptr) { - *reason = "Generating "; - *reason += Quoted(MocConst().PredefsFileRel); - *reason += ", because it doesn't exist."; + *reason = cmStrCat("Generating ", Quoted(MocConst().PredefsFileRel), + ", because it doesn't exist."); } return true; } @@ -355,9 +353,8 @@ bool cmQtAutoMocUic::JobMocPredefsT::Update(std::string* reason) const // Test if the settings changed if (MocConst().SettingsChanged) { if (reason != nullptr) { - *reason = "Generating "; - *reason += Quoted(MocConst().PredefsFileRel); - *reason += ", because the moc settings changed."; + *reason = cmStrCat("Generating ", Quoted(MocConst().PredefsFileRel), + ", because the moc settings changed."); } return true; } @@ -369,11 +366,8 @@ bool cmQtAutoMocUic::JobMocPredefsT::Update(std::string* reason) const if (execTime.Load(exec)) { if (MocEval().PredefsTime.Older(execTime)) { if (reason != nullptr) { - *reason = "Generating "; - *reason += Quoted(MocConst().PredefsFileRel); - *reason += " because it is older than "; - *reason += Quoted(exec); - *reason += "."; + *reason = cmStrCat("Generating ", Quoted(MocConst().PredefsFileRel), + " because it is older than ", Quoted(exec), '.'); } return true; } @@ -661,13 +655,11 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource( if (!sourceIncludesDotMoc && !parseData.Macro.empty() && !(relaxedMode && sourceIncludesMocUnderscore)) { { - std::string emsg = "The file contains a "; - emsg += Quoted(parseData.Macro); - emsg += " macro, but does not include "; - emsg += Quoted(sourceBase + ".moc"); - emsg += "!\nConsider to\n - add #include \""; - emsg += sourceBase; - emsg += ".moc\"\n - enable SKIP_AUTOMOC for this file"; + std::string emsg = + cmStrCat("The file contains a ", Quoted(parseData.Macro), + " macro, but does not include ", Quoted(sourceBase + ".moc"), + "!\nConsider to\n - add #include \"", sourceBase, + ".moc\"\n - enable SKIP_AUTOMOC for this file"); LogFileError(GenT::MOC, sourceFile.FileName, emsg); } return false; @@ -679,11 +671,11 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource( SourceFileHandleT header = MocFindIncludedHeader(sourceDir, headerBase); if (!header) { { - std::string msg = "The file includes the moc file "; - msg += Quoted(incKey.Key); - msg += ",\nbut the header could not be found " - "in the following locations\n"; - msg += MocMessageTestHeaders(headerBase); + std::string msg = + cmStrCat("The file includes the moc file ", Quoted(incKey.Key), + ",\nbut the header could not be found " + "in the following locations\n", + MocMessageTestHeaders(headerBase)); LogFileError(GenT::MOC, sourceFile.FileName, msg); } return false; @@ -698,18 +690,14 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource( // used. This is for KDE4 compatibility. { // Issue a warning - std::string msg = "The file contains a "; - msg += Quoted(parseData.Macro); - msg += " macro, but does not include "; - msg += Quoted(sourceBase + ".moc"); - msg += ".\nInstead it includes "; - msg += Quoted(incKey.Key); - msg += ".\nRunning moc on the source\n "; - msg += Quoted(sourceFile.FileName); - msg += "!\nBetter include "; - msg += Quoted(sourceBase + ".moc"); - msg += " for compatibility with regular mode.\n"; - msg += "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"; + std::string msg = cmStrCat( + "The file contains a ", Quoted(parseData.Macro), + " macro, but does not include ", Quoted(sourceBase + ".moc"), + ".\nInstead it includes ", Quoted(incKey.Key), + ".\nRunning moc on the source\n ", Quoted(sourceFile.FileName), + "!\nBetter include ", Quoted(sourceBase + ".moc"), + " for compatibility with regular mode.\n", + "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"); Log().WarningFile(GenT::MOC, sourceFile.FileName, msg); } // Create mapping @@ -747,12 +735,12 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource( std::string const headerBase = incKey.Dir + incKey.Base; SourceFileHandleT header = MocFindIncludedHeader(sourceDir, headerBase); if (!header) { - std::string msg = "The file includes the moc file "; - msg += Quoted(incKey.Key); - msg += ",\nwhich seems to be the moc file from a different source " - "file.\nCMAKE_AUTOMOC_RELAXED_MODE: Also a matching header" - "could not be found in the following locations\n"; - msg += MocMessageTestHeaders(headerBase); + std::string msg = + cmStrCat("The file includes the moc file ", Quoted(incKey.Key), + ",\nwhich seems to be the moc file from a different source " + "file.\nCMAKE_AUTOMOC_RELAXED_MODE: Also a matching header" + "could not be found in the following locations\n", + MocMessageTestHeaders(headerBase)); LogFileError(GenT::MOC, sourceFile.FileName, msg); return false; } @@ -762,28 +750,22 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource( } // Issue a warning if (ownMoc && parseData.Macro.empty()) { - std::string msg = "The file includes the moc file "; - msg += Quoted(incKey.Key); - msg += ", but does not contain a\n"; - msg += MocConst().MacrosString(); - msg += " macro.\nRunning moc on the header\n "; - msg += Quoted(header->FileName); - msg += "!\nBetter include "; - msg += Quoted("moc_" + incKey.Base + ".cpp"); - msg += " for a compatibility with regular mode.\n"; - msg += "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"; + std::string msg = cmStrCat( + "The file includes the moc file ", Quoted(incKey.Key), + ", but does not contain a\n", MocConst().MacrosString(), + " macro.\nRunning moc on the header\n ", Quoted(header->FileName), + "!\nBetter include ", Quoted("moc_" + incKey.Base + ".cpp"), + " for a compatibility with regular mode.\n", + "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"); Log().WarningFile(GenT::MOC, sourceFile.FileName, msg); } else { - std::string msg = "The file includes the moc file "; - msg += Quoted(incKey.Key); - msg += " instead of "; - msg += Quoted("moc_" + incKey.Base + ".cpp"); - msg += ".\nRunning moc on the header\n "; - msg += Quoted(header->FileName); - msg += "!\nBetter include "; - msg += Quoted("moc_" + incKey.Base + ".cpp"); - msg += " for compatibility with regular mode.\n"; - msg += "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"; + std::string msg = cmStrCat( + "The file includes the moc file ", Quoted(incKey.Key), + " instead of ", Quoted("moc_" + incKey.Base + ".cpp"), + ".\nRunning moc on the header\n ", Quoted(header->FileName), + "!\nBetter include ", Quoted("moc_" + incKey.Base + ".cpp"), + " for compatibility with regular mode.\n", + "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"); Log().WarningFile(GenT::MOC, sourceFile.FileName, msg); } // Create mapping @@ -798,22 +780,19 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource( bool const ownMoc = (incKey.Base == sourceBase); if (!ownMoc) { // Don't allow <BASE>.moc include other than own in regular mode - std::string msg = "The file includes the moc file "; - msg += Quoted(incKey.Key); - msg += ",\nwhich seems to be the moc file from a different " - "source file.\nThis is not supported. Include "; - msg += Quoted(sourceBase + ".moc"); - msg += " to run moc on this source file."; + std::string msg = cmStrCat( + "The file includes the moc file ", Quoted(incKey.Key), + ",\nwhich seems to be the moc file from a different " + "source file.\nThis is not supported. Include ", + Quoted(sourceBase + ".moc"), " to run moc on this source file."); LogFileError(GenT::MOC, sourceFile.FileName, msg); return false; } // Accept but issue a warning if moc isn't required if (parseData.Macro.empty()) { - std::string msg = "The file includes the moc file "; - msg += Quoted(incKey.Key); - msg += ", but does not contain a "; - msg += MocConst().MacrosString(); - msg += " macro."; + std::string msg = cmStrCat( + "The file includes the moc file ", Quoted(incKey.Key), + ", but does not contain a ", MocConst().MacrosString(), " macro."); Log().WarningFile(GenT::MOC, sourceFile.FileName, msg); } // Create mapping @@ -839,9 +818,7 @@ cmQtAutoMocUic::JobEvaluateT::MocFindIncludedHeader( } // Search in include directories for (std::string const& path : MocConst().IncludePaths) { - std::string testPath = path; - testPath += '/'; - testPath += includeBase; + std::string testPath = cmStrCat(path, '/', includeBase); SourceFileHandleT res = MocFindHeader(testPath); if (res) { return res; @@ -891,10 +868,9 @@ std::string cmQtAutoMocUic::JobEvaluateT::MocMessageTestHeaders( { std::ostringstream res; { - std::string exts = ".{"; - exts += cmJoin(BaseConst().HeaderExtensions, ","); - exts += '}'; - // Compose result string + std::string exts = + cmStrCat(".{", cmJoin(BaseConst().HeaderExtensions, ","), + '}'); // Compose result string res << " " << fileBase << exts << '\n'; for (std::string const& path : MocConst().IncludePaths) { res << " " << path << '/' << fileBase << exts << '\n'; @@ -912,9 +888,8 @@ bool cmQtAutoMocUic::JobEvaluateT::MocRegisterIncluded( if (handle) { // Check if the output file would be generated from different source files if (handle->SourceFile != sourceFileHandle) { - std::string msg = "The source files\n "; - msg += Quoted(includerFileHandle->FileName); - msg += '\n'; + std::string msg = cmStrCat("The source files\n ", + Quoted(includerFileHandle->FileName), '\n'); for (auto const& item : handle->IncluderFiles) { msg += " "; msg += Quoted(item->FileName); @@ -1018,9 +993,8 @@ bool cmQtAutoMocUic::JobEvaluateT::UicRegisterMapping( MappingHandleT const& handle = it->second; if (handle->SourceFile != uiFileHandle) { // The output file already gets generated - from a different .ui file! - std::string msg = "The source files\n "; - msg += Quoted(includerFileHandle->FileName); - msg += '\n'; + std::string msg = cmStrCat("The source files\n ", + Quoted(includerFileHandle->FileName), '\n'); for (auto const& item : handle->IncluderFiles) { msg += " "; msg += Quoted(item->FileName); @@ -1061,8 +1035,7 @@ cmQtAutoMocUic::JobEvaluateT::UicFindIncludedUi( std::string const& sourceFile, std::string const& sourceDir, IncludeKeyT const& incKey) const { - std::string searchFileName = incKey.Base; - searchFileName += ".ui"; + std::string searchFileName = cmStrCat(incKey.Base, ".ui"); // Collect search paths list std::vector<std::string> testFiles; { @@ -1072,26 +1045,17 @@ cmQtAutoMocUic::JobEvaluateT::UicFindIncludedUi( // Vicinity of the source testFiles.emplace_back(sourceDir + searchFileName); if (!incKey.Dir.empty()) { - std::string path = sourceDir; - path += incKey.Dir; - path += searchFileName; - testFiles.emplace_back(path); + testFiles.emplace_back(cmStrCat(sourceDir, incKey.Dir, searchFileName)); } // AUTOUIC search paths if (!searchPaths.empty()) { for (std::string const& sPath : searchPaths) { - std::string path = sPath; - path += '/'; - path += searchFileName; - testFiles.emplace_back(std::move(path)); + testFiles.emplace_back(cmStrCat(sPath, '/', searchFileName)); } if (!incKey.Dir.empty()) { for (std::string const& sPath : searchPaths) { - std::string path = sPath; - path += '/'; - path += incKey.Dir; - path += searchFileName; - testFiles.emplace_back(std::move(path)); + testFiles.emplace_back( + cmStrCat(sPath, '/', incKey.Dir, searchFileName)); } } } @@ -1116,11 +1080,10 @@ cmQtAutoMocUic::JobEvaluateT::UicFindIncludedUi( // Log error { - std::string msg = "The file includes the uic file "; - msg += Quoted(incKey.Key); - msg += ",\nbut the user interface file "; - msg += Quoted(searchFileName); - msg += "\ncould not be found in the following locations\n"; + std::string msg = + cmStrCat("The file includes the uic file ", Quoted(incKey.Key), + ",\nbut the user interface file ", Quoted(searchFileName), + "\ncould not be found in the following locations\n"); for (std::string const& testFile : testFiles) { msg += " "; msg += Quoted(testFile); @@ -1203,10 +1166,9 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping, cmFileTime outputFileTime; if (!outputFileTime.Load(outputFile)) { if (reason != nullptr) { - *reason = "Generating "; - *reason += Quoted(outputFile); - *reason += ", because it doesn't exist, from "; - *reason += Quoted(sourceFile); + *reason = + cmStrCat("Generating ", Quoted(outputFile), + ", because it doesn't exist, from ", Quoted(sourceFile)); } return true; } @@ -1214,10 +1176,9 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping, // Test if any setting changed if (MocConst().SettingsChanged) { if (reason != nullptr) { - *reason = "Generating "; - *reason += Quoted(outputFile); - *reason += ", because the uic settings changed, from "; - *reason += Quoted(sourceFile); + *reason = cmStrCat("Generating ", Quoted(outputFile), + ", because the uic settings changed, from ", + Quoted(sourceFile)); } return true; } @@ -1225,10 +1186,9 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping, // Test if the source file is newer if (outputFileTime.Older(mapping.SourceFile->FileTime)) { if (reason != nullptr) { - *reason = "Generating "; - *reason += Quoted(outputFile); - *reason += ", because it's older than its source file, from "; - *reason += Quoted(sourceFile); + *reason = cmStrCat("Generating ", Quoted(outputFile), + ", because it's older than its source file, from ", + Quoted(sourceFile)); } return true; } @@ -1237,12 +1197,9 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping, if (!MocConst().PredefsFileAbs.empty()) { if (outputFileTime.Older(MocEval().PredefsTime)) { if (reason != nullptr) { - *reason = "Generating "; - *reason += Quoted(outputFile); - *reason += ", because it's older than "; - *reason += Quoted(MocConst().PredefsFileAbs); - *reason += ", from "; - *reason += Quoted(sourceFile); + *reason = cmStrCat( + "Generating ", Quoted(outputFile), ", because it's older than ", + Quoted(MocConst().PredefsFileAbs), ", from ", Quoted(sourceFile)); } return true; } @@ -1251,10 +1208,9 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping, // Test if the moc executable is newer if (outputFileTime.Older(MocConst().ExecutableTime)) { if (reason != nullptr) { - *reason = "Generating "; - *reason += Quoted(outputFile); - *reason += ", because it's older than the moc executable, from "; - *reason += Quoted(sourceFile); + *reason = cmStrCat("Generating ", Quoted(outputFile), + ", because it's older than the moc executable, from ", + Quoted(sourceFile)); } return true; } @@ -1274,12 +1230,10 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping, // Test if dependency file is older if (outputFileTime.Older(depMatch.second)) { if (reason != nullptr) { - *reason = "Generating "; - *reason += Quoted(outputFile); - *reason += ", because it's older than its dependency file "; - *reason += Quoted(depMatch.first); - *reason += ", from "; - *reason += Quoted(sourceFile); + *reason = + cmStrCat("Generating ", Quoted(outputFile), + ", because it's older than its dependency file ", + Quoted(depMatch.first), ", from ", Quoted(sourceFile)); } return true; } @@ -1344,10 +1298,9 @@ bool cmQtAutoMocUic::JobGenerateT::UicUpdate(MappingT const& mapping, cmFileTime outputFileTime; if (!outputFileTime.Load(outputFile)) { if (reason != nullptr) { - *reason = "Generating "; - *reason += Quoted(outputFile); - *reason += ", because it doesn't exist, from "; - *reason += Quoted(sourceFile); + *reason = + cmStrCat("Generating ", Quoted(outputFile), + ", because it doesn't exist, from ", Quoted(sourceFile)); } return true; } @@ -1355,10 +1308,9 @@ bool cmQtAutoMocUic::JobGenerateT::UicUpdate(MappingT const& mapping, // Test if the uic settings changed if (UicConst().SettingsChanged) { if (reason != nullptr) { - *reason = "Generating "; - *reason += Quoted(outputFile); - *reason += ", because the uic settings changed, from "; - *reason += Quoted(sourceFile); + *reason = cmStrCat("Generating ", Quoted(outputFile), + ", because the uic settings changed, from ", + Quoted(sourceFile)); } return true; } @@ -1366,10 +1318,9 @@ bool cmQtAutoMocUic::JobGenerateT::UicUpdate(MappingT const& mapping, // Test if the source file is newer if (outputFileTime.Older(mapping.SourceFile->FileTime)) { if (reason != nullptr) { - *reason = "Generating "; - *reason += Quoted(outputFile); - *reason += " because it's older than the source file "; - *reason += Quoted(sourceFile); + *reason = cmStrCat("Generating ", Quoted(outputFile), + " because it's older than the source file ", + Quoted(sourceFile)); } return true; } @@ -1377,10 +1328,9 @@ bool cmQtAutoMocUic::JobGenerateT::UicUpdate(MappingT const& mapping, // Test if the uic executable is newer if (outputFileTime.Older(UicConst().ExecutableTime)) { if (reason != nullptr) { - *reason = "Generating "; - *reason += Quoted(outputFile); - *reason += ", because it's older than the uic executable, from "; - *reason += Quoted(sourceFile); + *reason = cmStrCat("Generating ", Quoted(outputFile), + ", because it's older than the uic executable, from ", + Quoted(sourceFile)); } return true; } @@ -1416,10 +1366,9 @@ void cmQtAutoMocUic::JobMocT::Process() } } else { // Moc command failed - std::string msg = "The moc process failed to compile\n "; - msg += Quoted(sourceFile); - msg += "\ninto\n "; - msg += Quoted(outputFile); + std::string msg = + cmStrCat("The moc process failed to compile\n ", Quoted(sourceFile), + "\ninto\n ", Quoted(outputFile)); if (Mapping->IncluderFiles.empty()) { msg += ".\n"; } else { @@ -1465,11 +1414,9 @@ void cmQtAutoMocUic::JobUicT::Process() } } else { // Uic command failed - std::string msg = "The uic process failed to compile\n "; - msg += Quoted(sourceFile); - msg += "\ninto\n "; - msg += Quoted(outputFile); - msg += "\nincluded by\n"; + std::string msg = + cmStrCat("The uic process failed to compile\n ", Quoted(sourceFile), + "\ninto\n ", Quoted(outputFile), "\nincluded by\n"); for (auto const& item : Mapping->IncluderFiles) { msg += " "; msg += Quoted(item->FileName); @@ -1544,8 +1491,8 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) return makefile->IsOn(key); }; auto InfoGetList = [makefile](const char* key) -> std::vector<std::string> { - std::vector<std::string> list; - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list); + std::vector<std::string> list = + cmExpandedList(makefile->GetSafeDefinition(key)); return list; }; auto InfoGetLists = @@ -1562,12 +1509,7 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) if (length >= 2) { std::string::const_iterator itBeg = value.begin() + (pos + 1); std::string::const_iterator itEnd = itBeg + (length - 2); - { - std::string subValue(itBeg, itEnd); - std::vector<std::string> list; - cmSystemTools::ExpandListArgument(subValue, list); - lists.push_back(std::move(list)); - } + lists.emplace_back(cmExpandedList(std::string(itBeg, itEnd))); } pos += length; pos += ListSep.size(); @@ -1578,9 +1520,7 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) auto InfoGetConfig = [makefile, this](const char* key) -> std::string { const char* valueConf = nullptr; { - std::string keyConf = key; - keyConf += '_'; - keyConf += InfoConfig(); + std::string keyConf = cmStrCat(key, '_', InfoConfig()); valueConf = makefile->GetDefinition(keyConf); } if (valueConf == nullptr) { @@ -1590,8 +1530,7 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) }; auto InfoGetConfigList = [&InfoGetConfig](const char* key) -> std::vector<std::string> { - std::vector<std::string> list; - cmSystemTools::ExpandListArgument(InfoGetConfig(key), list); + std::vector<std::string> list = cmExpandedList(InfoGetConfig(key)); return list; }; auto LogInfoError = [this](std::string const& msg) -> bool { @@ -1622,7 +1561,7 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) BaseConst_.MultiConfig = InfoGetBool("AM_MULTI_CONFIG"); { unsigned long num = 1; - if (cmSystemTools::StringToULong(InfoGet("AM_PARALLEL").c_str(), &num)) { + if (cmStrToULong(InfoGet("AM_PARALLEL"), &num)) { num = std::max<unsigned long>(num, 1); num = std::min<unsigned long>(num, ParallelMax); } @@ -1651,9 +1590,9 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) return LogInfoError("CMake executable file name missing."); } if (!BaseConst_.CMakeExecutableTime.Load(BaseConst_.CMakeExecutable)) { - std::string error = "The CMake executable "; - error += Quoted(BaseConst_.CMakeExecutable); - error += " does not exist."; + std::string error = + cmStrCat("The CMake executable ", Quoted(BaseConst_.CMakeExecutable), + " does not exist."); return LogInfoError(error); } BaseConst_.ParseCacheFile = InfoGetConfig("AM_PARSE_CACHE_FILE"); @@ -1670,8 +1609,7 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) // - Qt environment { unsigned long qtv = BaseConst_.QtVersionMajor; - if (cmSystemTools::StringToULong(InfoGet("AM_QT_VERSION_MAJOR").c_str(), - &qtv)) { + if (cmStrToULong(InfoGet("AM_QT_VERSION_MAJOR"), &qtv)) { BaseConst_.QtVersionMajor = static_cast<unsigned int>(qtv); } } @@ -1682,9 +1620,9 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) MocConst_.Enabled = true; // Load the executable file time if (!MocConst_.ExecutableTime.Load(MocConst_.Executable)) { - std::string error = "The moc executable "; - error += Quoted(MocConst_.Executable); - error += " does not exist."; + std::string error = + cmStrCat("The moc executable ", Quoted(MocConst_.Executable), + " does not exist."); return LogInfoError(error); } for (std::string& sfl : InfoGetList("AM_MOC_SKIP")) { @@ -1750,9 +1688,9 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) UicConst_.Enabled = true; // Load the executable file time if (!UicConst_.ExecutableTime.Load(UicConst_.Executable)) { - std::string error = "The uic executable "; - error += Quoted(UicConst_.Executable); - error += " does not exist."; + std::string error = + cmStrCat("The uic executable ", Quoted(UicConst_.Executable), + " does not exist."); return LogInfoError(error); } for (std::string& sfl : InfoGetList("AM_UIC_SKIP")) { @@ -1804,7 +1742,8 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) // Headers { // Get file lists - const char *keyFiles = "AM_HEADERS", *keyFlags = "AM_HEADERS_FLAGS"; + const char* keyFiles = "AM_HEADERS"; + const char* keyFlags = "AM_HEADERS_FLAGS"; std::vector<std::string> files = InfoGetList(keyFiles); std::vector<std::string> flags = InfoGetList(keyFlags); std::vector<std::string> builds; @@ -1839,7 +1778,8 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) // Sources { - const char *keyFiles = "AM_SOURCES", *keyFlags = "AM_SOURCES_FLAGS"; + const char* keyFiles = "AM_SOURCES"; + const char* keyFlags = "AM_SOURCES_FLAGS"; std::vector<std::string> files = InfoGetList(keyFiles); std::vector<std::string> flags = InfoGetList(keyFlags); if (!MatchSizes(keyFiles, keyFlags, files.size(), flags.size())) { @@ -1892,7 +1832,7 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) std::list<std::string>::iterator it = includes.begin(); while (it != includes.end()) { std::string const& path = *it; - if (cmSystemTools::StringStartsWith(path, ppath->c_str())) { + if (cmHasPrefix(path, *ppath)) { MocConst_.IncludePaths.push_back(path); it = includes.erase(it); } else { diff --git a/Source/cmQtAutoMocUic.h b/Source/cmQtAutoMocUic.h index 8061c13..dc18328 100644 --- a/Source/cmQtAutoMocUic.h +++ b/Source/cmQtAutoMocUic.h @@ -14,7 +14,7 @@ #include <atomic> #include <cstddef> #include <map> -#include <memory> // IWYU pragma: keep +#include <memory> #include <set> #include <string> #include <unordered_map> diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx index 20885df..cc1a290 100644 --- a/Source/cmQtAutoRcc.cxx +++ b/Source/cmQtAutoRcc.cxx @@ -11,6 +11,7 @@ #include "cmFileLockResult.h" #include "cmMakefile.h" #include "cmProcessOutput.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" // -- Class methods @@ -27,17 +28,15 @@ bool cmQtAutoRcc::Init(cmMakefile* makefile) }; auto InfoGetList = [makefile](std::string const& key) -> std::vector<std::string> { - std::vector<std::string> list; - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list); + std::vector<std::string> list = + cmExpandedList(makefile->GetSafeDefinition(key)); return list; }; auto InfoGetConfig = [makefile, this](std::string const& key) -> std::string { const char* valueConf = nullptr; { - std::string keyConf = key; - keyConf += '_'; - keyConf += InfoConfig(); + std::string keyConf = cmStrCat(key, '_', InfoConfig()); valueConf = makefile->GetDefinition(keyConf); } if (valueConf == nullptr) { @@ -47,8 +46,7 @@ bool cmQtAutoRcc::Init(cmMakefile* makefile) }; auto InfoGetConfigList = [&InfoGetConfig](std::string const& key) -> std::vector<std::string> { - std::vector<std::string> list; - cmSystemTools::ExpandListArgument(InfoGetConfig(key), list); + std::vector<std::string> list = cmExpandedList(InfoGetConfig(key)); return list; }; auto LogInfoError = [this](std::string const& msg) -> bool { @@ -81,9 +79,8 @@ bool cmQtAutoRcc::Init(cmMakefile* makefile) // - Rcc executable RccExecutable_ = InfoGet("ARCC_RCC_EXECUTABLE"); if (!RccExecutableTime_.Load(RccExecutable_)) { - std::string error = "The rcc executable "; - error += Quoted(RccExecutable_); - error += " does not exist."; + std::string error = cmStrCat("The rcc executable ", Quoted(RccExecutable_), + " does not exist."); return LogInfoError(error); } RccListOptions_ = InfoGetList("ARCC_RCC_LIST_OPTIONS"); @@ -124,17 +121,12 @@ bool cmQtAutoRcc::Init(cmMakefile* makefile) // Init derived information // ------------------------ - RccFilePublic_ = AutogenBuildDir_; - RccFilePublic_ += '/'; - RccFilePublic_ += RccPathChecksum_; - RccFilePublic_ += '/'; - RccFilePublic_ += RccFileName_; + RccFilePublic_ = + cmStrCat(AutogenBuildDir_, '/', RccPathChecksum_, '/', RccFileName_); // Compute rcc output file name if (IsMultiConfig()) { - RccFileOutput_ = IncludeDir_; - RccFileOutput_ += '/'; - RccFileOutput_ += MultiConfigOutput(); + RccFileOutput_ = cmStrCat(IncludeDir_, '/', MultiConfigOutput()); } else { RccFileOutput_ = RccFilePublic_; } @@ -178,10 +170,8 @@ bool cmQtAutoRcc::Process() std::string cmQtAutoRcc::MultiConfigOutput() const { static std::string const suffix = "_CMAKE_"; - std::string res; - res += RccPathChecksum_; - res += '/'; - res += AppendFilenameSuffix(RccFileName_, suffix); + std::string res = cmStrCat(RccPathChecksum_, '/', + AppendFilenameSuffix(RccFileName_, suffix)); return res; } @@ -192,21 +182,10 @@ bool cmQtAutoRcc::SettingsFileRead() cmCryptoHash crypt(cmCryptoHash::AlgoSHA256); std::string const sep(" ~~~ "); { - std::string str; - str += RccExecutable_; - str += sep; - str += cmJoin(RccListOptions_, ";"); - str += sep; - str += QrcFile_; - str += sep; - str += RccPathChecksum_; - str += sep; - str += RccFileName_; - str += sep; - str += cmJoin(Options_, ";"); - str += sep; - str += cmJoin(Inputs_, ";"); - str += sep; + std::string str = + cmStrCat(RccExecutable_, sep, cmJoin(RccListOptions_, ";"), sep, + QrcFile_, sep, RccPathChecksum_, sep, RccFileName_, sep, + cmJoin(Options_, ";"), sep, cmJoin(Inputs_, ";"), sep); SettingsString_ = crypt.HashString(str); } } @@ -272,9 +251,7 @@ bool cmQtAutoRcc::SettingsFileWrite() Log().Info(GenT::RCC, "Writing settings file " + Quoted(SettingsFile_)); } // Write settings file - std::string content = "rcc:"; - content += SettingsString_; - content += '\n'; + std::string content = cmStrCat("rcc:", SettingsString_, '\n'); std::string error; if (!FileWrite(SettingsFile_, content, &error)) { Log().ErrorFile(GenT::RCC, SettingsFile_, @@ -296,9 +273,8 @@ bool cmQtAutoRcc::TestQrcRccFiles(bool& generate) // Test if the rcc input file exists if (!QrcFileTime_.Load(QrcFile_)) { std::string error; - error = "The resources file "; - error += Quoted(QrcFile_); - error += " does not exist"; + error = + cmStrCat("The resources file ", Quoted(QrcFile_), " does not exist"); Log().ErrorFile(GenT::RCC, QrcFile_, error); return false; } @@ -306,10 +282,8 @@ bool cmQtAutoRcc::TestQrcRccFiles(bool& generate) // Test if the rcc output file exists if (!RccFileTime_.Load(RccFileOutput_)) { if (Log().Verbose()) { - Reason = "Generating "; - Reason += Quoted(RccFileOutput_); - Reason += ", because it doesn't exist, from "; - Reason += Quoted(QrcFile_); + Reason = cmStrCat("Generating ", Quoted(RccFileOutput_), + ", because it doesn't exist, from ", Quoted(QrcFile_)); } generate = true; return true; @@ -318,10 +292,9 @@ bool cmQtAutoRcc::TestQrcRccFiles(bool& generate) // Test if the settings changed if (SettingsChanged_) { if (Log().Verbose()) { - Reason = "Generating "; - Reason += Quoted(RccFileOutput_); - Reason += ", because the rcc settings changed, from "; - Reason += Quoted(QrcFile_); + Reason = cmStrCat("Generating ", Quoted(RccFileOutput_), + ", because the rcc settings changed, from ", + Quoted(QrcFile_)); } generate = true; return true; @@ -330,12 +303,9 @@ bool cmQtAutoRcc::TestQrcRccFiles(bool& generate) // Test if the rcc output file is older than the .qrc file if (RccFileTime_.Older(QrcFileTime_)) { if (Log().Verbose()) { - Reason = "Generating "; - Reason += Quoted(RccFileOutput_); - Reason += ", because it is older than "; - Reason += Quoted(QrcFile_); - Reason += ", from "; - Reason += Quoted(QrcFile_); + Reason = cmStrCat("Generating ", Quoted(RccFileOutput_), + ", because it is older than ", Quoted(QrcFile_), + ", from ", Quoted(QrcFile_)); } generate = true; return true; @@ -344,10 +314,9 @@ bool cmQtAutoRcc::TestQrcRccFiles(bool& generate) // Test if the rcc output file is older than the rcc executable if (RccFileTime_.Older(RccExecutableTime_)) { if (Log().Verbose()) { - Reason = "Generating "; - Reason += Quoted(RccFileOutput_); - Reason += ", because it is older than the rcc executable, from "; - Reason += Quoted(QrcFile_); + Reason = cmStrCat("Generating ", Quoted(RccFileOutput_), + ", because it is older than the rcc executable, from ", + Quoted(QrcFile_)); } generate = true; return true; @@ -374,21 +343,17 @@ bool cmQtAutoRcc::TestResources(bool& generate) cmFileTime fileTime; if (!fileTime.Load(resFile)) { std::string error; - error = "Could not find the resource file\n "; - error += Quoted(resFile); - error += '\n'; + error = cmStrCat("Could not find the resource file\n ", Quoted(resFile), + '\n'); Log().ErrorFile(GenT::RCC, QrcFile_, error); return false; } // Check if the resource file is newer than the rcc output file if (RccFileTime_.Older(fileTime)) { if (Log().Verbose()) { - Reason = "Generating "; - Reason += Quoted(RccFileOutput_); - Reason += ", because it is older than "; - Reason += Quoted(resFile); - Reason += ", from "; - Reason += Quoted(QrcFile_); + Reason = cmStrCat("Generating ", Quoted(RccFileOutput_), + ", because it is older than ", Quoted(resFile), + ", from ", Quoted(QrcFile_)); } generate = true; break; @@ -402,10 +367,9 @@ bool cmQtAutoRcc::TestInfoFile() // Test if the rcc output file is older than the info file if (RccFileTime_.Older(InfoFileTime())) { if (Log().Verbose()) { - std::string reason = "Touching "; - reason += Quoted(RccFileOutput_); - reason += " because it is older than "; - reason += Quoted(InfoFile()); + std::string reason = + cmStrCat("Touching ", Quoted(RccFileOutput_), + " because it is older than ", Quoted(InfoFile())); Log().Info(GenT::RCC, reason); } // Touch build file @@ -456,10 +420,9 @@ bool cmQtAutoRcc::GenerateRcc() if (!result || (retVal != 0)) { // rcc process failed { - std::string err = "The rcc process failed to compile\n "; - err += Quoted(QrcFile_); - err += "\ninto\n "; - err += Quoted(RccFileOutput_); + std::string err = + cmStrCat("The rcc process failed to compile\n ", Quoted(QrcFile_), + "\ninto\n ", Quoted(RccFileOutput_)); Log().ErrorCommand(GenT::RCC, err, cmd, rccStdOut + rccStdErr); } cmSystemTools::RemoveFile(RccFileOutput_); @@ -481,12 +444,10 @@ bool cmQtAutoRcc::GenerateWrapper() // Generate a wrapper source file on demand if (IsMultiConfig()) { // Wrapper file content - std::string content; - content += "// This is an autogenerated configuration wrapper file.\n"; - content += "// Changes will be overwritten.\n"; - content += "#include <"; - content += MultiConfigOutput(); - content += ">\n"; + std::string content = + cmStrCat("// This is an autogenerated configuration wrapper file.\n", + "// Changes will be overwritten.\n", "#include <", + MultiConfigOutput(), ">\n"); // Compare with existing file content bool fileDiffers = true; diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx index 2064275..1f9aae8 100644 --- a/Source/cmRST.cxx +++ b/Source/cmRST.cxx @@ -4,6 +4,7 @@ #include "cmAlgorithms.h" #include "cmRange.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVersion.h" @@ -341,7 +342,7 @@ void cmRST::OutputMarkupLines(bool inlineMarkup) { for (auto line : this->MarkupLines) { if (!line.empty()) { - line = " " + line; + line = cmStrCat(" ", line); } this->OutputLine(line, inlineMarkup); } diff --git a/Source/cmRemoveCommand.cxx b/Source/cmRemoveCommand.cxx index a64ad8c..457b708 100644 --- a/Source/cmRemoveCommand.cxx +++ b/Source/cmRemoveCommand.cxx @@ -2,14 +2,13 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmRemoveCommand.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" -#include "cmSystemTools.h" - -class cmExecutionStatus; +#include "cmStringAlgorithms.h" // cmRemoveCommand -bool cmRemoveCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmRemoveCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { return true; @@ -17,7 +16,7 @@ bool cmRemoveCommand::InitialPass(std::vector<std::string> const& args, std::string const& variable = args[0]; // VAR is always first // get the old value - const char* cacheValue = this->Makefile->GetDefinition(variable); + const char* cacheValue = status.GetMakefile().GetDefinition(variable); // if there is no old value then return if (!cacheValue) { @@ -25,13 +24,12 @@ bool cmRemoveCommand::InitialPass(std::vector<std::string> const& args, } // expand the variable - std::vector<std::string> const varArgsExpanded = - cmSystemTools::ExpandedListArgument(cacheValue); + std::vector<std::string> const varArgsExpanded = cmExpandedList(cacheValue); // expand the args // check for REMOVE(VAR v1 v2 ... vn) std::vector<std::string> const argsExpanded = - cmSystemTools::ExpandedLists(args.begin() + 1, args.end()); + cmExpandedLists(args.begin() + 1, args.end()); // now create the new value std::string value; @@ -52,7 +50,7 @@ bool cmRemoveCommand::InitialPass(std::vector<std::string> const& args, } // add the definition - this->Makefile->AddDefinition(variable, value.c_str()); + status.GetMakefile().AddDefinition(variable, value); return true; } diff --git a/Source/cmRemoveCommand.h b/Source/cmRemoveCommand.h index 7b11849..fb72ab5 100644 --- a/Source/cmRemoveCommand.h +++ b/Source/cmRemoveCommand.h @@ -8,29 +8,14 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmRemoveCommand +/** * \brief remove command * * cmRemoveCommand implements the remove CMake command */ -class cmRemoveCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmRemoveCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmRemoveCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmRemoveDefinitionsCommand.h b/Source/cmRemoveDefinitionsCommand.h index a5cb204..85d01d4 100644 --- a/Source/cmRemoveDefinitionsCommand.h +++ b/Source/cmRemoveDefinitionsCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -25,7 +27,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmRemoveDefinitionsCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmRemoveDefinitionsCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmReturnCommand.cxx b/Source/cmReturnCommand.cxx index ceea8b4..5905669 100644 --- a/Source/cmReturnCommand.cxx +++ b/Source/cmReturnCommand.cxx @@ -5,8 +5,8 @@ #include "cmExecutionStatus.h" // cmReturnCommand -bool cmReturnCommand::InitialPass(std::vector<std::string> const&, - cmExecutionStatus& status) +bool cmReturnCommand(std::vector<std::string> const&, + cmExecutionStatus& status) { status.SetReturnInvoked(); return true; diff --git a/Source/cmReturnCommand.h b/Source/cmReturnCommand.h index ef39614..2404a36 100644 --- a/Source/cmReturnCommand.h +++ b/Source/cmReturnCommand.h @@ -8,29 +8,10 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmReturnCommand - * \brief Return from a directory or function - * - * cmReturnCommand returns from a directory or function - */ -class cmReturnCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmReturnCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +/// Return from a directory or function +bool cmReturnCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmRuntimeDependencyArchive.cxx b/Source/cmRuntimeDependencyArchive.cxx new file mode 100644 index 0000000..1b3f387 --- /dev/null +++ b/Source/cmRuntimeDependencyArchive.cxx @@ -0,0 +1,377 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmRuntimeDependencyArchive.h" + +#include "cmBinUtilsLinuxELFLinker.h" +#include "cmBinUtilsMacOSMachOLinker.h" +#include "cmBinUtilsWindowsPELinker.h" +#include "cmExecutionStatus.h" +#include "cmMakefile.h" +#include "cmStateTypes.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" + +#if defined(_WIN32) +# include "cmGlobalGenerator.h" +# ifndef CMAKE_BOOTSTRAP +# include "cmGlobalVisualStudioVersionedGenerator.h" +# endif +# include "cmVSSetupHelper.h" +# include "cmsys/Glob.hxx" +#endif + +#include <algorithm> +#include <sstream> +#include <string> +#include <utility> +#include <vector> + +#include "cm_memory.hxx" + +#if defined(_WIN32) +static void AddVisualStudioPath(std::vector<std::string>& paths, + const std::string& prefix, + unsigned int version, cmGlobalGenerator* gg) +{ + // If generating for the VS IDE, use the same instance. + std::string vsloc; + bool found = false; +# ifndef CMAKE_BOOTSTRAP + if (gg->GetName().find(prefix) == 0) { + cmGlobalVisualStudioVersionedGenerator* vsgen = + static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); + if (vsgen->GetVSInstance(vsloc)) { + found = true; + } + } +# endif + + // Otherwise, find a VS instance ourselves. + if (!found) { + cmVSSetupAPIHelper vsSetupAPIHelper(version); + if (vsSetupAPIHelper.GetVSInstanceInfo(vsloc)) { + cmSystemTools::ConvertToUnixSlashes(vsloc); + found = true; + } + } + + if (found) { + cmsys::Glob glob; + glob.SetListDirs(true); + glob.FindFiles(vsloc + "/VC/Tools/MSVC/*"); + for (auto const& vcdir : glob.GetFiles()) { + paths.push_back(vcdir + "/bin/Hostx64/x64"); + paths.push_back(vcdir + "/bin/Hostx86/x64"); + paths.push_back(vcdir + "/bin/Hostx64/x86"); + paths.push_back(vcdir + "/bin/Hostx86/x86"); + } + } +} + +static void AddRegistryPath(std::vector<std::string>& paths, + const std::string& path, cmMakefile* mf) +{ + // We should view the registry as the target application would view + // it. + cmSystemTools::KeyWOW64 view = cmSystemTools::KeyWOW64_32; + cmSystemTools::KeyWOW64 other_view = cmSystemTools::KeyWOW64_64; + if (mf->PlatformIs64Bit()) { + view = cmSystemTools::KeyWOW64_64; + other_view = cmSystemTools::KeyWOW64_32; + } + + // Expand using the view of the target application. + std::string expanded = path; + cmSystemTools::ExpandRegistryValues(expanded, view); + cmSystemTools::GlobDirs(expanded, paths); + + // Executables can be either 32-bit or 64-bit, so expand using the + // alternative view. + expanded = path; + cmSystemTools::ExpandRegistryValues(expanded, other_view); + cmSystemTools::GlobDirs(expanded, paths); +} + +static void AddEnvPath(std::vector<std::string>& paths, const std::string& var, + const std::string& suffix) +{ + std::string value; + if (cmSystemTools::GetEnv(var, value)) { + paths.push_back(value + suffix); + } +} +#endif + +static cmsys::RegularExpression TransformCompile(const std::string& str) +{ + return cmsys::RegularExpression(str); +} + +cmRuntimeDependencyArchive::cmRuntimeDependencyArchive( + cmExecutionStatus& status, std::vector<std::string> searchDirectories, + std::string bundleExecutable, + const std::vector<std::string>& preIncludeRegexes, + const std::vector<std::string>& preExcludeRegexes, + const std::vector<std::string>& postIncludeRegexes, + const std::vector<std::string>& postExcludeRegexes) + : Status(status) + , SearchDirectories(std::move(searchDirectories)) + , BundleExecutable(std::move(bundleExecutable)) + , PreIncludeRegexes(preIncludeRegexes.size()) + , PreExcludeRegexes(preExcludeRegexes.size()) + , PostIncludeRegexes(postIncludeRegexes.size()) + , PostExcludeRegexes(postExcludeRegexes.size()) +{ + std::transform(preIncludeRegexes.begin(), preIncludeRegexes.end(), + this->PreIncludeRegexes.begin(), TransformCompile); + std::transform(preExcludeRegexes.begin(), preExcludeRegexes.end(), + this->PreExcludeRegexes.begin(), TransformCompile); + std::transform(postIncludeRegexes.begin(), postIncludeRegexes.end(), + this->PostIncludeRegexes.begin(), TransformCompile); + std::transform(postExcludeRegexes.begin(), postExcludeRegexes.end(), + this->PostExcludeRegexes.begin(), TransformCompile); +} + +bool cmRuntimeDependencyArchive::Prepare() +{ + std::string platform = this->GetMakefile()->GetSafeDefinition( + "CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM"); + if (platform.empty()) { + std::string systemName = + this->GetMakefile()->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME"); + if (systemName == "Windows") { + platform = "windows+pe"; + } else if (systemName == "Darwin") { + platform = "macos+macho"; + } else if (systemName == "Linux") { + platform = "linux+elf"; + } + } + if (platform == "linux+elf") { + this->Linker = cm::make_unique<cmBinUtilsLinuxELFLinker>(this); + } else if (platform == "windows+pe") { + this->Linker = cm::make_unique<cmBinUtilsWindowsPELinker>(this); + } else if (platform == "macos+macho") { + this->Linker = cm::make_unique<cmBinUtilsMacOSMachOLinker>(this); + } else { + std::ostringstream e; + e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM: " + << platform; + this->SetError(e.str()); + return false; + } + + return this->Linker->Prepare(); +} + +bool cmRuntimeDependencyArchive::GetRuntimeDependencies( + const std::vector<std::string>& executables, + const std::vector<std::string>& libraries, + const std::vector<std::string>& modules) +{ + for (auto const& exe : executables) { + if (!this->Linker->ScanDependencies(exe, cmStateEnums::EXECUTABLE)) { + return false; + } + } + for (auto const& lib : libraries) { + if (!this->Linker->ScanDependencies(lib, cmStateEnums::SHARED_LIBRARY)) { + return false; + } + } + for (auto const& mod : modules) { + if (!this->Linker->ScanDependencies(mod, cmStateEnums::MODULE_LIBRARY)) { + return false; + } + } + + return true; +} + +void cmRuntimeDependencyArchive::SetError(const std::string& e) +{ + this->Status.SetError(e); +} + +std::string cmRuntimeDependencyArchive::GetBundleExecutable() +{ + return this->BundleExecutable; +} + +const std::vector<std::string>& +cmRuntimeDependencyArchive::GetSearchDirectories() +{ + return this->SearchDirectories; +} + +std::string cmRuntimeDependencyArchive::GetGetRuntimeDependenciesTool() +{ + return this->GetMakefile()->GetSafeDefinition( + "CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL"); +} + +bool cmRuntimeDependencyArchive::GetGetRuntimeDependenciesCommand( + const std::string& search, std::vector<std::string>& command) +{ + // First see if it was supplied by the user + std::string toolCommand = this->GetMakefile()->GetSafeDefinition( + "CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND"); + if (!toolCommand.empty()) { + cmExpandList(toolCommand, command); + return true; + } + + // Now go searching for it + std::vector<std::string> paths; +#ifdef _WIN32 + cmGlobalGenerator* gg = this->GetMakefile()->GetGlobalGenerator(); + + // Add newer Visual Studio paths + AddVisualStudioPath(paths, "Visual Studio 16 ", 16, gg); + AddVisualStudioPath(paths, "Visual Studio 15 ", 15, gg); + + // Add older Visual Studio paths + AddRegistryPath( + paths, + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\14.0;InstallDir]/" + "../../VC/bin", + this->GetMakefile()); + AddEnvPath(paths, "VS140COMNTOOLS", "/../../VC/bin"); + paths.push_back( + "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin"); + AddRegistryPath( + paths, + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\12.0;InstallDir]/" + "../../VC/bin", + this->GetMakefile()); + AddEnvPath(paths, "VS120COMNTOOLS", "/../../VC/bin"); + paths.push_back( + "C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/bin"); + AddRegistryPath( + paths, + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\11.0;InstallDir]/" + "../../VC/bin", + this->GetMakefile()); + AddEnvPath(paths, "VS110COMNTOOLS", "/../../VC/bin"); + paths.push_back( + "C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/bin"); + AddRegistryPath( + paths, + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\10.0;InstallDir]/" + "../../VC/bin", + this->GetMakefile()); + AddEnvPath(paths, "VS100COMNTOOLS", "/../../VC/bin"); + paths.push_back( + "C:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/bin"); + AddRegistryPath( + paths, + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\9.0;InstallDir]/" + "../../VC/bin", + this->GetMakefile()); + AddEnvPath(paths, "VS90COMNTOOLS", "/../../VC/bin"); + paths.push_back("C:/Program Files/Microsoft Visual Studio 9.0/VC/bin"); + paths.push_back("C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin"); + AddRegistryPath( + paths, + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0;InstallDir]/" + "../../VC/bin", + this->GetMakefile()); + AddEnvPath(paths, "VS80COMNTOOLS", "/../../VC/bin"); + paths.push_back("C:/Program Files/Microsoft Visual Studio 8/VC/BIN"); + paths.push_back("C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN"); + AddRegistryPath( + paths, + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\7.1;InstallDir]/" + "../../VC7/bin", + this->GetMakefile()); + AddEnvPath(paths, "VS71COMNTOOLS", "/../../VC7/bin"); + paths.push_back( + "C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN"); + paths.push_back( + "C:/Program Files (x86)/Microsoft Visual Studio .NET 2003/VC7/BIN"); +#endif + + std::string program = cmSystemTools::FindProgram(search, paths); + if (!program.empty()) { + command = { program }; + return true; + } + + // Couldn't find it + return false; +} + +bool cmRuntimeDependencyArchive::IsPreExcluded(const std::string& name) +{ + cmsys::RegularExpressionMatch match; + + for (auto const& regex : this->PreIncludeRegexes) { + if (regex.find(name.c_str(), match)) { + return false; + } + } + + for (auto const& regex : this->PreExcludeRegexes) { + if (regex.find(name.c_str(), match)) { + return true; + } + } + + return false; +} + +bool cmRuntimeDependencyArchive::IsPostExcluded(const std::string& name) +{ + cmsys::RegularExpressionMatch match; + + for (auto const& regex : this->PostIncludeRegexes) { + if (regex.find(name.c_str(), match)) { + return false; + } + } + + for (auto const& regex : this->PostExcludeRegexes) { + if (regex.find(name.c_str(), match)) { + return true; + } + } + + return false; +} + +void cmRuntimeDependencyArchive::AddResolvedPath(const std::string& name, + const std::string& path, + bool& unique) +{ + auto it = this->ResolvedPaths.emplace(name, std::set<std::string>{}).first; + unique = true; + for (auto const& other : it->second) { + if (cmSystemTools::SameFile(path, other)) { + unique = false; + break; + } + } + it->second.insert(path); +} + +void cmRuntimeDependencyArchive::AddUnresolvedPath(const std::string& name) +{ + this->UnresolvedPaths.insert(name); +} + +cmMakefile* cmRuntimeDependencyArchive::GetMakefile() +{ + return &this->Status.GetMakefile(); +} + +const std::map<std::string, std::set<std::string>>& +cmRuntimeDependencyArchive::GetResolvedPaths() +{ + return this->ResolvedPaths; +} + +const std::set<std::string>& cmRuntimeDependencyArchive::GetUnresolvedPaths() +{ + return this->UnresolvedPaths; +} diff --git a/Source/cmRuntimeDependencyArchive.h b/Source/cmRuntimeDependencyArchive.h new file mode 100644 index 0000000..e063121 --- /dev/null +++ b/Source/cmRuntimeDependencyArchive.h @@ -0,0 +1,70 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#ifndef cmRuntimeDependencyArchive_h +#define cmRuntimeDependencyArchive_h + +#include "cmBinUtilsLinker.h" + +#include "cmsys/RegularExpression.hxx" + +#include <map> +#include <memory> +#include <set> +#include <string> +#include <vector> + +class cmExecutionStatus; +class cmMakefile; + +class cmRuntimeDependencyArchive +{ +public: + explicit cmRuntimeDependencyArchive( + cmExecutionStatus& status, std::vector<std::string> searchDirectories, + std::string bundleExecutable, + const std::vector<std::string>& preIncludeRegexes, + const std::vector<std::string>& preExcludeRegexes, + const std::vector<std::string>& postIncludeRegexes, + const std::vector<std::string>& postExcludeRegexes); + bool Prepare(); + bool GetRuntimeDependencies(const std::vector<std::string>& executables, + const std::vector<std::string>& libraries, + const std::vector<std::string>& modules); + + void SetError(const std::string& e); + + std::string GetBundleExecutable(); + const std::vector<std::string>& GetSearchDirectories(); + std::string GetGetRuntimeDependenciesTool(); + bool GetGetRuntimeDependenciesCommand(const std::string& search, + std::vector<std::string>& command); + bool IsPreExcluded(const std::string& name); + bool IsPostExcluded(const std::string& name); + + void AddResolvedPath(const std::string& name, const std::string& path, + bool& unique); + void AddUnresolvedPath(const std::string& name); + + cmMakefile* GetMakefile(); + const std::map<std::string, std::set<std::string>>& GetResolvedPaths(); + const std::set<std::string>& GetUnresolvedPaths(); + +private: + cmExecutionStatus& Status; + std::unique_ptr<cmBinUtilsLinker> Linker; + + std::string GetRuntimeDependenciesTool; + std::vector<std::string> GetRuntimeDependenciesCommand; + + std::vector<std::string> SearchDirectories; + std::string BundleExecutable; + std::vector<cmsys::RegularExpression> PreIncludeRegexes; + std::vector<cmsys::RegularExpression> PreExcludeRegexes; + std::vector<cmsys::RegularExpression> PostIncludeRegexes; + std::vector<cmsys::RegularExpression> PostExcludeRegexes; + std::map<std::string, std::set<std::string>> ResolvedPaths; + std::set<std::string> UnresolvedPaths; +}; + +#endif // cmRuntimeDependencyArchive_h diff --git a/Source/cmScriptGenerator.cxx b/Source/cmScriptGenerator.cxx index 9182b41..1438f07 100644 --- a/Source/cmScriptGenerator.cxx +++ b/Source/cmScriptGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmScriptGenerator.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include <utility> @@ -51,9 +52,8 @@ static void cmScriptGeneratorEncodeConfig(const std::string& config, std::string cmScriptGenerator::CreateConfigTest(const std::string& config) { - std::string result = "\"${"; - result += this->RuntimeConfigVariable; - result += "}\" MATCHES \"^("; + std::string result = + cmStrCat("\"${", this->RuntimeConfigVariable, "}\" MATCHES \"^("); if (!config.empty()) { cmScriptGeneratorEncodeConfig(config, result); } @@ -64,9 +64,8 @@ std::string cmScriptGenerator::CreateConfigTest(const std::string& config) std::string cmScriptGenerator::CreateConfigTest( std::vector<std::string> const& configs) { - std::string result = "\"${"; - result += this->RuntimeConfigVariable; - result += "}\" MATCHES \"^("; + std::string result = + cmStrCat("\"${", this->RuntimeConfigVariable, "}\" MATCHES \"^("); const char* sep = ""; for (std::string const& config : configs) { result += sep; diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx index f98984e..d15ce57 100644 --- a/Source/cmSearchPath.cxx +++ b/Source/cmSearchPath.cxx @@ -6,9 +6,9 @@ #include <cassert> #include <utility> -#include "cmAlgorithms.h" #include "cmFindCommon.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmSearchPath::cmSearchPath(cmFindCommon* findCmd) @@ -78,8 +78,7 @@ void cmSearchPath::AddCMakePath(const std::string& variable) // Get a path from a CMake variable. if (const char* value = this->FC->Makefile->GetDefinition(variable)) { - std::vector<std::string> expanded; - cmSystemTools::ExpandListArgument(value, expanded); + std::vector<std::string> expanded = cmExpandedList(value); for (std::string const& p : expanded) { this->AddPathInternal( @@ -103,8 +102,7 @@ void cmSearchPath::AddCMakePrefixPath(const std::string& variable) // Get a path from a CMake variable. if (const char* value = this->FC->Makefile->GetDefinition(variable)) { - std::vector<std::string> expanded; - cmSystemTools::ExpandListArgument(value, expanded); + std::vector<std::string> expanded = cmExpandedList(value); this->AddPrefixPaths( expanded, this->FC->Makefile->GetCurrentSourceDirectory().c_str()); diff --git a/Source/cmSeparateArgumentsCommand.cxx b/Source/cmSeparateArgumentsCommand.cxx index 28cbdc0..27f45a8 100644 --- a/Source/cmSeparateArgumentsCommand.cxx +++ b/Source/cmSeparateArgumentsCommand.cxx @@ -5,17 +5,16 @@ #include <algorithm> #include <sstream> +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmSystemTools.h" -class cmExecutionStatus; - // cmSeparateArgumentsCommand -bool cmSeparateArgumentsCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmSeparateArgumentsCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("must be given at least one argument."); + status.SetError("must be given at least one argument."); return false; } @@ -59,17 +58,17 @@ bool cmSeparateArgumentsCommand::InitialPass( } else { std::ostringstream e; e << "given unknown argument " << arg; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } if (mode == ModeOld) { // Original space-replacement version of command. - if (const char* def = this->Makefile->GetDefinition(var)) { + if (const char* def = status.GetMakefile().GetDefinition(var)) { std::string value = def; std::replace(value.begin(), value.end(), ' ', ';'); - this->Makefile->AddDefinition(var, value.c_str()); + status.GetMakefile().AddDefinition(var, value); } } else { // Parse the command line. @@ -97,7 +96,7 @@ bool cmSeparateArgumentsCommand::InitialPass( value += si; } } - this->Makefile->AddDefinition(var, value.c_str()); + status.GetMakefile().AddDefinition(var, value); } return true; diff --git a/Source/cmSeparateArgumentsCommand.h b/Source/cmSeparateArgumentsCommand.h index 988ad23..e000c51 100644 --- a/Source/cmSeparateArgumentsCommand.h +++ b/Source/cmSeparateArgumentsCommand.h @@ -8,29 +8,14 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmSeparateArgumentsCommand +/** * \brief separate_arguments command * * cmSeparateArgumentsCommand implements the separate_arguments CMake command */ -class cmSeparateArgumentsCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmSeparateArgumentsCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmSeparateArgumentsCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx index 1903fd9..9df1883 100644 --- a/Source/cmServer.cxx +++ b/Source/cmServer.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmServer.h" -#include "cmAlgorithms.h" #include "cmConnection.h" #include "cmFileMonitor.h" #include "cmJsonObjectDictionary.h" @@ -18,10 +17,11 @@ #include <cassert> #include <cstdint> #include <iostream> -#include <memory> #include <mutex> #include <utility> +#include "cm_memory.hxx" + void on_signal(uv_signal_t* signal, int signum) { auto conn = static_cast<cmServerBase*>(signal->data); diff --git a/Source/cmServer.h b/Source/cmServer.h index aba4924..ab2ad23 100644 --- a/Source/cmServer.h +++ b/Source/cmServer.h @@ -10,7 +10,7 @@ #include "cmUVHandlePtr.h" -#include <memory> // IWYU pragma: keep +#include <memory> #include <string> #include <vector> diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index 558391f..670161d 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -19,11 +19,12 @@ #include <algorithm> #include <cassert> #include <functional> -#include <memory> #include <string> #include <utility> #include <vector> +#include "cm_memory.hxx" + // Get rid of some windows macros: #undef max @@ -378,8 +379,7 @@ void cmServerProtocol1::HandleCMakeFileChanges(const std::string& path, SendSignal(kFILE_CHANGE_SIGNAL, obj); } -const cmServerResponse cmServerProtocol1::Process( - const cmServerRequest& request) +cmServerResponse cmServerProtocol1::Process(const cmServerRequest& request) { assert(this->m_State >= STATE_ACTIVE); @@ -434,7 +434,7 @@ cmServerResponse cmServerProtocol1::ProcessCache( keys = allKeys; } else { for (auto const& i : keys) { - if (std::find(allKeys.begin(), allKeys.end(), i) == allKeys.end()) { + if (!cmContains(allKeys, i)) { return request.ReportError("Key \"" + i + "\" not found in cache."); } } diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h index 2f55a20..5da4344 100644 --- a/Source/cmServerProtocol.h +++ b/Source/cmServerProtocol.h @@ -80,7 +80,7 @@ public: virtual std::pair<int, int> ProtocolVersion() const = 0; virtual bool IsExperimental() const = 0; - virtual const cmServerResponse Process(const cmServerRequest& request) = 0; + virtual cmServerResponse Process(const cmServerRequest& request) = 0; bool Activate(cmServer* server, const cmServerRequest& request, std::string* errorMessage); @@ -106,7 +106,7 @@ class cmServerProtocol1 : public cmServerProtocol public: std::pair<int, int> ProtocolVersion() const override; bool IsExperimental() const override; - const cmServerResponse Process(const cmServerRequest& request) override; + cmServerResponse Process(const cmServerRequest& request) override; private: bool DoActivate(const cmServerRequest& request, diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx index 41555e8..8c3a4cb 100644 --- a/Source/cmSetCommand.cxx +++ b/Source/cmSetCommand.cxx @@ -2,22 +2,21 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSetCommand.h" -#include "cmAlgorithms.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmRange.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmExecutionStatus; - // cmSetCommand -bool cmSetCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmSetCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } @@ -45,7 +44,7 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args, std::string m = "Only the first value argument is used when setting " "an environment variable. Argument '" + args[2] + "' and later are unused."; - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, m); + status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, m); } return true; } @@ -59,13 +58,13 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args, // SET (VAR) // Removes the definition of VAR. if (args.size() == 1) { - this->Makefile->RemoveDefinition(variable); + status.GetMakefile().RemoveDefinition(variable); return true; } // SET (VAR PARENT_SCOPE) // Removes the definition of VAR // in the parent scope. if (args.size() == 2 && args.back() == "PARENT_SCOPE") { - this->Makefile->RaiseScope(variable, nullptr); + status.GetMakefile().RaiseScope(variable, nullptr); return true; } @@ -106,7 +105,7 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args, value = cmJoin(cmMakeRange(args).advance(1).retreat(ignoreLastArgs), ";"); if (parentScope) { - this->Makefile->RaiseScope(variable, value.c_str()); + status.GetMakefile().RaiseScope(variable, value.c_str()); return true; } @@ -116,7 +115,7 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args, if ((args.back() == "CACHE") || (args.size() > 1 && args[args.size() - 2] == "CACHE") || (force && !cache)) { - this->SetError("given invalid arguments for CACHE mode."); + status.SetError("given invalid arguments for CACHE mode."); return false; } @@ -125,7 +124,7 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args, if (!cmState::StringToCacheEntryType(args[cacheStart + 1].c_str(), type)) { std::string m = "implicitly converting '" + args[cacheStart + 1] + "' to 'STRING' type."; - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, m); + status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, m); // Setting this may not be required, since it's // initialized as a string. Keeping this here to // ensure that the type is actually converting to a string. @@ -135,7 +134,7 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args, } // see if this is already in the cache - cmState* state = this->Makefile->GetState(); + cmState* state = status.GetMakefile().GetState(); const char* existingValue = state->GetCacheEntryValue(variable); if (existingValue && (state->GetCacheEntryType(variable) != cmStateEnums::UNINITIALIZED)) { @@ -150,11 +149,11 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args, // if it is meant to be in the cache then define it in the cache if (cache) { - this->Makefile->AddCacheDefinition(variable, value.c_str(), docstring, - type, force); + status.GetMakefile().AddCacheDefinition(variable, value.c_str(), docstring, + type, force); } else { // add the definition - this->Makefile->AddDefinition(variable, value.c_str()); + status.GetMakefile().AddDefinition(variable, value); } return true; } diff --git a/Source/cmSetCommand.h b/Source/cmSetCommand.h index 76e3eae..0973d33 100644 --- a/Source/cmSetCommand.h +++ b/Source/cmSetCommand.h @@ -8,29 +8,14 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmSetCommand +/** * \brief Set a CMAKE variable * * cmSetCommand sets a variable to a value with expansion. */ -class cmSetCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmSetCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmSetCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmSetDirectoryPropertiesCommand.cxx b/Source/cmSetDirectoryPropertiesCommand.cxx index 8d3961a..35daca6 100644 --- a/Source/cmSetDirectoryPropertiesCommand.cxx +++ b/Source/cmSetDirectoryPropertiesCommand.cxx @@ -2,31 +2,37 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSetDirectoryPropertiesCommand.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" -class cmExecutionStatus; +namespace { +bool RunCommand(cmMakefile& mf, std::vector<std::string>::const_iterator ait, + std::vector<std::string>::const_iterator aitend, + std::string& errors); +} // cmSetDirectoryPropertiesCommand -bool cmSetDirectoryPropertiesCommand::InitialPass( - std::vector<std::string> const& args, cmExecutionStatus&) +bool cmSetDirectoryPropertiesCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } std::string errors; - bool ret = cmSetDirectoryPropertiesCommand::RunCommand( - this->Makefile, args.begin() + 1, args.end(), errors); + bool ret = + RunCommand(status.GetMakefile(), args.begin() + 1, args.end(), errors); if (!ret) { - this->SetError(errors); + status.SetError(errors); } return ret; } -bool cmSetDirectoryPropertiesCommand::RunCommand( - cmMakefile* mf, std::vector<std::string>::const_iterator ait, - std::vector<std::string>::const_iterator aitend, std::string& errors) +namespace { +bool RunCommand(cmMakefile& mf, std::vector<std::string>::const_iterator ait, + std::vector<std::string>::const_iterator aitend, + std::string& errors) { for (; ait != aitend; ait += 2) { if (ait + 1 == aitend) { @@ -43,8 +49,9 @@ bool cmSetDirectoryPropertiesCommand::RunCommand( errors = "Commands and macros cannot be set using SET_CMAKE_PROPERTIES"; return false; } - mf->SetProperty(prop, value.c_str()); + mf.SetProperty(prop, value.c_str()); } return true; } +} diff --git a/Source/cmSetDirectoryPropertiesCommand.h b/Source/cmSetDirectoryPropertiesCommand.h index 473347c..c243dd7 100644 --- a/Source/cmSetDirectoryPropertiesCommand.h +++ b/Source/cmSetDirectoryPropertiesCommand.h @@ -8,30 +8,9 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -class cmMakefile; - -class cmSetDirectoryPropertiesCommand : public cmCommand -{ -public: - cmCommand* Clone() override { return new cmSetDirectoryPropertiesCommand; } - - /** - * This is called when the command is first encountered in - * the input file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - /** - * Static entry point for use by other commands - */ - static bool RunCommand(cmMakefile* mf, - std::vector<std::string>::const_iterator ait, - std::vector<std::string>::const_iterator aitend, - std::string& errors); -}; +bool cmSetDirectoryPropertiesCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx index e9343c7..7e3a340 100644 --- a/Source/cmSetPropertyCommand.cxx +++ b/Source/cmSetPropertyCommand.cxx @@ -2,8 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSetPropertyCommand.h" +#include <set> #include <sstream> +#include "cmExecutionStatus.h" #include "cmGlobalGenerator.h" #include "cmInstalledFile.h" #include "cmMakefile.h" @@ -11,25 +13,72 @@ #include "cmRange.h" #include "cmSourceFile.h" #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTest.h" #include "cmake.h" -class cmExecutionStatus; - -cmSetPropertyCommand::cmSetPropertyCommand() -{ - this->AppendMode = false; - this->AppendAsString = false; - this->Remove = true; +namespace { +bool HandleGlobalMode(cmExecutionStatus& status, + const std::set<std::string>& names, + const std::string& propertyName, + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove); +bool HandleDirectoryMode(cmExecutionStatus& status, + const std::set<std::string>& names, + const std::string& propertyName, + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove); +bool HandleTargetMode(cmExecutionStatus& status, + const std::set<std::string>& names, + const std::string& propertyName, + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove); +bool HandleTarget(cmTarget* target, cmMakefile& makefile, + const std::string& propertyName, + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove); +bool HandleSourceMode(cmExecutionStatus& status, + const std::set<std::string>& names, + const std::string& propertyName, + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove); +bool HandleSource(cmSourceFile* sf, const std::string& propertyName, + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove); +bool HandleTestMode(cmExecutionStatus& status, std::set<std::string>& names, + const std::string& propertyName, + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove); +bool HandleTest(cmTest* test, const std::string& propertyName, + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove); +bool HandleCacheMode(cmExecutionStatus& status, + const std::set<std::string>& names, + const std::string& propertyName, + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove); +bool HandleCacheEntry(std::string const& cacheKey, const cmMakefile& makefile, + const std::string& propertyName, + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove); +bool HandleInstallMode(cmExecutionStatus& status, + const std::set<std::string>& names, + const std::string& propertyName, + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove); +bool HandleInstall(cmInstalledFile* file, cmMakefile& makefile, + const std::string& propertyName, + const std::string& propertyValue, bool appendAsString, + bool appendMode, bool remove); } -bool cmSetPropertyCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmSetPropertyCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 2) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } @@ -55,10 +104,17 @@ bool cmSetPropertyCommand::InitialPass(std::vector<std::string> const& args, e << "given invalid scope " << scopeName << ". " << "Valid scopes are GLOBAL, DIRECTORY, " "TARGET, SOURCE, TEST, CACHE, INSTALL."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } + bool appendAsString = false; + bool appendMode = false; + bool remove = true; + std::set<std::string> names; + std::string propertyName; + std::string propertyValue; + // Parse the rest of the arguments up to the values. enum Doing { @@ -74,54 +130,61 @@ bool cmSetPropertyCommand::InitialPass(std::vector<std::string> const& args, doing = DoingProperty; } else if (arg == "APPEND") { doing = DoingNone; - this->AppendMode = true; - this->Remove = false; - this->AppendAsString = false; + appendMode = true; + remove = false; + appendAsString = false; } else if (arg == "APPEND_STRING") { doing = DoingNone; - this->AppendMode = true; - this->Remove = false; - this->AppendAsString = true; + appendMode = true; + remove = false; + appendAsString = true; } else if (doing == DoingNames) { - this->Names.insert(arg); + names.insert(arg); } else if (doing == DoingProperty) { - this->PropertyName = arg; + propertyName = arg; doing = DoingValues; } else if (doing == DoingValues) { - this->PropertyValue += sep; + propertyValue += sep; sep = ";"; - this->PropertyValue += arg; - this->Remove = false; + propertyValue += arg; + remove = false; } else { std::ostringstream e; e << "given invalid argument \"" << arg << "\"."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } // Make sure a property name was found. - if (this->PropertyName.empty()) { - this->SetError("not given a PROPERTY <name> argument."); + if (propertyName.empty()) { + status.SetError("not given a PROPERTY <name> argument."); return false; } // Dispatch property setting. switch (scope) { case cmProperty::GLOBAL: - return this->HandleGlobalMode(); + return HandleGlobalMode(status, names, propertyName, propertyValue, + appendAsString, appendMode, remove); case cmProperty::DIRECTORY: - return this->HandleDirectoryMode(); + return HandleDirectoryMode(status, names, propertyName, propertyValue, + appendAsString, appendMode, remove); case cmProperty::TARGET: - return this->HandleTargetMode(); + return HandleTargetMode(status, names, propertyName, propertyValue, + appendAsString, appendMode, remove); case cmProperty::SOURCE_FILE: - return this->HandleSourceMode(); + return HandleSourceMode(status, names, propertyName, propertyValue, + appendAsString, appendMode, remove); case cmProperty::TEST: - return this->HandleTestMode(); + return HandleTestMode(status, names, propertyName, propertyValue, + appendAsString, appendMode, remove); case cmProperty::CACHE: - return this->HandleCacheMode(); + return HandleCacheMode(status, names, propertyName, propertyValue, + appendAsString, appendMode, remove); case cmProperty::INSTALL: - return this->HandleInstallMode(); + return HandleInstallMode(status, names, propertyName, propertyValue, + appendAsString, appendMode, remove); case cmProperty::VARIABLE: case cmProperty::CACHED_VARIABLE: @@ -130,57 +193,66 @@ bool cmSetPropertyCommand::InitialPass(std::vector<std::string> const& args, return true; } -bool cmSetPropertyCommand::HandleGlobalMode() +namespace { +bool HandleGlobalMode(cmExecutionStatus& status, + const std::set<std::string>& names, + const std::string& propertyName, + const std::string& propertyValue, + const bool appendAsString, const bool appendMode, + const bool remove) { - if (!this->Names.empty()) { - this->SetError("given names for GLOBAL scope."); + if (!names.empty()) { + status.SetError("given names for GLOBAL scope."); return false; } // Set or append the property. - cmake* cm = this->Makefile->GetCMakeInstance(); - std::string const& name = this->PropertyName; - const char* value = this->PropertyValue.c_str(); - if (this->Remove) { + cmake* cm = status.GetMakefile().GetCMakeInstance(); + const char* value = propertyValue.c_str(); + if (remove) { value = nullptr; } - if (this->AppendMode) { - cm->AppendProperty(name, value ? value : "", this->AppendAsString); + if (appendMode) { + cm->AppendProperty(propertyName, value ? value : "", appendAsString); } else { - cm->SetProperty(name, value); + cm->SetProperty(propertyName, value); } return true; } -bool cmSetPropertyCommand::HandleDirectoryMode() +bool HandleDirectoryMode(cmExecutionStatus& status, + const std::set<std::string>& names, + const std::string& propertyName, + const std::string& propertyValue, + const bool appendAsString, const bool appendMode, + const bool remove) { - if (this->Names.size() > 1) { - this->SetError("allows at most one name for DIRECTORY scope."); + if (names.size() > 1) { + status.SetError("allows at most one name for DIRECTORY scope."); return false; } // Default to the current directory. - cmMakefile* mf = this->Makefile; + cmMakefile* mf = &status.GetMakefile(); // Lookup the directory if given. - if (!this->Names.empty()) { + if (!names.empty()) { // Construct the directory name. Interpret relative paths with // respect to the current directory. - std::string dir = *this->Names.begin(); + std::string dir = *names.begin(); if (!cmSystemTools::FileIsFullPath(dir)) { - dir = this->Makefile->GetCurrentSourceDirectory(); - dir += "/"; - dir += *this->Names.begin(); + dir = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', + *names.begin()); } // The local generators are associated with collapsed paths. dir = cmSystemTools::CollapseFullPath(dir); - mf = this->Makefile->GetGlobalGenerator()->FindMakefile(dir); + mf = status.GetMakefile().GetGlobalGenerator()->FindMakefile(dir); if (!mf) { // Could not find the directory. - this->SetError( + status.SetError( "DIRECTORY scope provided but requested directory was not found. " "This could be because the directory argument was invalid or, " "it is valid but has not been processed yet."); @@ -189,109 +261,128 @@ bool cmSetPropertyCommand::HandleDirectoryMode() } // Set or append the property. - std::string const& name = this->PropertyName; - const char* value = this->PropertyValue.c_str(); - if (this->Remove) { + const char* value = propertyValue.c_str(); + if (remove) { value = nullptr; } - if (this->AppendMode) { - mf->AppendProperty(name, value ? value : "", this->AppendAsString); + if (appendMode) { + mf->AppendProperty(propertyName, value ? value : "", appendAsString); } else { - mf->SetProperty(name, value); + mf->SetProperty(propertyName, value); } return true; } -bool cmSetPropertyCommand::HandleTargetMode() +bool HandleTargetMode(cmExecutionStatus& status, + const std::set<std::string>& names, + const std::string& propertyName, + const std::string& propertyValue, + const bool appendAsString, const bool appendMode, + const bool remove) { - for (std::string const& name : this->Names) { - if (this->Makefile->IsAlias(name)) { - this->SetError("can not be used on an ALIAS target."); + for (std::string const& name : names) { + if (status.GetMakefile().IsAlias(name)) { + status.SetError("can not be used on an ALIAS target."); return false; } - if (cmTarget* target = this->Makefile->FindTargetToUse(name)) { + if (cmTarget* target = status.GetMakefile().FindTargetToUse(name)) { // Handle the current target. - if (!this->HandleTarget(target)) { + if (!HandleTarget(target, status.GetMakefile(), propertyName, + propertyValue, appendAsString, appendMode, remove)) { return false; } } else { std::ostringstream e; e << "could not find TARGET " << name << ". Perhaps it has not yet been created."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } return true; } -bool cmSetPropertyCommand::HandleTarget(cmTarget* target) +bool HandleTarget(cmTarget* target, cmMakefile& makefile, + const std::string& propertyName, + const std::string& propertyValue, const bool appendAsString, + const bool appendMode, const bool remove) { // Set or append the property. - std::string const& name = this->PropertyName; - const char* value = this->PropertyValue.c_str(); - if (this->Remove) { + const char* value = propertyValue.c_str(); + if (remove) { value = nullptr; } - if (this->AppendMode) { - target->AppendProperty(name, value, this->AppendAsString); + if (appendMode) { + target->AppendProperty(propertyName, value, appendAsString); } else { - target->SetProperty(name, value); + target->SetProperty(propertyName, value); } // Check the resulting value. - target->CheckProperty(name, this->Makefile); + target->CheckProperty(propertyName, &makefile); return true; } -bool cmSetPropertyCommand::HandleSourceMode() +bool HandleSourceMode(cmExecutionStatus& status, + const std::set<std::string>& names, + const std::string& propertyName, + const std::string& propertyValue, + const bool appendAsString, const bool appendMode, + const bool remove) { - for (std::string const& name : this->Names) { + for (std::string const& name : names) { // Get the source file. - if (cmSourceFile* sf = this->Makefile->GetOrCreateSource(name)) { - if (!this->HandleSource(sf)) { + if (cmSourceFile* sf = status.GetMakefile().GetOrCreateSource(name)) { + if (!HandleSource(sf, propertyName, propertyValue, appendAsString, + appendMode, remove)) { return false; } } else { std::ostringstream e; e << "given SOURCE name that could not be found or created: " << name; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } return true; } -bool cmSetPropertyCommand::HandleSource(cmSourceFile* sf) +bool HandleSource(cmSourceFile* sf, const std::string& propertyName, + const std::string& propertyValue, const bool appendAsString, + const bool appendMode, const bool remove) { // Set or append the property. - std::string const& name = this->PropertyName; - const char* value = this->PropertyValue.c_str(); - if (this->Remove) { + const char* value = propertyValue.c_str(); + if (remove) { value = nullptr; } - if (this->AppendMode) { - sf->AppendProperty(name, value, this->AppendAsString); + if (appendMode) { + sf->AppendProperty(propertyName, value, appendAsString); } else { - sf->SetProperty(name, value); + sf->SetProperty(propertyName, value); } return true; } -bool cmSetPropertyCommand::HandleTestMode() +bool HandleTestMode(cmExecutionStatus& status, std::set<std::string>& names, + const std::string& propertyName, + const std::string& propertyValue, + const bool appendAsString, const bool appendMode, + const bool remove) { // Look for tests with all names given. std::set<std::string>::iterator next; - for (std::set<std::string>::iterator ni = this->Names.begin(); - ni != this->Names.end(); ni = next) { + for (std::set<std::string>::iterator ni = names.begin(); ni != names.end(); + ni = next) { next = ni; ++next; - if (cmTest* test = this->Makefile->GetTest(*ni)) { - if (this->HandleTest(test)) { - this->Names.erase(ni); + if (cmTest* test = status.GetMakefile().GetTest(*ni)) { + if (HandleTest(test, propertyName, propertyValue, appendAsString, + appendMode, remove)) { + names.erase(ni); } else { return false; } @@ -299,137 +390,151 @@ bool cmSetPropertyCommand::HandleTestMode() } // Names that are still left were not found. - if (!this->Names.empty()) { + if (!names.empty()) { std::ostringstream e; e << "given TEST names that do not exist:\n"; - for (std::string const& name : this->Names) { + for (std::string const& name : names) { e << " " << name << "\n"; } - this->SetError(e.str()); + status.SetError(e.str()); return false; } return true; } -bool cmSetPropertyCommand::HandleTest(cmTest* test) +bool HandleTest(cmTest* test, const std::string& propertyName, + const std::string& propertyValue, const bool appendAsString, + const bool appendMode, const bool remove) { // Set or append the property. - std::string const& name = this->PropertyName; - const char* value = this->PropertyValue.c_str(); - if (this->Remove) { + const char* value = propertyValue.c_str(); + if (remove) { value = nullptr; } - if (this->AppendMode) { - test->AppendProperty(name, value, this->AppendAsString); + if (appendMode) { + test->AppendProperty(propertyName, value, appendAsString); } else { - test->SetProperty(name, value); + test->SetProperty(propertyName, value); } return true; } -bool cmSetPropertyCommand::HandleCacheMode() +bool HandleCacheMode(cmExecutionStatus& status, + const std::set<std::string>& names, + const std::string& propertyName, + const std::string& propertyValue, + const bool appendAsString, const bool appendMode, + const bool remove) { - if (this->PropertyName == "ADVANCED") { - if (!this->Remove && !cmSystemTools::IsOn(this->PropertyValue) && - !cmSystemTools::IsOff(this->PropertyValue)) { + if (propertyName == "ADVANCED") { + if (!remove && !cmIsOn(propertyValue) && !cmIsOff(propertyValue)) { std::ostringstream e; - e << "given non-boolean value \"" << this->PropertyValue + e << "given non-boolean value \"" << propertyValue << R"(" for CACHE property "ADVANCED". )"; - this->SetError(e.str()); + status.SetError(e.str()); return false; } - } else if (this->PropertyName == "TYPE") { - if (!cmState::IsCacheEntryType(this->PropertyValue)) { + } else if (propertyName == "TYPE") { + if (!cmState::IsCacheEntryType(propertyValue)) { std::ostringstream e; - e << "given invalid CACHE entry TYPE \"" << this->PropertyValue << "\""; - this->SetError(e.str()); + e << "given invalid CACHE entry TYPE \"" << propertyValue << "\""; + status.SetError(e.str()); return false; } - } else if (this->PropertyName != "HELPSTRING" && - this->PropertyName != "STRINGS" && - this->PropertyName != "VALUE") { + } else if (propertyName != "HELPSTRING" && propertyName != "STRINGS" && + propertyName != "VALUE") { std::ostringstream e; - e << "given invalid CACHE property " << this->PropertyName << ". " + e << "given invalid CACHE property " << propertyName << ". " << "Settable CACHE properties are: " << "ADVANCED, HELPSTRING, STRINGS, TYPE, and VALUE."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } - for (std::string const& name : this->Names) { + for (std::string const& name : names) { // Get the source file. - cmMakefile* mf = this->GetMakefile(); - cmake* cm = mf->GetCMakeInstance(); + cmake* cm = status.GetMakefile().GetCMakeInstance(); const char* existingValue = cm->GetState()->GetCacheEntryValue(name); if (existingValue) { - if (!this->HandleCacheEntry(name)) { + if (!HandleCacheEntry(name, status.GetMakefile(), propertyName, + propertyValue, appendAsString, appendMode, + remove)) { return false; } } else { std::ostringstream e; e << "could not find CACHE variable " << name << ". Perhaps it has not yet been created."; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } return true; } -bool cmSetPropertyCommand::HandleCacheEntry(std::string const& cacheKey) +bool HandleCacheEntry(std::string const& cacheKey, const cmMakefile& makefile, + const std::string& propertyName, + const std::string& propertyValue, + const bool appendAsString, const bool appendMode, + const bool remove) { // Set or append the property. - std::string const& name = this->PropertyName; - const char* value = this->PropertyValue.c_str(); - cmState* state = this->Makefile->GetState(); - if (this->Remove) { - state->RemoveCacheEntryProperty(cacheKey, name); + const char* value = propertyValue.c_str(); + cmState* state = makefile.GetState(); + if (remove) { + state->RemoveCacheEntryProperty(cacheKey, propertyName); } - if (this->AppendMode) { - state->AppendCacheEntryProperty(cacheKey, name, value, - this->AppendAsString); + if (appendMode) { + state->AppendCacheEntryProperty(cacheKey, propertyName, value, + appendAsString); } else { - state->SetCacheEntryProperty(cacheKey, name, value); + state->SetCacheEntryProperty(cacheKey, propertyName, value); } return true; } -bool cmSetPropertyCommand::HandleInstallMode() +bool HandleInstallMode(cmExecutionStatus& status, + const std::set<std::string>& names, + const std::string& propertyName, + const std::string& propertyValue, + const bool appendAsString, const bool appendMode, + const bool remove) { - cmake* cm = this->Makefile->GetCMakeInstance(); + cmake* cm = status.GetMakefile().GetCMakeInstance(); - for (std::string const& name : this->Names) { + for (std::string const& name : names) { if (cmInstalledFile* file = - cm->GetOrCreateInstalledFile(this->Makefile, name)) { - if (!this->HandleInstall(file)) { + cm->GetOrCreateInstalledFile(&status.GetMakefile(), name)) { + if (!HandleInstall(file, status.GetMakefile(), propertyName, + propertyValue, appendAsString, appendMode, remove)) { return false; } } else { std::ostringstream e; e << "given INSTALL name that could not be found or created: " << name; - this->SetError(e.str()); + status.SetError(e.str()); return false; } } return true; } -bool cmSetPropertyCommand::HandleInstall(cmInstalledFile* file) +bool HandleInstall(cmInstalledFile* file, cmMakefile& makefile, + const std::string& propertyName, + const std::string& propertyValue, const bool appendAsString, + const bool appendMode, const bool remove) { // Set or append the property. - std::string const& name = this->PropertyName; - - cmMakefile* mf = this->Makefile; - - const char* value = this->PropertyValue.c_str(); - if (this->Remove) { - file->RemoveProperty(name); - } else if (this->AppendMode) { - file->AppendProperty(mf, name, value, this->AppendAsString); + const char* value = propertyValue.c_str(); + if (remove) { + file->RemoveProperty(propertyName); + } else if (appendMode) { + file->AppendProperty(&makefile, propertyName, value, appendAsString); } else { - file->SetProperty(mf, name, value); + file->SetProperty(&makefile, propertyName, value); } return true; } +} diff --git a/Source/cmSetPropertyCommand.h b/Source/cmSetPropertyCommand.h index f1126bb..ec36f84 100644 --- a/Source/cmSetPropertyCommand.h +++ b/Source/cmSetPropertyCommand.h @@ -5,53 +5,12 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <set> #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -class cmInstalledFile; -class cmSourceFile; -class cmTarget; -class cmTest; - -class cmSetPropertyCommand : public cmCommand -{ -public: - cmSetPropertyCommand(); - - cmCommand* Clone() override { return new cmSetPropertyCommand; } - - /** - * This is called when the command is first encountered in - * the input file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - std::set<std::string> Names; - std::string PropertyName; - std::string PropertyValue; - bool Remove; - bool AppendMode; - bool AppendAsString; - // Implementation of each property type. - bool HandleGlobalMode(); - bool HandleDirectoryMode(); - bool HandleTargetMode(); - bool HandleTarget(cmTarget* target); - bool HandleSourceMode(); - bool HandleSource(cmSourceFile* sf); - bool HandleTestMode(); - bool HandleTest(cmTest* test); - bool HandleCacheMode(); - bool HandleCacheEntry(std::string const&); - bool HandleInstallMode(); - bool HandleInstall(cmInstalledFile* file); -}; +bool cmSetPropertyCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmSetSourceFilesPropertiesCommand.cxx b/Source/cmSetSourceFilesPropertiesCommand.cxx index 9388e7c..8e3217f 100644 --- a/Source/cmSetSourceFilesPropertiesCommand.cxx +++ b/Source/cmSetSourceFilesPropertiesCommand.cxx @@ -4,7 +4,7 @@ #include "cmMakefile.h" #include "cmSourceFile.h" -#include "cmSystemTools.h" +#include "cmStringAlgorithms.h" class cmExecutionStatus; @@ -87,7 +87,7 @@ bool cmSetSourceFilesPropertiesCommand::RunCommand( propertyPairs.push_back(*j); if (*j == "GENERATED") { ++j; - if (j != propend && cmSystemTools::IsOn(*j)) { + if (j != propend && cmIsOn(*j)) { generated = true; } } else { diff --git a/Source/cmSetSourceFilesPropertiesCommand.h b/Source/cmSetSourceFilesPropertiesCommand.h index afb19f6..6fd6c41 100644 --- a/Source/cmSetSourceFilesPropertiesCommand.h +++ b/Source/cmSetSourceFilesPropertiesCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -16,7 +18,10 @@ class cmMakefile; class cmSetSourceFilesPropertiesCommand : public cmCommand { public: - cmCommand* Clone() override { return new cmSetSourceFilesPropertiesCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmSetSourceFilesPropertiesCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmSetTargetPropertiesCommand.cxx b/Source/cmSetTargetPropertiesCommand.cxx index 1dc7e69..b4360e4 100644 --- a/Source/cmSetTargetPropertiesCommand.cxx +++ b/Source/cmSetTargetPropertiesCommand.cxx @@ -6,6 +6,7 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmTarget.h" class cmExecutionStatus; @@ -52,8 +53,8 @@ bool cmSetTargetPropertiesCommand::InitialPass( bool ret = cmSetTargetPropertiesCommand::SetOneTarget( args[i], propertyPairs, this->Makefile); if (!ret) { - std::string message = "Can not find target to add properties to: "; - message += args[i]; + std::string message = + cmStrCat("Can not find target to add properties to: ", args[i]); this->SetError(message); return false; } diff --git a/Source/cmSetTargetPropertiesCommand.h b/Source/cmSetTargetPropertiesCommand.h index c9755da..7e4606e 100644 --- a/Source/cmSetTargetPropertiesCommand.h +++ b/Source/cmSetTargetPropertiesCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -16,7 +18,10 @@ class cmMakefile; class cmSetTargetPropertiesCommand : public cmCommand { public: - cmCommand* Clone() override { return new cmSetTargetPropertiesCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmSetTargetPropertiesCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmSetTestsPropertiesCommand.cxx b/Source/cmSetTestsPropertiesCommand.cxx index cc9587c..ed909c6 100644 --- a/Source/cmSetTestsPropertiesCommand.cxx +++ b/Source/cmSetTestsPropertiesCommand.cxx @@ -6,6 +6,7 @@ #include "cmAlgorithms.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmTest.h" class cmExecutionStatus; @@ -70,8 +71,7 @@ bool cmSetTestsPropertiesCommand::SetOneTest( } } } else { - errors = "Can not find test to add properties to: "; - errors += tname; + errors = cmStrCat("Can not find test to add properties to: ", tname); return false; } diff --git a/Source/cmSetTestsPropertiesCommand.h b/Source/cmSetTestsPropertiesCommand.h index 84b2645..d73e95a 100644 --- a/Source/cmSetTestsPropertiesCommand.h +++ b/Source/cmSetTestsPropertiesCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -16,7 +18,10 @@ class cmMakefile; class cmSetTestsPropertiesCommand : public cmCommand { public: - cmCommand* Clone() override { return new cmSetTestsPropertiesCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmSetTestsPropertiesCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmSiteNameCommand.cxx b/Source/cmSiteNameCommand.cxx index 9f041bc..d47f121 100644 --- a/Source/cmSiteNameCommand.cxx +++ b/Source/cmSiteNameCommand.cxx @@ -4,18 +4,18 @@ #include "cmsys/RegularExpression.hxx" +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmExecutionStatus; - // cmSiteNameCommand -bool cmSiteNameCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmSiteNameCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 1) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } std::vector<std::string> paths; @@ -26,12 +26,12 @@ bool cmSiteNameCommand::InitialPass(std::vector<std::string> const& args, paths.emplace_back("/sbin"); paths.emplace_back("/usr/local/bin"); - const char* cacheValue = this->Makefile->GetDefinition(args[0]); + const char* cacheValue = status.GetMakefile().GetDefinition(args[0]); if (cacheValue) { return true; } - const char* temp = this->Makefile->GetDefinition("HOSTNAME"); + const char* temp = status.GetMakefile().GetDefinition("HOSTNAME"); std::string hostname_cmd; if (temp) { hostname_cmd = temp; @@ -50,7 +50,7 @@ bool cmSiteNameCommand::InitialPass(std::vector<std::string> const& args, } #else // try to find the hostname for this computer - if (!cmSystemTools::IsOff(hostname_cmd)) { + if (!cmIsOff(hostname_cmd)) { std::string host; cmSystemTools::RunSingleCommand(hostname_cmd, &host, nullptr, nullptr, nullptr, cmSystemTools::OUTPUT_NONE); @@ -71,7 +71,7 @@ bool cmSiteNameCommand::InitialPass(std::vector<std::string> const& args, } } #endif - this->Makefile->AddCacheDefinition( + status.GetMakefile().AddCacheDefinition( args[0], siteName.c_str(), "Name of the computer/site where compile is being run", cmStateEnums::STRING); diff --git a/Source/cmSiteNameCommand.h b/Source/cmSiteNameCommand.h index 2d8dc17..e8fc608 100644 --- a/Source/cmSiteNameCommand.h +++ b/Source/cmSiteNameCommand.h @@ -8,29 +8,14 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmSiteNameCommand +/** * \brief site_name command * * cmSiteNameCommand implements the site_name CMake command */ -class cmSiteNameCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmSiteNameCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmSiteNameCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index d05fb68..a6d2807 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -11,6 +11,7 @@ #include "cmMessageType.h" #include "cmProperty.h" #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" @@ -150,9 +151,7 @@ bool cmSourceFile::FindFullPath(std::string* error) for (auto exts : extsLists) { for (std::string const& ext : *exts) { if (!ext.empty()) { - std::string extPath = fullPath; - extPath += '.'; - extPath += ext; + std::string extPath = cmStrCat(fullPath, '.', ext); if (cmSystemTools::FileExists(extPath)) { this->FullPath = extPath; return true; @@ -177,10 +176,8 @@ bool cmSourceFile::FindFullPath(std::string* error) } // Compose error - std::string err; - err += "Cannot find source file:\n "; - err += lPath; - err += "\nTried extensions"; + std::string err = + cmStrCat("Cannot find source file:\n ", lPath, "\nTried extensions"); for (auto exts : extsLists) { for (std::string const& ext : *exts) { err += " ."; @@ -242,7 +239,7 @@ void cmSourceFile::SetProperty(const std::string& prop, const char* value) // Update IsGenerated flag if (prop == propGENERATED) { - this->IsGenerated = cmSystemTools::IsOn(value); + this->IsGenerated = cmIsOn(value); } } @@ -316,7 +313,7 @@ const char* cmSourceFile::GetSafeProperty(const std::string& prop) const bool cmSourceFile::GetPropertyAsBool(const std::string& prop) const { - return cmSystemTools::IsOn(this->GetProperty(prop)); + return cmIsOn(this->GetProperty(prop)); } cmCustomCommand* cmSourceFile::GetCustomCommand() diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx index acacba2..0e8d09d 100644 --- a/Source/cmSourceFileLocation.cxx +++ b/Source/cmSourceFileLocation.cxx @@ -2,10 +2,10 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSourceFileLocation.h" -#include "cmAlgorithms.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" @@ -110,8 +110,7 @@ void cmSourceFileLocation::UpdateExtension(const std::string& name) // Check the source tree only because a file in the build tree should // be specified by full path at least once. We do not want this // detection to depend on whether the project has already been built. - tryPath = this->Makefile->GetCurrentSourceDirectory(); - tryPath += "/"; + tryPath = cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/'); } if (!this->Directory.empty()) { tryPath += this->Directory; @@ -146,8 +145,7 @@ bool cmSourceFileLocation::MatchesAmbiguousExtension( // adding an extension. if (!(this->Name.size() > loc.Name.size() && this->Name[loc.Name.size()] == '.' && - cmHasLiteralPrefixImpl(this->Name.c_str(), loc.Name.c_str(), - loc.Name.size()))) { + cmHasPrefix(this->Name, loc.Name))) { return false; } diff --git a/Source/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx index 7e1e836..418a40f 100644 --- a/Source/cmSourceGroup.cxx +++ b/Source/cmSourceGroup.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSourceGroup.h" +#include "cmStringAlgorithms.h" + #include <utility> class cmSourceGroupInternals @@ -17,8 +19,7 @@ cmSourceGroup::cmSourceGroup(std::string name, const char* regex, this->Internal = new cmSourceGroupInternals; this->SetGroupRegex(regex); if (parentName) { - this->FullName = parentName; - this->FullName += "\\"; + this->FullName = cmStrCat(parentName, '\\'); } this->FullName += this->Name; } diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx index 04b4d72..399f1da 100644 --- a/Source/cmSourceGroupCommand.cxx +++ b/Source/cmSourceGroupCommand.cxx @@ -2,13 +2,14 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSourceGroupCommand.h" -#include <algorithm> #include <set> #include <stddef.h> #include <utility> +#include "cmAlgorithms.h" #include "cmMakefile.h" #include "cmSourceGroup.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" namespace { @@ -20,7 +21,7 @@ const std::string kSourceGroupOptionName = "<sg_name>"; std::vector<std::string> tokenizePath(const std::string& path) { - return cmSystemTools::tokenize(path, "\\/"); + return cmTokenize(path, "\\/"); } std::string getFullFilePath(const std::string& currentPath, @@ -29,9 +30,7 @@ std::string getFullFilePath(const std::string& currentPath, std::string fullPath = path; if (!cmSystemTools::FileIsFullPath(path)) { - fullPath = currentPath; - fullPath += "/"; - fullPath += path; + fullPath = cmStrCat(currentPath, '/', path); } return cmSystemTools::CollapseFullPath(fullPath); @@ -54,8 +53,8 @@ bool rootIsPrefix(const std::string& root, const std::vector<std::string>& files, std::string& error) { for (std::string const& file : files) { - if (!cmSystemTools::StringStartsWith(file, root.c_str())) { - error = "ROOT: " + root + " is not a prefix of file: " + file; + if (!cmHasPrefix(file, root)) { + error = cmStrCat("ROOT: ", root, " is not a prefix of file: ", file); return false; } } @@ -93,7 +92,7 @@ bool addFilesToItsSourceGroups(const std::string& root, std::vector<std::string> tokenizedPath; if (!prefix.empty()) { - tokenizedPath = tokenizePath(prefix + '/' + sgFilesPath); + tokenizedPath = tokenizePath(cmStrCat(prefix, '/', sgFilesPath)); } else { tokenizedPath = tokenizePath(sgFilesPath); } @@ -139,8 +138,7 @@ cmSourceGroupCommand::getExpectedOptions() const bool cmSourceGroupCommand::isExpectedOption( const std::string& argument, const ExpectedOptions& expectedOptions) { - return std::find(expectedOptions.begin(), expectedOptions.end(), argument) != - expectedOptions.end(); + return cmContains(expectedOptions, argument); } void cmSourceGroupCommand::parseArguments( @@ -236,9 +234,8 @@ bool cmSourceGroupCommand::InitialPass(std::vector<std::string> const& args, for (auto const& filesArg : filesArguments) { std::string src = filesArg; if (!cmSystemTools::FileIsFullPath(src)) { - src = this->Makefile->GetCurrentSourceDirectory(); - src += "/"; - src += filesArg; + src = + cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', filesArg); } src = cmSystemTools::CollapseFullPath(src); sg->AddGroupFile(src); diff --git a/Source/cmSourceGroupCommand.h b/Source/cmSourceGroupCommand.h index ec5ad32..eec4ec0 100644 --- a/Source/cmSourceGroupCommand.h +++ b/Source/cmSourceGroupCommand.h @@ -9,6 +9,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -25,7 +27,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmSourceGroupCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmSourceGroupCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmState.cxx b/Source/cmState.cxx index fa7df0b..b6f1808 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -5,35 +5,34 @@ #include "cmsys/RegularExpression.hxx" #include <algorithm> #include <assert.h> +#include <stdlib.h> #include <string.h> #include <utility> -#include "cmAlgorithms.h" +#include "cm_memory.hxx" + #include "cmCacheManager.h" #include "cmCommand.h" #include "cmDefinitions.h" #include "cmDisallowedCommand.h" +#include "cmExecutionStatus.h" #include "cmGlobVerificationManager.h" #include "cmListFileCache.h" +#include "cmMakefile.h" +#include "cmMessageType.h" #include "cmStatePrivate.h" #include "cmStateSnapshot.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" -#include "cmUnexpectedCommand.h" #include "cmake.h" cmState::cmState() { - this->CacheManager = new cmCacheManager; - this->GlobVerificationManager = new cmGlobVerificationManager; + this->CacheManager = cm::make_unique<cmCacheManager>(); + this->GlobVerificationManager = cm::make_unique<cmGlobVerificationManager>(); } -cmState::~cmState() -{ - delete this->CacheManager; - delete this->GlobVerificationManager; - cmDeleteAll(this->BuiltinCommands); - cmDeleteAll(this->ScriptedCommands); -} +cmState::~cmState() = default; const char* cmState::GetTargetTypeName(cmStateEnums::TargetType targetType) { @@ -267,7 +266,7 @@ void cmState::RemoveCacheEntryProperty(std::string const& key, cmStateSnapshot cmState::Reset() { - this->GlobalProperties.clear(); + this->GlobalProperties.Clear(); this->PropertyDefinitions.clear(); this->GlobVerificationManager->Reset(); @@ -289,7 +288,7 @@ cmStateSnapshot cmState::Reset() it->LinkDirectoriesBacktraces.clear(); it->DirectoryEnd = pos; it->NormalTargetNames.clear(); - it->Properties.clear(); + it->Properties.Clear(); it->Children.clear(); } @@ -310,8 +309,8 @@ cmStateSnapshot cmState::Reset() pos->Parent = this->VarTree.Root(); pos->Root = this->VarTree.Root(); - pos->Vars->Set("CMAKE_SOURCE_DIR", srcDir.c_str()); - pos->Vars->Set("CMAKE_BINARY_DIR", binDir.c_str()); + pos->Vars->Set("CMAKE_SOURCE_DIR", srcDir); + pos->Vars->Set("CMAKE_BINARY_DIR", binDir); } this->DefineProperty("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY, "", "", @@ -421,61 +420,117 @@ void cmState::SetIsGeneratorMultiConfig(bool b) this->IsGeneratorMultiConfig = b; } -void cmState::AddBuiltinCommand(std::string const& name, cmCommand* command) +void cmState::AddBuiltinCommand(std::string const& name, + std::unique_ptr<cmCommand> command) +{ + this->AddBuiltinCommand(name, cmLegacyCommandWrapper(std::move(command))); +} + +void cmState::AddBuiltinCommand(std::string const& name, Command command) { assert(name == cmSystemTools::LowerCase(name)); assert(this->BuiltinCommands.find(name) == this->BuiltinCommands.end()); - this->BuiltinCommands.insert(std::make_pair(name, command)); + this->BuiltinCommands.emplace(name, std::move(command)); +} + +static bool InvokeBuiltinCommand(cmState::BuiltinCommand command, + std::vector<cmListFileArgument> const& args, + cmExecutionStatus& status) +{ + cmMakefile& mf = status.GetMakefile(); + std::vector<std::string> expandedArguments; + if (!mf.ExpandArguments(args, expandedArguments)) { + // There was an error expanding arguments. It was already + // reported, so we can skip this command without error. + return true; + } + return command(expandedArguments, status); } -void cmState::AddDisallowedCommand(std::string const& name, cmCommand* command, +void cmState::AddBuiltinCommand(std::string const& name, + BuiltinCommand command) +{ + this->AddBuiltinCommand( + name, + [command](const std::vector<cmListFileArgument>& args, + cmExecutionStatus& status) -> bool { + return InvokeBuiltinCommand(command, args, status); + }); +} + +void cmState::AddDisallowedCommand(std::string const& name, + BuiltinCommand command, cmPolicies::PolicyID policy, const char* message) { - this->AddBuiltinCommand(name, - new cmDisallowedCommand(command, policy, message)); + this->AddBuiltinCommand( + name, + [command, policy, message](const std::vector<cmListFileArgument>& args, + cmExecutionStatus& status) -> bool { + cmMakefile& mf = status.GetMakefile(); + switch (mf.GetPolicyStatus(policy)) { + case cmPolicies::WARN: + mf.IssueMessage(MessageType::AUTHOR_WARNING, + cmPolicies::GetPolicyWarning(policy)); + break; + case cmPolicies::OLD: + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + mf.IssueMessage(MessageType::FATAL_ERROR, message); + return true; + } + return InvokeBuiltinCommand(command, args, status); + }); +} + +void cmState::AddDisallowedCommand(std::string const& name, + std::unique_ptr<cmCommand> command, + cmPolicies::PolicyID policy, + const char* message) +{ + this->AddBuiltinCommand( + name, + cm::make_unique<cmDisallowedCommand>(std::move(command), policy, message)); } void cmState::AddUnexpectedCommand(std::string const& name, const char* error) { - this->AddBuiltinCommand(name, new cmUnexpectedCommand(name, error)); + this->AddBuiltinCommand( + name, + [name, error](std::vector<cmListFileArgument> const&, + cmExecutionStatus& status) -> bool { + const char* versionValue = + status.GetMakefile().GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION"); + if (name == "endif" && (!versionValue || atof(versionValue) <= 1.4)) { + return true; + } + status.SetError(error); + return false; + }); } -void cmState::AddScriptedCommand(std::string const& name, cmCommand* command) +void cmState::AddScriptedCommand(std::string const& name, Command command) { std::string sName = cmSystemTools::LowerCase(name); // if the command already exists, give a new name to the old command. - if (cmCommand* oldCmd = this->GetCommand(sName)) { - std::string const newName = "_" + sName; - std::map<std::string, cmCommand*>::iterator pos = - this->ScriptedCommands.find(newName); - if (pos != this->ScriptedCommands.end()) { - delete pos->second; - this->ScriptedCommands.erase(pos); - } - this->ScriptedCommands.insert(std::make_pair(newName, oldCmd->Clone())); + if (Command oldCmd = this->GetCommand(sName)) { + this->ScriptedCommands["_" + sName] = oldCmd; } - // if the command already exists, free the old one - std::map<std::string, cmCommand*>::iterator pos = - this->ScriptedCommands.find(sName); - if (pos != this->ScriptedCommands.end()) { - delete pos->second; - this->ScriptedCommands.erase(pos); - } - this->ScriptedCommands.insert(std::make_pair(sName, command)); + this->ScriptedCommands[sName] = std::move(command); } -cmCommand* cmState::GetCommand(std::string const& name) const +cmState::Command cmState::GetCommand(std::string const& name) const { return GetCommandByExactName(cmSystemTools::LowerCase(name)); } -cmCommand* cmState::GetCommandByExactName(std::string const& name) const +cmState::Command cmState::GetCommandByExactName(std::string const& name) const { - std::map<std::string, cmCommand*>::const_iterator pos; - pos = this->ScriptedCommands.find(name); + auto pos = this->ScriptedCommands.find(name); if (pos != this->ScriptedCommands.end()) { return pos->second; } @@ -506,16 +561,11 @@ std::vector<std::string> cmState::GetCommandNames() const void cmState::RemoveBuiltinCommand(std::string const& name) { assert(name == cmSystemTools::LowerCase(name)); - std::map<std::string, cmCommand*>::iterator i = - this->BuiltinCommands.find(name); - assert(i != this->BuiltinCommands.end()); - delete i->second; - this->BuiltinCommands.erase(i); + this->BuiltinCommands.erase(name); } void cmState::RemoveUserDefinedCommands() { - cmDeleteAll(this->ScriptedCommands); this->ScriptedCommands.clear(); } @@ -584,7 +634,7 @@ const char* cmState::GetGlobalProperty(const std::string& prop) bool cmState::GetGlobalPropertyAsBool(const std::string& prop) { - return cmSystemTools::IsOn(this->GetGlobalProperty(prop)); + return cmIsOn(this->GetGlobalProperty(prop)); } void cmState::SetSourceDirectory(std::string const& sourceDirectory) diff --git a/Source/cmState.h b/Source/cmState.h index 6abe71c..937ab61 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -5,7 +5,9 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <functional> #include <map> +#include <memory> #include <set> #include <string> #include <vector> @@ -26,6 +28,7 @@ class cmGlobVerificationManager; class cmPropertyDefinition; class cmStateSnapshot; class cmMessenger; +class cmExecutionStatus; class cmState { @@ -140,16 +143,27 @@ public: bool GetIsGeneratorMultiConfig() const; void SetIsGeneratorMultiConfig(bool b); + using Command = std::function<bool(std::vector<cmListFileArgument> const&, + cmExecutionStatus&)>; + using BuiltinCommand = bool (*)(std::vector<std::string> const&, + cmExecutionStatus&); + // Returns a command from its name, case insensitive, or nullptr - cmCommand* GetCommand(std::string const& name) const; + Command GetCommand(std::string const& name) const; // Returns a command from its name, or nullptr - cmCommand* GetCommandByExactName(std::string const& name) const; + Command GetCommandByExactName(std::string const& name) const; - void AddBuiltinCommand(std::string const& name, cmCommand* command); - void AddDisallowedCommand(std::string const& name, cmCommand* command, + void AddBuiltinCommand(std::string const& name, + std::unique_ptr<cmCommand> command); + void AddBuiltinCommand(std::string const& name, Command command); + void AddBuiltinCommand(std::string const& name, BuiltinCommand command); + void AddDisallowedCommand(std::string const& name, BuiltinCommand command, + cmPolicies::PolicyID policy, const char* message); + void AddDisallowedCommand(std::string const& name, + std::unique_ptr<cmCommand> command, cmPolicies::PolicyID policy, const char* message); void AddUnexpectedCommand(std::string const& name, const char* error); - void AddScriptedCommand(std::string const& name, cmCommand* command); + void AddScriptedCommand(std::string const& name, Command command); void RemoveBuiltinCommand(std::string const& name); void RemoveUserDefinedCommands(); std::vector<std::string> GetCommandNames() const; @@ -208,11 +222,11 @@ private: std::map<cmProperty::ScopeType, cmPropertyDefinitionMap> PropertyDefinitions; std::vector<std::string> EnabledLanguages; - std::map<std::string, cmCommand*> BuiltinCommands; - std::map<std::string, cmCommand*> ScriptedCommands; + std::map<std::string, Command> BuiltinCommands; + std::map<std::string, Command> ScriptedCommands; cmPropertyMap GlobalProperties; - cmCacheManager* CacheManager; - cmGlobVerificationManager* GlobVerificationManager; + std::unique_ptr<cmCacheManager> CacheManager; + std::unique_ptr<cmGlobVerificationManager> GlobVerificationManager; cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType> BuildsystemDirectory; diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index 182d3fe..df96bd3 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -6,7 +6,7 @@ #include <algorithm> #include <assert.h> #include <iterator> -#include <utility> +#include <vector> #include "cmAlgorithms.h" #include "cmProperty.h" @@ -662,17 +662,12 @@ const char* cmStateDirectory::GetProperty(const std::string& prop, bool cmStateDirectory::GetPropertyAsBool(const std::string& prop) const { - return cmSystemTools::IsOn(this->GetProperty(prop)); + return cmIsOn(this->GetProperty(prop)); } std::vector<std::string> cmStateDirectory::GetPropertyKeys() const { - std::vector<std::string> keys; - keys.reserve(this->DirectoryState->Properties.size()); - for (auto const& it : this->DirectoryState->Properties) { - keys.push_back(it.first); - } - return keys; + return this->DirectoryState->Properties.GetKeys(); } void cmStateDirectory::AddNormalTargetName(std::string const& name) diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h index 6956594..fe15563 100644 --- a/Source/cmStateDirectory.h +++ b/Source/cmStateDirectory.h @@ -14,6 +14,7 @@ #include "cmListFileCache.h" #include "cmStatePrivate.h" #include "cmStateSnapshot.h" +#include "cmStringAlgorithms.h" class cmStateDirectory { diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index 63bec71..121923d 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -222,14 +222,14 @@ bool cmStateSnapshot::IsInitialized(std::string const& name) const } void cmStateSnapshot::SetDefinition(std::string const& name, - std::string const& value) + cm::string_view value) { - this->Position->Vars->Set(name, value.c_str()); + this->Position->Vars->Set(name, value); } void cmStateSnapshot::RemoveDefinition(std::string const& name) { - this->Position->Vars->Set(name, nullptr); + this->Position->Vars->Unset(name); } std::vector<std::string> cmStateSnapshot::UnusedKeys() const @@ -264,7 +264,11 @@ bool cmStateSnapshot::RaiseScope(std::string const& var, const char* varDef) cmDefinitions::Raise(var, this->Position->Vars, this->Position->Root); // Now update the definition in the parent scope. - this->Position->Parent->Set(var, varDef); + if (varDef) { + this->Position->Parent->Set(var, varDef); + } else { + this->Position->Parent->Unset(var); + } return true; } @@ -324,7 +328,7 @@ void cmStateSnapshot::SetDefaultDefinitions() #if defined(__CYGWIN__) std::string legacy; if (cmSystemTools::GetEnv("CMAKE_LEGACY_CYGWIN_WIN32", legacy) && - cmSystemTools::IsOn(legacy.c_str())) { + cmIsOn(legacy.c_str())) { this->SetDefinition("WIN32", "1"); this->SetDefinition("CMAKE_HOST_WIN32", "1"); } diff --git a/Source/cmStateSnapshot.h b/Source/cmStateSnapshot.h index c315f48..da39127 100644 --- a/Source/cmStateSnapshot.h +++ b/Source/cmStateSnapshot.h @@ -9,6 +9,8 @@ #include <string> #include <vector> +#include "cm_string_view.hxx" + #include "cmLinkedTree.h" #include "cmPolicies.h" #include "cmStateTypes.h" @@ -24,7 +26,7 @@ public: std::string const* GetDefinition(std::string const& name) const; bool IsInitialized(std::string const& name) const; - void SetDefinition(std::string const& name, std::string const& value); + void SetDefinition(std::string const& name, cm::string_view value); void RemoveDefinition(std::string const& name); std::vector<std::string> UnusedKeys() const; std::vector<std::string> ClosureKeys() const; diff --git a/Source/cmStringAlgorithms.cxx b/Source/cmStringAlgorithms.cxx new file mode 100644 index 0000000..c686aa0 --- /dev/null +++ b/Source/cmStringAlgorithms.cxx @@ -0,0 +1,324 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmStringAlgorithms.h" + +#include <algorithm> +#include <cstdio> +#include <errno.h> +#include <stdlib.h> + +std::string cmTrimWhitespace(cm::string_view str) +{ + auto start = str.begin(); + while (start != str.end() && cmIsSpace(*start)) { + ++start; + } + if (start == str.end()) { + return std::string(); + } + auto stop = str.end() - 1; + while (cmIsSpace(*stop)) { + --stop; + } + return std::string(start, stop + 1); +} + +std::string cmRemoveQuotes(cm::string_view str) +{ + // We process only strings that have two quotes at least. + // Also front() and back() are only defined behavior on non empty strings. + if (str.size() >= 2 && // + str.front() == '"' && // + str.back() == '"') { + // Remove a quote from the front and back + str.remove_prefix(1); + str.remove_suffix(1); + } + return std::string(str); +} + +std::string cmEscapeQuotes(cm::string_view str) +{ + std::string result; + result.reserve(str.size()); + for (const char ch : str) { + if (ch == '"') { + result += '\\'; + } + result += ch; + } + return result; +} + +std::vector<std::string> cmTokenize(cm::string_view str, cm::string_view sep) +{ + std::vector<std::string> tokens; + cm::string_view::size_type tokend = 0; + + do { + cm::string_view::size_type tokstart = str.find_first_not_of(sep, tokend); + if (tokstart == cm::string_view::npos) { + break; // no more tokens + } + tokend = str.find_first_of(sep, tokstart); + if (tokend == cm::string_view::npos) { + tokens.emplace_back(str.substr(tokstart)); + } else { + tokens.emplace_back(str.substr(tokstart, tokend - tokstart)); + } + } while (tokend != cm::string_view::npos); + + if (tokens.empty()) { + tokens.emplace_back(); + } + return tokens; +} + +void cmExpandList(cm::string_view arg, std::vector<std::string>& argsOut, + bool emptyArgs) +{ + // If argument is empty, it is an empty list. + if (!emptyArgs && arg.empty()) { + return; + } + + // if there are no ; in the name then just copy the current string + if (arg.find(';') == cm::string_view::npos) { + argsOut.emplace_back(arg); + return; + } + + std::string newArg; + // Break the string at non-escaped semicolons not nested in []. + int squareNesting = 0; + cm::string_view::iterator last = arg.begin(); + cm::string_view::iterator const cend = arg.end(); + for (cm::string_view::iterator c = last; c != cend; ++c) { + switch (*c) { + case '\\': { + // We only want to allow escaping of semicolons. Other + // escapes should not be processed here. + cm::string_view::iterator cnext = c + 1; + if ((cnext != cend) && *cnext == ';') { + newArg.append(last, c); + // Skip over the escape character + last = cnext; + c = cnext; + } + } break; + case '[': { + ++squareNesting; + } break; + case ']': { + --squareNesting; + } break; + case ';': { + // Break the string here if we are not nested inside square + // brackets. + if (squareNesting == 0) { + newArg.append(last, c); + // Skip over the semicolon + last = c + 1; + if (!newArg.empty() || emptyArgs) { + // Add the last argument if the string is not empty. + argsOut.push_back(newArg); + newArg.clear(); + } + } + } break; + default: { + // Just append this character. + } break; + } + } + newArg.append(last, cend); + if (!newArg.empty() || emptyArgs) { + // Add the last argument if the string is not empty. + argsOut.push_back(std::move(newArg)); + } +} + +std::vector<std::string> cmExpandedList(cm::string_view arg, bool emptyArgs) +{ + std::vector<std::string> argsOut; + cmExpandList(arg, argsOut, emptyArgs); + return argsOut; +} + +namespace { +template <std::size_t N, typename T> +inline void MakeDigits(cm::string_view& view, char (&digits)[N], + const char* pattern, T value) +{ + int res = std::snprintf(digits, N, pattern, value); + if (res > 0 && res < static_cast<int>(N)) { + view = cm::string_view(digits, static_cast<std::size_t>(res)); + } +} +} // unnamed namespace + +cmAlphaNum::cmAlphaNum(int val) +{ + MakeDigits(View_, Digits_, "%i", val); +} + +cmAlphaNum::cmAlphaNum(unsigned int val) +{ + MakeDigits(View_, Digits_, "%u", val); +} + +cmAlphaNum::cmAlphaNum(long int val) +{ + MakeDigits(View_, Digits_, "%li", val); +} + +cmAlphaNum::cmAlphaNum(unsigned long int val) +{ + MakeDigits(View_, Digits_, "%lu", val); +} + +cmAlphaNum::cmAlphaNum(long long int val) +{ + MakeDigits(View_, Digits_, "%lli", val); +} + +cmAlphaNum::cmAlphaNum(unsigned long long int val) +{ + MakeDigits(View_, Digits_, "%llu", val); +} + +cmAlphaNum::cmAlphaNum(float val) +{ + MakeDigits(View_, Digits_, "%g", static_cast<double>(val)); +} + +cmAlphaNum::cmAlphaNum(double val) +{ + MakeDigits(View_, Digits_, "%g", val); +} + +std::string cmCatViews(std::initializer_list<cm::string_view> views) +{ + std::size_t total_size = 0; + for (cm::string_view const& view : views) { + total_size += view.size(); + } + + std::string result(total_size, '\0'); + std::string::iterator sit = result.begin(); + for (cm::string_view const& view : views) { + sit = std::copy_n(view.data(), view.size(), sit); + } + return result; +} + +bool cmIsInternallyOn(cm::string_view val) +{ + return (val.size() == 4) && // + (val[0] == 'I' || val[0] == 'i') && // + (val[1] == '_') && // + (val[2] == 'O' || val[2] == 'o') && // + (val[3] == 'N' || val[3] == 'n'); +} + +bool cmIsNOTFOUND(cm::string_view val) +{ + return (val == "NOTFOUND") || cmHasLiteralSuffix(val, "-NOTFOUND"); +} + +bool cmIsOn(cm::string_view val) +{ + switch (val.size()) { + case 1: + return val[0] == '1' || val[0] == 'Y' || val[0] == 'y'; + case 2: + return // + (val[0] == 'O' || val[0] == 'o') && // + (val[1] == 'N' || val[1] == 'n'); + case 3: + return // + (val[0] == 'Y' || val[0] == 'y') && // + (val[1] == 'E' || val[1] == 'e') && // + (val[2] == 'S' || val[2] == 's'); + case 4: + return // + (val[0] == 'T' || val[0] == 't') && // + (val[1] == 'R' || val[1] == 'r') && // + (val[2] == 'U' || val[2] == 'u') && // + (val[3] == 'E' || val[3] == 'e'); + default: + break; + } + + return false; +} + +bool cmIsOff(cm::string_view val) +{ + switch (val.size()) { + case 0: + return true; + case 1: + return val[0] == '0' || val[0] == 'N' || val[0] == 'n'; + case 2: + return // + (val[0] == 'N' || val[0] == 'n') && // + (val[1] == 'O' || val[1] == 'o'); + case 3: + return // + (val[0] == 'O' || val[0] == 'o') && // + (val[1] == 'F' || val[1] == 'f') && // + (val[2] == 'F' || val[2] == 'f'); + case 5: + return // + (val[0] == 'F' || val[0] == 'f') && // + (val[1] == 'A' || val[1] == 'a') && // + (val[2] == 'L' || val[2] == 'l') && // + (val[3] == 'S' || val[3] == 's') && // + (val[4] == 'E' || val[4] == 'e'); + case 6: + return // + (val[0] == 'I' || val[0] == 'i') && // + (val[1] == 'G' || val[1] == 'g') && // + (val[2] == 'N' || val[2] == 'n') && // + (val[3] == 'O' || val[3] == 'o') && // + (val[4] == 'R' || val[4] == 'r') && // + (val[5] == 'E' || val[5] == 'e'); + default: + break; + } + + return cmIsNOTFOUND(val); +} + +bool cmStrToLong(const char* str, long* value) +{ + errno = 0; + char* endp; + *value = strtol(str, &endp, 10); + return (*endp == '\0') && (endp != str) && (errno == 0); +} + +bool cmStrToLong(std::string const& str, long* value) +{ + return cmStrToLong(str.c_str(), value); +} + +bool cmStrToULong(const char* str, unsigned long* value) +{ + errno = 0; + char* endp; + while (cmIsSpace(*str)) { + ++str; + } + if (*str == '-') { + return false; + } + *value = strtoul(str, &endp, 10); + return (*endp == '\0') && (endp != str) && (errno == 0); +} + +bool cmStrToULong(std::string const& str, unsigned long* value) +{ + return cmStrToULong(str.c_str(), value); +} diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h new file mode 100644 index 0000000..5b8b878 --- /dev/null +++ b/Source/cmStringAlgorithms.h @@ -0,0 +1,292 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmStringAlgorithms_h +#define cmStringAlgorithms_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmRange.h" +#include "cm_string_view.hxx" +#include <cctype> +#include <initializer_list> +#include <sstream> +#include <string.h> +#include <string> +#include <utility> +#include <vector> + +/** String range type. */ +typedef cmRange<std::vector<std::string>::const_iterator> cmStringRange; + +/** Callable string comparison struct. */ +struct cmStrCmp +{ + cmStrCmp(std::string str) + : Test_(std::move(str)) + { + } + + bool operator()(cm::string_view sv) const { return Test_ == sv; } + +private: + std::string const Test_; +}; + +/** Returns true if the character @a ch is a whitespace character. **/ +inline bool cmIsSpace(char ch) +{ + return ((ch & 0x80) == 0) && std::isspace(ch); +} + +/** Returns a string that has whitespace removed from the start and the end. */ +std::string cmTrimWhitespace(cm::string_view str); + +/** Returns a string that has quotes removed from the start and the end. */ +std::string cmRemoveQuotes(cm::string_view str); + +/** Escape quotes in a string. */ +std::string cmEscapeQuotes(cm::string_view str); + +/** Joins elements of a range with separator into a single string. */ +template <typename Range> +std::string cmJoin(Range const& rng, cm::string_view separator) +{ + if (rng.empty()) { + return std::string(); + } + + std::ostringstream os; + auto it = rng.begin(); + auto const end = rng.end(); + os << *it; + while (++it != end) { + os << separator << *it; + } + return os.str(); +} + +/** Extract tokens that are separated by any of the characters in @a sep. */ +std::vector<std::string> cmTokenize(cm::string_view str, cm::string_view sep); + +/** + * Expand the ; separated string @a arg into multiple arguments. + * All found arguments are appended to @a argsOut. + */ +void cmExpandList(cm::string_view arg, std::vector<std::string>& argsOut, + bool emptyArgs = false); + +/** + * Expand out any arguments in the string range [@a first, @a last) that have + * ; separated strings into multiple arguments. All found arguments are + * appended to @a argsOut. + */ +template <class InputIt> +void cmExpandLists(InputIt first, InputIt last, + std::vector<std::string>& argsOut) +{ + for (; first != last; ++first) { + ExpandList(*first, argsOut); + } +} + +/** + * Same as cmExpandList but a new vector is created containing + * the expanded arguments from the string @a arg. + */ +std::vector<std::string> cmExpandedList(cm::string_view arg, + bool emptyArgs = false); + +/** + * Same as cmExpandList but a new vector is created containing the expanded + * versions of all arguments in the string range [@a first, @a last). + */ +template <class InputIt> +std::vector<std::string> cmExpandedLists(InputIt first, InputIt last) +{ + std::vector<std::string> argsOut; + for (; first != last; ++first) { + cmExpandList(*first, argsOut); + } + return argsOut; +} + +/** Concatenate string pieces into a single string. */ +std::string cmCatViews(std::initializer_list<cm::string_view> views); + +/** Utility class for cmStrCat. */ +class cmAlphaNum +{ +public: + cmAlphaNum(cm::string_view view) + : View_(view) + { + } + cmAlphaNum(std::string const& str) + : View_(str) + { + } + cmAlphaNum(const char* str) + : View_(str) + { + } + cmAlphaNum(char ch) + : View_(Digits_, 1) + { + Digits_[0] = ch; + } + cmAlphaNum(int val); + cmAlphaNum(unsigned int val); + cmAlphaNum(long int val); + cmAlphaNum(unsigned long int val); + cmAlphaNum(long long int val); + cmAlphaNum(unsigned long long int val); + cmAlphaNum(float val); + cmAlphaNum(double val); + + cm::string_view View() const { return View_; } + +private: + cm::string_view View_; + char Digits_[32]; +}; + +/** Concatenate string pieces and numbers into a single string. */ +template <typename... AV> +inline std::string cmStrCat(cmAlphaNum const& a, cmAlphaNum const& b, + AV const&... args) +{ + return cmCatViews( + { a.View(), b.View(), static_cast<cmAlphaNum const&>(args).View()... }); +} + +/** Joins wrapped elements of a range with separator into a single string. */ +template <typename Range> +std::string cmWrap(cm::string_view prefix, Range const& rng, + cm::string_view suffix, cm::string_view sep) +{ + if (rng.empty()) { + return std::string(); + } + return cmCatViews( + { prefix, cmJoin(rng, cmCatViews({ suffix, sep, prefix })), suffix }); +} + +/** Joins wrapped elements of a range with separator into a single string. */ +template <typename Range> +std::string cmWrap(char prefix, Range const& rng, char suffix, + cm::string_view sep) +{ + return cmWrap(cm::string_view(&prefix, 1), rng, cm::string_view(&suffix, 1), + sep); +} + +/** + * Does a string indicates that CMake/CPack/CTest internally + * forced this value. This is not the same as On, but this + * may be considered as "internally switched on". + */ +bool cmIsInternallyOn(cm::string_view val); +inline bool cmIsInternallyOn(const char* val) +{ + if (!val) { + return false; + } + return cmIsInternallyOn(cm::string_view(val)); +} + +/** Return true if value is NOTFOUND or ends in -NOTFOUND. */ +bool cmIsNOTFOUND(cm::string_view val); + +/** + * Does a string indicate a true or ON value? This is not the same as ifdef. + */ +bool cmIsOn(cm::string_view val); +inline bool cmIsOn(const char* val) +{ + if (!val) { + return false; + } + return cmIsOn(cm::string_view(val)); +} + +/** + * Does a string indicate a false or off value ? Note that this is + * not the same as !IsOn(...) because there are a number of + * ambiguous values such as "/usr/local/bin" a path will result in + * IsON and IsOff both returning false. Note that the special path + * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true. + */ +bool cmIsOff(cm::string_view val); +inline bool cmIsOff(const char* val) +{ + if (!val) { + return true; + } + return cmIsOff(cm::string_view(val)); +} + +/** Returns true if string @a str starts with the character @a prefix. */ +inline bool cmHasPrefix(cm::string_view str, char prefix) +{ + return !str.empty() && (str.front() == prefix); +} + +/** Returns true if string @a str starts with string @a prefix. */ +inline bool cmHasPrefix(cm::string_view str, cm::string_view prefix) +{ + return str.compare(0, prefix.size(), prefix) == 0; +} + +/** Returns true if string @a str starts with string @a prefix. */ +template <size_t N> +inline bool cmHasLiteralPrefix(cm::string_view str, const char (&prefix)[N]) +{ + return cmHasPrefix(str, cm::string_view(prefix, N - 1)); +} + +/** Returns true if string @a str ends with the character @a suffix. */ +inline bool cmHasSuffix(cm::string_view str, char suffix) +{ + return !str.empty() && (str.back() == suffix); +} + +/** Returns true if string @a str ends with string @a suffix. */ +inline bool cmHasSuffix(cm::string_view str, cm::string_view suffix) +{ + return str.size() >= suffix.size() && + str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; +} + +/** Returns true if string @a str ends with string @a suffix. */ +template <size_t N> +inline bool cmHasLiteralSuffix(cm::string_view str, const char (&suffix)[N]) +{ + return cmHasSuffix(str, cm::string_view(suffix, N - 1)); +} + +/** Removes an existing suffix character of from the string @a str. */ +inline void cmStripSuffixIfExists(std::string& str, char suffix) +{ + if (cmHasSuffix(str, suffix)) { + str.pop_back(); + } +} + +/** Removes an existing suffix string of from the string @a str. */ +inline void cmStripSuffixIfExists(std::string& str, cm::string_view suffix) +{ + if (cmHasSuffix(str, suffix)) { + str.resize(str.size() - suffix.size()); + } +} + +/** Converts a string to long. Expects that the whole string is an integer. */ +bool cmStrToLong(const char* str, long* value); +bool cmStrToLong(std::string const& str, long* value); + +/** Converts a string to unsigned long. Expects that the whole string is an + * integer */ +bool cmStrToULong(const char* str, unsigned long* value); +bool cmStrToULong(std::string const& str, unsigned long* value); + +#endif diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 998f904..9a2de9d 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -8,139 +8,70 @@ #include <algorithm> #include <ctype.h> #include <iterator> -#include <memory> // IWYU pragma: keep +#include <memory> #include <sstream> #include <stdio.h> #include <stdlib.h> +#include "cm_static_string_view.hxx" + #include "cmAlgorithms.h" #include "cmCryptoHash.h" +#include "cmExecutionStatus.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmRange.h" +#include "cmStringAlgorithms.h" #include "cmStringReplaceHelper.h" +#include "cmSubcommandTable.h" #include "cmSystemTools.h" #include "cmTimestamp.h" #include "cmUuid.h" -class cmExecutionStatus; +namespace { -bool cmStringCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) -{ - if (args.empty()) { - this->SetError("must be called with at least one argument."); - return false; - } +bool RegexMatch(std::vector<std::string> const& args, + cmExecutionStatus& status); +bool RegexMatchAll(std::vector<std::string> const& args, + cmExecutionStatus& status); +bool RegexReplace(std::vector<std::string> const& args, + cmExecutionStatus& status); - const std::string& subCommand = args[0]; - if (subCommand == "REGEX") { - return this->HandleRegexCommand(args); - } - if (subCommand == "REPLACE") { - return this->HandleReplaceCommand(args); - } - if (subCommand == "MD5" || subCommand == "SHA1" || subCommand == "SHA224" || - subCommand == "SHA256" || subCommand == "SHA384" || - subCommand == "SHA512" || subCommand == "SHA3_224" || - subCommand == "SHA3_256" || subCommand == "SHA3_384" || - subCommand == "SHA3_512") { - return this->HandleHashCommand(args); - } - if (subCommand == "TOLOWER") { - return this->HandleToUpperLowerCommand(args, false); - } - if (subCommand == "TOUPPER") { - return this->HandleToUpperLowerCommand(args, true); - } - if (subCommand == "COMPARE") { - return this->HandleCompareCommand(args); - } - if (subCommand == "ASCII") { - return this->HandleAsciiCommand(args); - } - if (subCommand == "CONFIGURE") { - return this->HandleConfigureCommand(args); - } - if (subCommand == "LENGTH") { - return this->HandleLengthCommand(args); - } - if (subCommand == "APPEND") { - return this->HandleAppendCommand(args); - } - if (subCommand == "PREPEND") { - return this->HandlePrependCommand(args); - } - if (subCommand == "CONCAT") { - return this->HandleConcatCommand(args); - } - if (subCommand == "JOIN") { - return this->HandleJoinCommand(args); - } - if (subCommand == "SUBSTRING") { - return this->HandleSubstringCommand(args); - } - if (subCommand == "STRIP") { - return this->HandleStripCommand(args); - } - if (subCommand == "REPEAT") { - return this->HandleRepeatCommand(args); - } - if (subCommand == "RANDOM") { - return this->HandleRandomCommand(args); - } - if (subCommand == "FIND") { - return this->HandleFindCommand(args); - } - if (subCommand == "TIMESTAMP") { - return this->HandleTimestampCommand(args); - } - if (subCommand == "MAKE_C_IDENTIFIER") { - return this->HandleMakeCIdentifierCommand(args); - } - if (subCommand == "GENEX_STRIP") { - return this->HandleGenexStripCommand(args); - } - if (subCommand == "UUID") { - return this->HandleUuidCommand(args); - } +bool joinImpl(std::vector<std::string> const& args, std::string const& glue, + size_t varIdx, cmMakefile& makefile); - std::string e = "does not recognize sub-command " + subCommand; - this->SetError(e); - return false; -} - -bool cmStringCommand::HandleHashCommand(std::vector<std::string> const& args) +bool HandleHashCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) if (args.size() != 3) { std::ostringstream e; e << args[0] << " requires an output variable and an input string"; - this->SetError(e.str()); + status.SetError(e.str()); return false; } - std::unique_ptr<cmCryptoHash> hash(cmCryptoHash::New(args[0].c_str())); + std::unique_ptr<cmCryptoHash> hash(cmCryptoHash::New(args[0])); if (hash) { std::string out = hash->HashString(args[2]); - this->Makefile->AddDefinition(args[1], out.c_str()); + status.GetMakefile().AddDefinition(args[1], out); return true; } return false; #else std::ostringstream e; e << args[0] << " not available during bootstrap"; - this->SetError(e.str().c_str()); + status.SetError(e.str().c_str()); return false; #endif } -bool cmStringCommand::HandleToUpperLowerCommand( - std::vector<std::string> const& args, bool toUpper) +bool HandleToUpperLowerCommand(std::vector<std::string> const& args, + bool toUpper, cmExecutionStatus& status) { if (args.size() < 3) { - this->SetError("no output variable specified"); + status.SetError("no output variable specified"); return false; } @@ -154,14 +85,27 @@ bool cmStringCommand::HandleToUpperLowerCommand( } // Store the output in the provided variable. - this->Makefile->AddDefinition(outvar, output.c_str()); + status.GetMakefile().AddDefinition(outvar, output); return true; } -bool cmStringCommand::HandleAsciiCommand(std::vector<std::string> const& args) +bool HandleToUpperCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleToUpperLowerCommand(args, true, status); +} + +bool HandleToLowerCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return HandleToUpperLowerCommand(args, false, status); +} + +bool HandleAsciiCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 3) { - this->SetError("No output variable specified"); + status.SetError("No output variable specified"); return false; } std::string::size_type cc; @@ -172,27 +116,26 @@ bool cmStringCommand::HandleAsciiCommand(std::vector<std::string> const& args) if (ch > 0 && ch < 256) { output += static_cast<char>(ch); } else { - std::string error = "Character with code "; - error += args[cc]; - error += " does not exist."; - this->SetError(error); + std::string error = + cmStrCat("Character with code ", args[cc], " does not exist."); + status.SetError(error); return false; } } // Store the output in the provided variable. - this->Makefile->AddDefinition(outvar, output.c_str()); + status.GetMakefile().AddDefinition(outvar, output); return true; } -bool cmStringCommand::HandleConfigureCommand( - std::vector<std::string> const& args) +bool HandleConfigureCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 2) { - this->SetError("No input string specified."); + status.SetError("No input string specified."); return false; } if (args.size() < 3) { - this->SetError("No output variable specified."); + status.SetError("No output variable specified."); return false; } @@ -207,73 +150,75 @@ bool cmStringCommand::HandleConfigureCommand( } else { std::ostringstream err; err << "Unrecognized argument \"" << args[i] << "\""; - this->SetError(err.str()); + status.SetError(err.str()); return false; } } // Configure the string. std::string output; - this->Makefile->ConfigureString(args[1], output, atOnly, escapeQuotes); + status.GetMakefile().ConfigureString(args[1], output, atOnly, escapeQuotes); // Store the output in the provided variable. - this->Makefile->AddDefinition(args[2], output.c_str()); + status.GetMakefile().AddDefinition(args[2], output); return true; } -bool cmStringCommand::HandleRegexCommand(std::vector<std::string> const& args) +bool HandleRegexCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 2) { - this->SetError("sub-command REGEX requires a mode to be specified."); + status.SetError("sub-command REGEX requires a mode to be specified."); return false; } std::string const& mode = args[1]; if (mode == "MATCH") { if (args.size() < 5) { - this->SetError("sub-command REGEX, mode MATCH needs " - "at least 5 arguments total to command."); + status.SetError("sub-command REGEX, mode MATCH needs " + "at least 5 arguments total to command."); return false; } - return this->RegexMatch(args); + return RegexMatch(args, status); } if (mode == "MATCHALL") { if (args.size() < 5) { - this->SetError("sub-command REGEX, mode MATCHALL needs " - "at least 5 arguments total to command."); + status.SetError("sub-command REGEX, mode MATCHALL needs " + "at least 5 arguments total to command."); return false; } - return this->RegexMatchAll(args); + return RegexMatchAll(args, status); } if (mode == "REPLACE") { if (args.size() < 6) { - this->SetError("sub-command REGEX, mode REPLACE needs " - "at least 6 arguments total to command."); + status.SetError("sub-command REGEX, mode REPLACE needs " + "at least 6 arguments total to command."); return false; } - return this->RegexReplace(args); + return RegexReplace(args, status); } std::string e = "sub-command REGEX does not recognize mode " + mode; - this->SetError(e); + status.SetError(e); return false; } -bool cmStringCommand::RegexMatch(std::vector<std::string> const& args) +bool RegexMatch(std::vector<std::string> const& args, + cmExecutionStatus& status) { //"STRING(REGEX MATCH <regular_expression> <output variable> // <input> [<input>...])\n"; std::string const& regex = args[2]; std::string const& outvar = args[3]; - this->Makefile->ClearMatches(); + status.GetMakefile().ClearMatches(); // Compile the regular expression. cmsys::RegularExpression re; if (!re.compile(regex.c_str())) { std::string e = "sub-command REGEX, mode MATCH failed to compile regex \"" + regex + "\"."; - this->SetError(e); + status.SetError(e); return false; } @@ -283,38 +228,39 @@ bool cmStringCommand::RegexMatch(std::vector<std::string> const& args) // Scan through the input for all matches. std::string output; if (re.find(input)) { - this->Makefile->StoreMatches(re); + status.GetMakefile().StoreMatches(re); std::string::size_type l = re.start(); std::string::size_type r = re.end(); if (r - l == 0) { std::string e = "sub-command REGEX, mode MATCH regex \"" + regex + "\" matched an empty string."; - this->SetError(e); + status.SetError(e); return false; } output = input.substr(l, r - l); } // Store the output in the provided variable. - this->Makefile->AddDefinition(outvar, output.c_str()); + status.GetMakefile().AddDefinition(outvar, output); return true; } -bool cmStringCommand::RegexMatchAll(std::vector<std::string> const& args) +bool RegexMatchAll(std::vector<std::string> const& args, + cmExecutionStatus& status) { //"STRING(REGEX MATCHALL <regular_expression> <output variable> <input> // [<input>...])\n"; std::string const& regex = args[2]; std::string const& outvar = args[3]; - this->Makefile->ClearMatches(); + status.GetMakefile().ClearMatches(); // Compile the regular expression. cmsys::RegularExpression re; if (!re.compile(regex.c_str())) { std::string e = "sub-command REGEX, mode MATCHALL failed to compile regex \"" + regex + "\"."; - this->SetError(e); + status.SetError(e); return false; } @@ -325,14 +271,14 @@ bool cmStringCommand::RegexMatchAll(std::vector<std::string> const& args) std::string output; const char* p = input.c_str(); while (re.find(p)) { - this->Makefile->ClearMatches(); - this->Makefile->StoreMatches(re); + status.GetMakefile().ClearMatches(); + status.GetMakefile().StoreMatches(re); std::string::size_type l = re.start(); std::string::size_type r = re.end(); if (r - l == 0) { std::string e = "sub-command REGEX, mode MATCHALL regex \"" + regex + "\" matched an empty string."; - this->SetError(e); + status.SetError(e); return false; } if (!output.empty()) { @@ -343,32 +289,33 @@ bool cmStringCommand::RegexMatchAll(std::vector<std::string> const& args) } // Store the output in the provided variable. - this->Makefile->AddDefinition(outvar, output.c_str()); + status.GetMakefile().AddDefinition(outvar, output); return true; } -bool cmStringCommand::RegexReplace(std::vector<std::string> const& args) +bool RegexReplace(std::vector<std::string> const& args, + cmExecutionStatus& status) { //"STRING(REGEX REPLACE <regular_expression> <replace_expression> // <output variable> <input> [<input>...])\n" std::string const& regex = args[2]; std::string const& replace = args[3]; std::string const& outvar = args[4]; - cmStringReplaceHelper replaceHelper(regex, replace, this->Makefile); + cmStringReplaceHelper replaceHelper(regex, replace, &status.GetMakefile()); if (!replaceHelper.IsReplaceExpressionValid()) { - this->SetError( + status.SetError( "sub-command REGEX, mode REPLACE: " + replaceHelper.GetError() + "."); return false; } - this->Makefile->ClearMatches(); + status.GetMakefile().ClearMatches(); if (!replaceHelper.IsRegularExpressionValid()) { std::string e = "sub-command REGEX, mode REPLACE failed to compile regex \"" + regex + "\"."; - this->SetError(e); + status.SetError(e); return false; } @@ -378,21 +325,22 @@ bool cmStringCommand::RegexReplace(std::vector<std::string> const& args) std::string output; if (!replaceHelper.Replace(input, output)) { - this->SetError( + status.SetError( "sub-command REGEX, mode REPLACE: " + replaceHelper.GetError() + "."); return false; } // Store the output in the provided variable. - this->Makefile->AddDefinition(outvar, output.c_str()); + status.GetMakefile().AddDefinition(outvar, output); return true; } -bool cmStringCommand::HandleFindCommand(std::vector<std::string> const& args) +bool HandleFindCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { // check if all required parameters were passed if (args.size() < 4 || args.size() > 5) { - this->SetError("sub-command FIND requires 3 or 4 parameters."); + status.SetError("sub-command FIND requires 3 or 4 parameters."); return false; } @@ -404,7 +352,7 @@ bool cmStringCommand::HandleFindCommand(std::vector<std::string> const& args) // if we have 5 arguments the last one must be REVERSE if (args.size() == 5 && args[4] != "REVERSE") { - this->SetError("sub-command FIND: unknown last parameter"); + status.SetError("sub-command FIND: unknown last parameter"); return false; } @@ -415,9 +363,9 @@ bool cmStringCommand::HandleFindCommand(std::vector<std::string> const& args) // ensure that the user cannot accidentally specify REVERSE as a variable if (outvar == "REVERSE") { - this->SetError("sub-command FIND does not allow one to select REVERSE as " - "the output variable. " - "Maybe you missed the actual output variable?"); + status.SetError("sub-command FIND does not allow one to select REVERSE as " + "the output variable. " + "Maybe you missed the actual output variable?"); return false; } @@ -431,20 +379,20 @@ bool cmStringCommand::HandleFindCommand(std::vector<std::string> const& args) if (std::string::npos != pos) { std::ostringstream s; s << pos; - this->Makefile->AddDefinition(outvar, s.str().c_str()); + status.GetMakefile().AddDefinition(outvar, s.str()); return true; } // the character was not found, but this is not really an error - this->Makefile->AddDefinition(outvar, "-1"); + status.GetMakefile().AddDefinition(outvar, "-1"); return true; } -bool cmStringCommand::HandleCompareCommand( - std::vector<std::string> const& args) +bool HandleCompareCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 2) { - this->SetError("sub-command COMPARE requires a mode to be specified."); + status.SetError("sub-command COMPARE requires a mode to be specified."); return false; } std::string const& mode = args[1]; @@ -452,10 +400,10 @@ bool cmStringCommand::HandleCompareCommand( (mode == "LESS_EQUAL") || (mode == "GREATER") || (mode == "GREATER_EQUAL")) { if (args.size() < 5) { - std::string e = "sub-command COMPARE, mode "; - e += mode; - e += " needs at least 5 arguments total to command."; - this->SetError(e); + std::string e = + cmStrCat("sub-command COMPARE, mode ", mode, + " needs at least 5 arguments total to command."); + status.SetError(e); return false; } @@ -478,22 +426,22 @@ bool cmStringCommand::HandleCompareCommand( result = !(left == right); } if (result) { - this->Makefile->AddDefinition(outvar, "1"); + status.GetMakefile().AddDefinition(outvar, "1"); } else { - this->Makefile->AddDefinition(outvar, "0"); + status.GetMakefile().AddDefinition(outvar, "0"); } return true; } std::string e = "sub-command COMPARE does not recognize mode " + mode; - this->SetError(e); + status.SetError(e); return false; } -bool cmStringCommand::HandleReplaceCommand( - std::vector<std::string> const& args) +bool HandleReplaceCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 5) { - this->SetError("sub-command REPLACE requires at least four arguments."); + status.SetError("sub-command REPLACE requires at least four arguments."); return false; } @@ -506,15 +454,15 @@ bool cmStringCommand::HandleReplaceCommand( cmsys::SystemTools::ReplaceString(input, matchExpression.c_str(), replaceExpression.c_str()); - this->Makefile->AddDefinition(variableName, input.c_str()); + status.GetMakefile().AddDefinition(variableName, input); return true; } -bool cmStringCommand::HandleSubstringCommand( - std::vector<std::string> const& args) +bool HandleSubstringCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 5) { - this->SetError("sub-command SUBSTRING requires four arguments."); + status.SetError("sub-command SUBSTRING requires four arguments."); return false; } @@ -529,25 +477,26 @@ bool cmStringCommand::HandleSubstringCommand( std::ostringstream ostr; ostr << "begin index: " << begin << " is out of range 0 - " << stringLength; - this->SetError(ostr.str()); + status.SetError(ostr.str()); return false; } if (end < -1) { std::ostringstream ostr; ostr << "end index: " << end << " should be -1 or greater"; - this->SetError(ostr.str()); + status.SetError(ostr.str()); return false; } - this->Makefile->AddDefinition(variableName, - stringValue.substr(begin, end).c_str()); + status.GetMakefile().AddDefinition(variableName, + stringValue.substr(begin, end)); return true; } -bool cmStringCommand::HandleLengthCommand(std::vector<std::string> const& args) +bool HandleLengthCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 3) { - this->SetError("sub-command LENGTH requires two arguments."); + status.SetError("sub-command LENGTH requires two arguments."); return false; } @@ -558,14 +507,15 @@ bool cmStringCommand::HandleLengthCommand(std::vector<std::string> const& args) char buffer[1024]; sprintf(buffer, "%d", static_cast<int>(length)); - this->Makefile->AddDefinition(variableName, buffer); + status.GetMakefile().AddDefinition(variableName, buffer); return true; } -bool cmStringCommand::HandleAppendCommand(std::vector<std::string> const& args) +bool HandleAppendCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 2) { - this->SetError("sub-command APPEND requires at least one argument."); + status.SetError("sub-command APPEND requires at least one argument."); return false; } @@ -577,20 +527,20 @@ bool cmStringCommand::HandleAppendCommand(std::vector<std::string> const& args) const std::string& variable = args[1]; std::string value; - const char* oldValue = this->Makefile->GetDefinition(variable); + const char* oldValue = status.GetMakefile().GetDefinition(variable); if (oldValue) { value = oldValue; } value += cmJoin(cmMakeRange(args).advance(2), std::string()); - this->Makefile->AddDefinition(variable, value.c_str()); + status.GetMakefile().AddDefinition(variable, value); return true; } -bool cmStringCommand::HandlePrependCommand( - std::vector<std::string> const& args) +bool HandlePrependCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 2) { - this->SetError("sub-command PREPEND requires at least one argument."); + status.SetError("sub-command PREPEND requires at least one argument."); return false; } @@ -602,67 +552,69 @@ bool cmStringCommand::HandlePrependCommand( const std::string& variable = args[1]; std::string value = cmJoin(cmMakeRange(args).advance(2), std::string()); - const char* oldValue = this->Makefile->GetDefinition(variable); + const char* oldValue = status.GetMakefile().GetDefinition(variable); if (oldValue) { value += oldValue; } - this->Makefile->AddDefinition(variable, value.c_str()); + status.GetMakefile().AddDefinition(variable, value); return true; } -bool cmStringCommand::HandleConcatCommand(std::vector<std::string> const& args) +bool HandleConcatCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 2) { - this->SetError("sub-command CONCAT requires at least one argument."); + status.SetError("sub-command CONCAT requires at least one argument."); return false; } - return this->joinImpl(args, std::string(), 1); + return joinImpl(args, std::string(), 1, status.GetMakefile()); } -bool cmStringCommand::HandleJoinCommand(std::vector<std::string> const& args) +bool HandleJoinCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 3) { - this->SetError("sub-command JOIN requires at least two arguments."); + status.SetError("sub-command JOIN requires at least two arguments."); return false; } - return this->joinImpl(args, args[1], 2); + return joinImpl(args, args[1], 2, status.GetMakefile()); } -bool cmStringCommand::joinImpl(std::vector<std::string> const& args, - std::string const& glue, const size_t varIdx) +bool joinImpl(std::vector<std::string> const& args, std::string const& glue, + const size_t varIdx, cmMakefile& makefile) { std::string const& variableName = args[varIdx]; // NOTE Items to concat/join placed right after the variable for // both `CONCAT` and `JOIN` sub-commands. std::string value = cmJoin(cmMakeRange(args).advance(varIdx + 1), glue); - this->Makefile->AddDefinition(variableName, value.c_str()); + makefile.AddDefinition(variableName, value); return true; } -bool cmStringCommand::HandleMakeCIdentifierCommand( - std::vector<std::string> const& args) +bool HandleMakeCIdentifierCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 3) { - this->SetError("sub-command MAKE_C_IDENTIFIER requires two arguments."); + status.SetError("sub-command MAKE_C_IDENTIFIER requires two arguments."); return false; } const std::string& input = args[1]; const std::string& variableName = args[2]; - this->Makefile->AddDefinition(variableName, - cmSystemTools::MakeCidentifier(input).c_str()); + status.GetMakefile().AddDefinition(variableName, + cmSystemTools::MakeCidentifier(input)); return true; } -bool cmStringCommand::HandleGenexStripCommand( - std::vector<std::string> const& args) +bool HandleGenexStripCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 3) { - this->SetError("sub-command GENEX_STRIP requires two arguments."); + status.SetError("sub-command GENEX_STRIP requires two arguments."); return false; } @@ -673,14 +625,15 @@ bool cmStringCommand::HandleGenexStripCommand( const std::string& variableName = args[2]; - this->Makefile->AddDefinition(variableName, result.c_str()); + status.GetMakefile().AddDefinition(variableName, result); return true; } -bool cmStringCommand::HandleStripCommand(std::vector<std::string> const& args) +bool HandleStripCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() != 3) { - this->SetError("sub-command STRIP requires two arguments."); + status.SetError("sub-command STRIP requires two arguments."); return false; } @@ -712,13 +665,16 @@ bool cmStringCommand::HandleStripCommand(std::vector<std::string> const& args) outLength = endPos - startPos + 1; } - this->Makefile->AddDefinition( - variableName, stringValue.substr(startPos, outLength).c_str()); + status.GetMakefile().AddDefinition(variableName, + stringValue.substr(startPos, outLength)); return true; } -bool cmStringCommand::HandleRepeatCommand(std::vector<std::string> const& args) +bool HandleRepeatCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { + cmMakefile& makefile = status.GetMakefile(); + // `string(REPEAT "<str>" <times> OUTPUT_VARIABLE)` enum ArgPos : std::size_t { @@ -730,16 +686,15 @@ bool cmStringCommand::HandleRepeatCommand(std::vector<std::string> const& args) }; if (args.size() != ArgPos::TOTAL_ARGS) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "sub-command REPEAT requires three arguments."); + makefile.IssueMessage(MessageType::FATAL_ERROR, + "sub-command REPEAT requires three arguments."); return true; } unsigned long times; - if (!cmSystemTools::StringToULong(args[ArgPos::TIMES].c_str(), ×)) { - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, - "repeat count is not a positive number."); + if (!cmStrToULong(args[ArgPos::TIMES], ×)) { + makefile.IssueMessage(MessageType::FATAL_ERROR, + "repeat count is not a positive number."); return true; } @@ -766,14 +721,15 @@ bool cmStringCommand::HandleRepeatCommand(std::vector<std::string> const& args) break; } - this->Makefile->AddDefinition(variableName, result.c_str()); + makefile.AddDefinition(variableName, result); return true; } -bool cmStringCommand::HandleRandomCommand(std::vector<std::string> const& args) +bool HandleRandomCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 2 || args.size() == 3 || args.size() == 5) { - this->SetError("sub-command RANDOM requires at least one argument."); + status.SetError("sub-command RANDOM requires at least one argument."); return false; } @@ -810,11 +766,11 @@ bool cmStringCommand::HandleRandomCommand(std::vector<std::string> const& args) double sizeofAlphabet = static_cast<double>(alphabet.size()); if (sizeofAlphabet < 1) { - this->SetError("sub-command RANDOM invoked with bad alphabet."); + status.SetError("sub-command RANDOM invoked with bad alphabet."); return false; } if (length < 1) { - this->SetError("sub-command RANDOM invoked with bad length."); + status.SetError("sub-command RANDOM invoked with bad length."); return false; } const std::string& variableName = args.back(); @@ -833,19 +789,19 @@ bool cmStringCommand::HandleRandomCommand(std::vector<std::string> const& args) } result.push_back(0); - this->Makefile->AddDefinition(variableName, result.data()); + status.GetMakefile().AddDefinition(variableName, result.data()); return true; } -bool cmStringCommand::HandleTimestampCommand( - std::vector<std::string> const& args) +bool HandleTimestampCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 2) { - this->SetError("sub-command TIMESTAMP requires at least one argument."); + status.SetError("sub-command TIMESTAMP requires at least one argument."); return false; } if (args.size() > 4) { - this->SetError("sub-command TIMESTAMP takes at most three arguments."); + status.SetError("sub-command TIMESTAMP takes at most three arguments."); return false; } @@ -865,25 +821,26 @@ bool cmStringCommand::HandleTimestampCommand( } else { std::string e = " TIMESTAMP sub-command does not recognize option " + args[argsIndex] + "."; - this->SetError(e); + status.SetError(e); return false; } } cmTimestamp timestamp; std::string result = timestamp.CurrentTime(formatString, utcFlag); - this->Makefile->AddDefinition(outputVariable, result.c_str()); + status.GetMakefile().AddDefinition(outputVariable, result); return true; } -bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args) +bool HandleUuidCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) unsigned int argsIndex = 1; if (args.size() < 2) { - this->SetError("UUID sub-command requires an output variable."); + status.SetError("UUID sub-command requires an output variable."); return false; } @@ -898,21 +855,21 @@ bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args) if (args[argsIndex] == "NAMESPACE") { ++argsIndex; if (argsIndex >= args.size()) { - this->SetError("UUID sub-command, NAMESPACE requires a value."); + status.SetError("UUID sub-command, NAMESPACE requires a value."); return false; } uuidNamespaceString = args[argsIndex++]; } else if (args[argsIndex] == "NAME") { ++argsIndex; if (argsIndex >= args.size()) { - this->SetError("UUID sub-command, NAME requires a value."); + status.SetError("UUID sub-command, NAME requires a value."); return false; } uuidName = args[argsIndex++]; } else if (args[argsIndex] == "TYPE") { ++argsIndex; if (argsIndex >= args.size()) { - this->SetError("UUID sub-command, TYPE requires a value."); + status.SetError("UUID sub-command, TYPE requires a value."); return false; } uuidType = args[argsIndex++]; @@ -922,7 +879,7 @@ bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args) } else { std::string e = "UUID sub-command does not recognize option " + args[argsIndex] + "."; - this->SetError(e); + status.SetError(e); return false; } } @@ -932,7 +889,7 @@ bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args) std::vector<unsigned char> uuidNamespace; if (!uuidGenerator.StringToBinary(uuidNamespaceString, uuidNamespace)) { - this->SetError("UUID sub-command, malformed NAMESPACE UUID."); + status.SetError("UUID sub-command, malformed NAMESPACE UUID."); return false; } @@ -942,12 +899,12 @@ bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args) uuid = uuidGenerator.FromSha1(uuidNamespace, uuidName); } else { std::string e = "UUID sub-command, unknown TYPE '" + uuidType + "'."; - this->SetError(e); + status.SetError(e); return false; } if (uuid.empty()) { - this->SetError("UUID sub-command, generation failed."); + status.SetError("UUID sub-command, generation failed."); return false; } @@ -955,12 +912,59 @@ bool cmStringCommand::HandleUuidCommand(std::vector<std::string> const& args) uuid = cmSystemTools::UpperCase(uuid); } - this->Makefile->AddDefinition(outputVariable, uuid.c_str()); + status.GetMakefile().AddDefinition(outputVariable, uuid); return true; #else std::ostringstream e; e << args[0] << " not available during bootstrap"; - this->SetError(e.str().c_str()); + status.SetError(e.str().c_str()); return false; #endif } + +} // namespace + +bool cmStringCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + if (args.empty()) { + status.SetError("must be called with at least one argument."); + return false; + } + + static cmSubcommandTable const subcommand{ + { "REGEX"_s, HandleRegexCommand }, + { "REPLACE"_s, HandleReplaceCommand }, + { "MD5"_s, HandleHashCommand }, + { "SHA1"_s, HandleHashCommand }, + { "SHA224"_s, HandleHashCommand }, + { "SHA256"_s, HandleHashCommand }, + { "SHA384"_s, HandleHashCommand }, + { "SHA512"_s, HandleHashCommand }, + { "SHA3_224"_s, HandleHashCommand }, + { "SHA3_256"_s, HandleHashCommand }, + { "SHA3_384"_s, HandleHashCommand }, + { "SHA3_512"_s, HandleHashCommand }, + { "TOLOWER"_s, HandleToLowerCommand }, + { "TOUPPER"_s, HandleToUpperCommand }, + { "COMPARE"_s, HandleCompareCommand }, + { "ASCII"_s, HandleAsciiCommand }, + { "CONFIGURE"_s, HandleConfigureCommand }, + { "LENGTH"_s, HandleLengthCommand }, + { "APPEND"_s, HandleAppendCommand }, + { "PREPEND"_s, HandlePrependCommand }, + { "CONCAT"_s, HandleConcatCommand }, + { "JOIN"_s, HandleJoinCommand }, + { "SUBSTRING"_s, HandleSubstringCommand }, + { "STRIP"_s, HandleStripCommand }, + { "REPEAT"_s, HandleRepeatCommand }, + { "RANDOM"_s, HandleRandomCommand }, + { "FIND"_s, HandleFindCommand }, + { "TIMESTAMP"_s, HandleTimestampCommand }, + { "MAKE_C_IDENTIFIER"_s, HandleMakeCIdentifierCommand }, + { "GENEX_STRIP"_s, HandleGenexStripCommand }, + { "UUID"_s, HandleUuidCommand }, + }; + + return subcommand(args[0], args, status); +} diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h index acde605..bd71ba2 100644 --- a/Source/cmStringCommand.h +++ b/Source/cmStringCommand.h @@ -5,62 +5,16 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <cstddef> #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmStringCommand +/** * \brief Common string operations * */ -class cmStringCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmStringCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -protected: - bool HandleConfigureCommand(std::vector<std::string> const& args); - bool HandleAsciiCommand(std::vector<std::string> const& args); - bool HandleRegexCommand(std::vector<std::string> const& args); - bool RegexMatch(std::vector<std::string> const& args); - bool RegexMatchAll(std::vector<std::string> const& args); - bool RegexReplace(std::vector<std::string> const& args); - bool HandleHashCommand(std::vector<std::string> const& args); - bool HandleToUpperLowerCommand(std::vector<std::string> const& args, - bool toUpper); - bool HandleCompareCommand(std::vector<std::string> const& args); - bool HandleReplaceCommand(std::vector<std::string> const& args); - bool HandleLengthCommand(std::vector<std::string> const& args); - bool HandleSubstringCommand(std::vector<std::string> const& args); - bool HandleAppendCommand(std::vector<std::string> const& args); - bool HandlePrependCommand(std::vector<std::string> const& args); - bool HandleConcatCommand(std::vector<std::string> const& args); - bool HandleJoinCommand(std::vector<std::string> const& args); - bool HandleStripCommand(std::vector<std::string> const& args); - bool HandleRepeatCommand(std::vector<std::string> const& args); - bool HandleRandomCommand(std::vector<std::string> const& args); - bool HandleFindCommand(std::vector<std::string> const& args); - bool HandleTimestampCommand(std::vector<std::string> const& args); - bool HandleMakeCIdentifierCommand(std::vector<std::string> const& args); - bool HandleGenexStripCommand(std::vector<std::string> const& args); - bool HandleUuidCommand(std::vector<std::string> const& args); - - bool joinImpl(std::vector<std::string> const& args, std::string const& glue, - size_t varIdx); -}; +bool cmStringCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmSubcommandTable.cxx b/Source/cmSubcommandTable.cxx new file mode 100644 index 0000000..f6194f8 --- /dev/null +++ b/Source/cmSubcommandTable.cxx @@ -0,0 +1,31 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmSubcommandTable.h" + +#include <algorithm> + +#include "cmExecutionStatus.h" +#include "cmStringAlgorithms.h" + +cmSubcommandTable::cmSubcommandTable(std::initializer_list<InitElem> init) + : Impl(init.begin(), init.end()) +{ + std::sort(this->Impl.begin(), this->Impl.end(), + [](Elem const& left, Elem const& right) { + return left.first < right.first; + }); +} + +bool cmSubcommandTable::operator()(cm::string_view key, + std::vector<std::string> const& args, + cmExecutionStatus& status) const +{ + auto const it = std::lower_bound( + this->Impl.begin(), this->Impl.end(), key, + [](Elem const& elem, cm::string_view k) { return elem.first < k; }); + if (it != this->Impl.end() && it->first == key) { + return it->second(args, status); + } + status.SetError(cmStrCat("does not recognize sub-command ", key)); + return false; +} diff --git a/Source/cmSubcommandTable.h b/Source/cmSubcommandTable.h new file mode 100644 index 0000000..21342bb --- /dev/null +++ b/Source/cmSubcommandTable.h @@ -0,0 +1,36 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmSubcommandTable_h +#define cmSubcommandTable_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cm_static_string_view.hxx" +#include "cm_string_view.hxx" + +#include <initializer_list> +#include <string> +#include <utility> +#include <vector> + +class cmExecutionStatus; + +class cmSubcommandTable +{ +public: + using Command = bool (*)(std::vector<std::string> const&, + cmExecutionStatus&); + + using Elem = std::pair<cm::string_view, Command>; + using InitElem = std::pair<cm::static_string_view, Command>; + + cmSubcommandTable(std::initializer_list<InitElem> init); + + bool operator()(cm::string_view key, std::vector<std::string> const& args, + cmExecutionStatus& status) const; + +private: + std::vector<Elem> Impl; +}; + +#endif diff --git a/Source/cmSubdirCommand.cxx b/Source/cmSubdirCommand.cxx index 9d36228..07f8efe 100644 --- a/Source/cmSubdirCommand.cxx +++ b/Source/cmSubdirCommand.cxx @@ -3,6 +3,7 @@ #include "cmSubdirCommand.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmExecutionStatus; @@ -44,8 +45,8 @@ bool cmSubdirCommand::InitialPass(std::vector<std::string> const& args, cmSystemTools::GetFilenameName(i); this->Makefile->AddSubDirectory(i, binPath, excludeFromAll, false); } else { - std::string error = "Incorrect SUBDIRS command. Directory: "; - error += i + " does not exist."; + std::string error = cmStrCat("Incorrect SUBDIRS command. Directory: ", i, + " does not exist."); this->SetError(error); res = false; } diff --git a/Source/cmSubdirCommand.h b/Source/cmSubdirCommand.h index adab757..3499c46 100644 --- a/Source/cmSubdirCommand.h +++ b/Source/cmSubdirCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -25,7 +27,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmSubdirCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmSubdirCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmSubdirDependsCommand.h b/Source/cmSubdirDependsCommand.h index 2db28c6..64c28b9 100644 --- a/Source/cmSubdirDependsCommand.h +++ b/Source/cmSubdirDependsCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -15,7 +17,10 @@ class cmExecutionStatus; class cmSubdirDependsCommand : public cmCommand { public: - cmCommand* Clone() override { return new cmSubdirDependsCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmSubdirDependsCommand>(); + } bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; }; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 1501481..b7287d9 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -6,9 +6,10 @@ #include "cmDuration.h" #include "cmProcessOutput.h" #include "cmRange.h" +#include "cmStringAlgorithms.h" #include "cm_uv.h" -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) # include "cmArchiveWrite.h" # include "cmLocale.h" # include "cm_libarchive.h" @@ -20,7 +21,7 @@ # endif #endif -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) # include "cmCryptoHash.h" #endif @@ -83,11 +84,6 @@ cmSystemTools::OutputCallback s_StdoutCallback; } // namespace -static bool cm_isspace(char c) -{ - return ((c & 0x80) == 0) && isspace(c); -} - #if !defined(HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE) // For GetEnvironmentVariables # if defined(_WIN32) @@ -97,7 +93,7 @@ extern char** environ; # endif #endif -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) static std::string cm_archive_entry_pathname(struct archive_entry* entry) { # if cmsys_STL_HAS_WSTRING @@ -151,12 +147,10 @@ void cmSystemTools::ExpandRegistryValues(std::string& source, KeyWOW64 view) std::string key = regEntry.match(1); std::string val; if (ReadRegistryValue(key.c_str(), val, view)) { - std::string reg = "["; - reg += key + "]"; + std::string reg = cmStrCat('[', key, ']'); cmSystemTools::ReplaceString(source, reg.c_str(), val.c_str()); } else { - std::string reg = "["; - reg += key + "]"; + std::string reg = cmStrCat('[', key, ']'); cmSystemTools::ReplaceString(source, reg.c_str(), "/registry"); } } @@ -169,49 +163,20 @@ void cmSystemTools::ExpandRegistryValues(std::string& source, while (regEntry.find(source)) { // the arguments are the second match std::string key = regEntry.match(1); - std::string reg = "["; - reg += key + "]"; + std::string reg = cmStrCat('[', key, ']'); cmSystemTools::ReplaceString(source, reg.c_str(), "/registry"); } } #endif -std::string cmSystemTools::EscapeQuotes(const std::string& str) -{ - std::string result; - result.reserve(str.size()); - for (const char* ch = str.c_str(); *ch != '\0'; ++ch) { - if (*ch == '"') { - result += '\\'; - } - result += *ch; - } - return result; -} - -std::string cmSystemTools::HelpFileName(std::string name) +std::string cmSystemTools::HelpFileName(cm::string_view str) { + std::string name(str); cmSystemTools::ReplaceString(name, "<", ""); cmSystemTools::ReplaceString(name, ">", ""); return name; } -std::string cmSystemTools::TrimWhitespace(const std::string& s) -{ - std::string::const_iterator start = s.begin(); - while (start != s.end() && cm_isspace(*start)) { - ++start; - } - if (start == s.end()) { - return ""; - } - std::string::const_iterator stop = s.end() - 1; - while (cm_isspace(*stop)) { - --stop; - } - return std::string(start, stop + 1); -} - void cmSystemTools::Error(const std::string& m) { std::string message = "CMake Error: " + m; @@ -276,121 +241,11 @@ void cmSystemTools::Message(const std::string& m, const char* title) void cmSystemTools::ReportLastSystemError(const char* msg) { - std::string m = msg; - m += ": System Error: "; - m += Superclass::GetLastSystemError(); + std::string m = + cmStrCat(msg, ": System Error: ", Superclass::GetLastSystemError()); cmSystemTools::Error(m); } -bool cmSystemTools::IsInternallyOn(const char* val) -{ - if (!val) { - return false; - } - std::string v = val; - if (v.size() > 4) { - return false; - } - - for (char& c : v) { - c = static_cast<char>(toupper(c)); - } - return v == "I_ON"; -} - -bool cmSystemTools::IsOn(const char* val) -{ - if (!val) { - return false; - } - /* clang-format off */ - // "1" - if (val[0] == '1' && val[1] == '\0') { - return true; - } - // "ON" - if ((val[0] == 'O' || val[0] == 'o') && - (val[1] == 'N' || val[1] == 'n') && val[2] == '\0') { - return true; - } - // "Y", "YES" - if ((val[0] == 'Y' || val[0] == 'y') && (val[1] == '\0' || ( - (val[1] == 'E' || val[1] == 'e') && - (val[2] == 'S' || val[2] == 's') && val[3] == '\0'))) { - return true; - } - // "TRUE" - if ((val[0] == 'T' || val[0] == 't') && - (val[1] == 'R' || val[1] == 'r') && - (val[2] == 'U' || val[2] == 'u') && - (val[3] == 'E' || val[3] == 'e') && val[4] == '\0') { - return true; - } - /* clang-format on */ - return false; -} - -bool cmSystemTools::IsOn(const std::string& val) -{ - return cmSystemTools::IsOn(val.c_str()); -} - -bool cmSystemTools::IsNOTFOUND(const char* val) -{ - if (strcmp(val, "NOTFOUND") == 0) { - return true; - } - return cmHasLiteralSuffix(val, "-NOTFOUND"); -} - -bool cmSystemTools::IsOff(const char* val) -{ - // "" - if (!val || val[0] == '\0') { - return true; - } - /* clang-format off */ - // "0" - if (val[0] == '0' && val[1] == '\0') { - return true; - } - // "OFF" - if ((val[0] == 'O' || val[0] == 'o') && - (val[1] == 'F' || val[1] == 'f') && - (val[2] == 'F' || val[2] == 'f') && val[3] == '\0') { - return true; - } - // "N", "NO" - if ((val[0] == 'N' || val[0] == 'n') && (val[1] == '\0' || ( - (val[1] == 'O' || val[1] == 'o') && val[2] == '\0'))) { - return true; - } - // "FALSE" - if ((val[0] == 'F' || val[0] == 'f') && - (val[1] == 'A' || val[1] == 'a') && - (val[2] == 'L' || val[2] == 'l') && - (val[3] == 'S' || val[3] == 's') && - (val[4] == 'E' || val[4] == 'e') && val[5] == '\0') { - return true; - } - // "IGNORE" - if ((val[0] == 'I' || val[0] == 'i') && - (val[1] == 'G' || val[1] == 'g') && - (val[2] == 'N' || val[2] == 'n') && - (val[3] == 'O' || val[3] == 'o') && - (val[4] == 'R' || val[4] == 'r') && - (val[5] == 'E' || val[5] == 'e') && val[6] == '\0') { - return true; - } - /* clang-format on */ - return cmSystemTools::IsNOTFOUND(val); -} - -bool cmSystemTools::IsOff(const std::string& val) -{ - return cmSystemTools::IsOff(val.c_str()); -} - void cmSystemTools::ParseWindowsCommandLine(const char* command, std::vector<std::string>& args) { @@ -424,7 +279,7 @@ void cmSystemTools::ParseWindowsCommandLine(const char* command, } else { arg.append(backslashes, '\\'); backslashes = 0; - if (cm_isspace(*c)) { + if (cmIsSpace(*c)) { if (in_quotes) { arg.append(1, *c); } else if (in_argument) { @@ -487,10 +342,9 @@ std::vector<std::string> cmSystemTools::HandleResponseFile( if (cmHasLiteralPrefix(arg, "@")) { cmsys::ifstream responseFile(arg.substr(1).c_str(), std::ios::in); if (!responseFile) { - std::string error = "failed to open for reading ("; - error += cmSystemTools::GetLastSystemError(); - error += "):\n "; - error += arg.substr(1); + std::string error = cmStrCat("failed to open for reading (", + cmSystemTools::GetLastSystemError(), + "):\n ", cm::string_view(arg).substr(1)); cmSystemTools::Error(error); } else { std::string line; @@ -843,9 +697,7 @@ bool cmSystemTools::DoesFileExistWithExtensions( std::string hname; for (std::string const& headerExt : headerExts) { - hname = name; - hname += "."; - hname += headerExt; + hname = cmStrCat(name, '.', headerExt); if (cmSystemTools::FileExists(hname)) { return true; } @@ -863,7 +715,7 @@ std::string cmSystemTools::FileExistsInParentDirectories( cmSystemTools::ConvertToUnixSlashes(dir); std::string prevDir; while (dir != prevDir) { - std::string path = dir + "/" + file; + std::string path = cmStrCat(dir, "/", file); if (cmSystemTools::FileExists(path)) { return path; } @@ -1006,7 +858,7 @@ bool cmSystemTools::RenameFile(const std::string& oldname, std::string cmSystemTools::ComputeFileHash(const std::string& source, cmCryptoHash::Algo algo) { -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) cmCryptoHash hash(algo); return hash.HashFile(source); #else @@ -1019,7 +871,7 @@ std::string cmSystemTools::ComputeFileHash(const std::string& source, std::string cmSystemTools::ComputeStringMD5(const std::string& input) { -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) cmCryptoHash md5(cmCryptoHash::AlgoMD5); return md5.HashString(input); #else @@ -1035,7 +887,7 @@ std::string cmSystemTools::ComputeCertificateThumbprint( { std::string thumbprint; -#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32) +#if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32) BYTE* certData = NULL; CRYPT_INTEGER_BLOB cryptBlob; HCERTSTORE certStore = NULL; @@ -1139,9 +991,7 @@ void cmSystemTools::GlobDirs(const std::string& path, for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i) { if ((std::string(d.GetFile(i)) != ".") && (std::string(d.GetFile(i)) != "..")) { - std::string fname = startPath; - fname += "/"; - fname += d.GetFile(i); + std::string fname = cmStrCat(startPath, '/', d.GetFile(i)); if (cmSystemTools::FileIsDirectory(fname)) { fname += finishPath; cmSystemTools::GlobDirs(fname, files); @@ -1151,75 +1001,6 @@ void cmSystemTools::GlobDirs(const std::string& path, } } -void cmSystemTools::ExpandListArgument(const std::string& arg, - std::vector<std::string>& argsOut, - bool emptyArgs) -{ - // If argument is empty, it is an empty list. - if (!emptyArgs && arg.empty()) { - return; - } - // if there are no ; in the name then just copy the current string - if (arg.find(';') == std::string::npos) { - argsOut.push_back(arg); - return; - } - std::string newArg; - const char* last = arg.c_str(); - // Break the string at non-escaped semicolons not nested in []. - int squareNesting = 0; - for (const char* c = last; *c; ++c) { - switch (*c) { - case '\\': { - // We only want to allow escaping of semicolons. Other - // escapes should not be processed here. - const char* next = c + 1; - if (*next == ';') { - newArg.append(last, c - last); - // Skip over the escape character - last = c = next; - } - } break; - case '[': { - ++squareNesting; - } break; - case ']': { - --squareNesting; - } break; - case ';': { - // Break the string here if we are not nested inside square - // brackets. - if (squareNesting == 0) { - newArg.append(last, c - last); - // Skip over the semicolon - last = c + 1; - if (!newArg.empty() || emptyArgs) { - // Add the last argument if the string is not empty. - argsOut.push_back(newArg); - newArg.clear(); - } - } - } break; - default: { - // Just append this character. - } break; - } - } - newArg.append(last); - if (!newArg.empty() || emptyArgs) { - // Add the last argument if the string is not empty. - argsOut.push_back(newArg); - } -} - -std::vector<std::string> cmSystemTools::ExpandedListArgument( - const std::string& arg, bool emptyArgs) -{ - std::vector<std::string> argsOut; - ExpandListArgument(arg, argsOut, emptyArgs); - return argsOut; -} - bool cmSystemTools::SimpleGlob(const std::string& glob, std::vector<std::string>& files, int type /* = 0 */) @@ -1264,65 +1045,6 @@ bool cmSystemTools::SimpleGlob(const std::string& glob, return res; } -cmSystemTools::FileFormat cmSystemTools::GetFileFormat(std::string const& ext) -{ - if (ext.empty()) { - return cmSystemTools::NO_FILE_FORMAT; - } - if (ext == "c" || ext == ".c" || ext == "m" || ext == ".m") { - return cmSystemTools::C_FILE_FORMAT; - } - if (ext == "C" || ext == ".C" || ext == "M" || ext == ".M" || ext == "c++" || - ext == ".c++" || ext == "cc" || ext == ".cc" || ext == "cpp" || - ext == ".cpp" || ext == "cxx" || ext == ".cxx" || ext == "mm" || - ext == ".mm") { - return cmSystemTools::CXX_FILE_FORMAT; - } - if (ext == "f" || ext == ".f" || ext == "F" || ext == ".F" || ext == "f77" || - ext == ".f77" || ext == "f90" || ext == ".f90" || ext == "for" || - ext == ".for" || ext == "f95" || ext == ".f95") { - return cmSystemTools::FORTRAN_FILE_FORMAT; - } - if (ext == "java" || ext == ".java") { - return cmSystemTools::JAVA_FILE_FORMAT; - } - if (ext == "cu" || ext == ".cu") { - return cmSystemTools::CUDA_FILE_FORMAT; - } - if (ext == "H" || ext == ".H" || ext == "h" || ext == ".h" || ext == "h++" || - ext == ".h++" || ext == "hm" || ext == ".hm" || ext == "hpp" || - ext == ".hpp" || ext == "hxx" || ext == ".hxx" || ext == "in" || - ext == ".in" || ext == "txx" || ext == ".txx") { - return cmSystemTools::HEADER_FILE_FORMAT; - } - if (ext == "rc" || ext == ".rc") { - return cmSystemTools::RESOURCE_FILE_FORMAT; - } - if (ext == "def" || ext == ".def") { - return cmSystemTools::DEFINITION_FILE_FORMAT; - } - if (ext == "lib" || ext == ".lib" || ext == "a" || ext == ".a") { - return cmSystemTools::STATIC_LIBRARY_FILE_FORMAT; - } - if (ext == "o" || ext == ".o" || ext == "obj" || ext == ".obj") { - return cmSystemTools::OBJECT_FILE_FORMAT; - } -#ifdef __APPLE__ - if (ext == "dylib" || ext == ".dylib") { - return cmSystemTools::SHARED_LIBRARY_FILE_FORMAT; - } - if (ext == "so" || ext == ".so" || ext == "bundle" || ext == ".bundle") { - return cmSystemTools::MODULE_FILE_FORMAT; - } -#else // __APPLE__ - if (ext == "so" || ext == ".so" || ext == "sl" || ext == ".sl" || - ext == "dll" || ext == ".dll") { - return cmSystemTools::SHARED_LIBRARY_FILE_FORMAT; - } -#endif // __APPLE__ - return cmSystemTools::UNKNOWN_FILE_FORMAT; -} - std::string cmSystemTools::ConvertToOutputPath(std::string const& path) { #if defined(_WIN32) && !defined(__CYGWIN__) @@ -1448,12 +1170,11 @@ std::string cmSystemTools::ForceToRelativePath(std::string const& local_path, return relative; } -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP bool cmSystemTools::UnsetEnv(const char* value) { # if !defined(HAVE_UNSETENV) - std::string var = value; - var += "="; + std::string var = cmStrCat(value, '='); return cmSystemTools::PutEnv(var.c_str()); # else unsetenv(value); @@ -1513,7 +1234,7 @@ void cmSystemTools::EnableVSConsoleOutput() // output and allow it to be captured on the fly. cmSystemTools::PutEnv("vsconsoleoutput=1"); -# ifdef CMAKE_BUILD_WITH_CMAKE +# ifndef CMAKE_BOOTSTRAP // VS sets an environment variable to tell MS tools like "cl" to report // output through a backdoor pipe instead of stdout/stderr. Unset the // environment variable to close this backdoor for any path of process @@ -1535,14 +1256,12 @@ bool cmSystemTools::CreateTar(const std::string& outFileName, std::string const& mtime, std::string const& format) { -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); cmsys::ofstream fout(outFileName.c_str(), std::ios::out | std::ios::binary); if (!fout) { - std::string e = "Cannot open output file \""; - e += outFileName; - e += "\": "; - e += cmSystemTools::GetLastSystemError(); + std::string e = cmStrCat("Cannot open output file \"", outFileName, + "\": ", cmSystemTools::GetLastSystemError()); cmSystemTools::Error(e); return false; } @@ -1589,7 +1308,7 @@ bool cmSystemTools::CreateTar(const std::string& outFileName, #endif } -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) namespace { # define BSDTAR_FILESIZE_PRINTF "%lu" # define BSDTAR_FILESIZE_TYPE unsigned long @@ -1885,7 +1604,7 @@ bool cmSystemTools::ExtractTar(const std::string& outFileName, const std::vector<std::string>& files, bool verbose) { -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) return extract_tar(outFileName, files, verbose, true); #else (void)outFileName; @@ -1899,7 +1618,7 @@ bool cmSystemTools::ListTar(const std::string& outFileName, const std::vector<std::string>& files, bool verbose) { -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) return extract_tar(outFileName, files, verbose, false); #else (void)outFileName; @@ -2225,40 +1944,34 @@ void cmSystemTools::FindCMakeResources(const char* argv0) } #endif exe_dir = cmSystemTools::GetActualCaseForPath(exe_dir); - cmSystemToolsCMakeCommand = exe_dir; - cmSystemToolsCMakeCommand += "/cmake"; - cmSystemToolsCMakeCommand += cmSystemTools::GetExecutableExtension(); -#ifndef CMAKE_BUILD_WITH_CMAKE + cmSystemToolsCMakeCommand = + cmStrCat(exe_dir, "/cmake", cmSystemTools::GetExecutableExtension()); +#ifdef CMAKE_BOOTSTRAP // The bootstrap cmake does not provide the other tools, // so use the directory where they are about to be built. exe_dir = CMAKE_BOOTSTRAP_BINARY_DIR "/bin"; #endif - cmSystemToolsCTestCommand = exe_dir; - cmSystemToolsCTestCommand += "/ctest"; - cmSystemToolsCTestCommand += cmSystemTools::GetExecutableExtension(); - cmSystemToolsCPackCommand = exe_dir; - cmSystemToolsCPackCommand += "/cpack"; - cmSystemToolsCPackCommand += cmSystemTools::GetExecutableExtension(); - cmSystemToolsCMakeGUICommand = exe_dir; - cmSystemToolsCMakeGUICommand += "/cmake-gui"; - cmSystemToolsCMakeGUICommand += cmSystemTools::GetExecutableExtension(); + cmSystemToolsCTestCommand = + cmStrCat(exe_dir, "/ctest", cmSystemTools::GetExecutableExtension()); + cmSystemToolsCPackCommand = + cmStrCat(exe_dir, "/cpack", cmSystemTools::GetExecutableExtension()); + cmSystemToolsCMakeGUICommand = + cmStrCat(exe_dir, "/cmake-gui", cmSystemTools::GetExecutableExtension()); if (!cmSystemTools::FileExists(cmSystemToolsCMakeGUICommand)) { cmSystemToolsCMakeGUICommand.clear(); } - cmSystemToolsCMakeCursesCommand = exe_dir; - cmSystemToolsCMakeCursesCommand += "/ccmake"; - cmSystemToolsCMakeCursesCommand += cmSystemTools::GetExecutableExtension(); + cmSystemToolsCMakeCursesCommand = + cmStrCat(exe_dir, "/ccmake", cmSystemTools::GetExecutableExtension()); if (!cmSystemTools::FileExists(cmSystemToolsCMakeCursesCommand)) { cmSystemToolsCMakeCursesCommand.clear(); } - cmSystemToolsCMClDepsCommand = exe_dir; - cmSystemToolsCMClDepsCommand += "/cmcldeps"; - cmSystemToolsCMClDepsCommand += cmSystemTools::GetExecutableExtension(); + cmSystemToolsCMClDepsCommand = + cmStrCat(exe_dir, "/cmcldeps", cmSystemTools::GetExecutableExtension()); if (!cmSystemTools::FileExists(cmSystemToolsCMClDepsCommand)) { cmSystemToolsCMClDepsCommand.clear(); } -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP // Install tree has // - "<prefix><CMAKE_BIN_DIR>/cmake" // - "<prefix><CMAKE_DATA_DIR>" @@ -2456,7 +2169,8 @@ struct cmSystemToolsRPathInfo #if defined(CMAKE_USE_ELF_PARSER) bool cmSystemTools::ChangeRPath(std::string const& file, std::string const& oldRPath, - std::string const& newRPath, std::string* emsg, + std::string const& newRPath, + bool removeEnvironmentRPath, std::string* emsg, bool* changed) { if (changed) { @@ -2490,8 +2204,9 @@ bool cmSystemTools::ChangeRPath(std::string const& file, return true; } if (emsg) { - *emsg = "No valid ELF RPATH or RUNPATH entry exists in the file; "; - *emsg += elf.GetErrorMessage(); + *emsg = + cmStrCat("No valid ELF RPATH or RUNPATH entry exists in the file; ", + elf.GetErrorMessage()); } return false; } @@ -2543,7 +2258,9 @@ bool cmSystemTools::ChangeRPath(std::string const& file, // Construct the new value which preserves the part of the path // not being changed. - rp[rp_count].Value = se[i]->Value.substr(0, prefix_len); + if (!removeEnvironmentRPath) { + rp[rp_count].Value = se[i]->Value.substr(0, prefix_len); + } rp[rp_count].Value += newRPath; rp[rp_count].Value += se[i]->Value.substr(pos + oldRPath.length()); @@ -2555,9 +2272,8 @@ bool cmSystemTools::ChangeRPath(std::string const& file, // least one null terminator. if (rp[rp_count].Size < rp[rp_count].Value.length() + 1) { if (emsg) { - *emsg = "The replacement path is too long for the "; - *emsg += se_name[i]; - *emsg += " entry."; + *emsg = cmStrCat("The replacement path is too long for the ", + se_name[i], " entry."); } return false; } @@ -2593,9 +2309,7 @@ bool cmSystemTools::ChangeRPath(std::string const& file, // Seek to the RPATH position. if (!f.seekp(rp[i].Position)) { if (emsg) { - *emsg = "Error seeking to "; - *emsg += rp[i].Name; - *emsg += " position."; + *emsg = cmStrCat("Error seeking to ", rp[i].Name, " position."); } return false; } @@ -2610,9 +2324,8 @@ bool cmSystemTools::ChangeRPath(std::string const& file, // Make sure it wrote correctly. if (!f) { if (emsg) { - *emsg = "Error writing the new "; - *emsg += rp[i].Name; - *emsg += " string to the file."; + *emsg = cmStrCat("Error writing the new ", rp[i].Name, + " string to the file."); } return false; } @@ -2629,6 +2342,7 @@ bool cmSystemTools::ChangeRPath(std::string const& file, bool cmSystemTools::ChangeRPath(std::string const& /*file*/, std::string const& /*oldRPath*/, std::string const& /*newRPath*/, + bool /*removeEnvironmentRPath*/, std::string* /*emsg*/, bool* /*changed*/) { return false; @@ -2640,7 +2354,8 @@ bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op, { const char* endl = lhss; const char* endr = rhss; - unsigned long lhs, rhs; + unsigned long lhs; + unsigned long rhs; while (((*endl >= '0') && (*endl <= '9')) || ((*endr >= '0') && (*endr <= '9'))) { @@ -2951,61 +2666,20 @@ bool cmSystemTools::CheckRPath(std::string const& file, bool cmSystemTools::RepeatedRemoveDirectory(const std::string& dir) { +#ifdef _WIN32 // Windows sometimes locks files temporarily so try a few times. - for (int i = 0; i < 10; ++i) { + WindowsFileRetry retry = cmSystemTools::GetWindowsFileRetry(); + + for (unsigned int i = 0; i < retry.Count; ++i) { if (cmSystemTools::RemoveADirectory(dir)) { return true; } - cmSystemTools::Delay(100); + cmSystemTools::Delay(retry.Delay); } return false; -} - -std::vector<std::string> cmSystemTools::tokenize(const std::string& str, - const std::string& sep) -{ - std::vector<std::string> tokens; - std::string::size_type tokend = 0; - - do { - std::string::size_type tokstart = str.find_first_not_of(sep, tokend); - if (tokstart == std::string::npos) { - break; // no more tokens - } - tokend = str.find_first_of(sep, tokstart); - if (tokend == std::string::npos) { - tokens.push_back(str.substr(tokstart)); - } else { - tokens.push_back(str.substr(tokstart, tokend - tokstart)); - } - } while (tokend != std::string::npos); - - if (tokens.empty()) { - tokens.emplace_back(); - } - return tokens; -} - -bool cmSystemTools::StringToLong(const char* str, long* value) -{ - errno = 0; - char* endp; - *value = strtol(str, &endp, 10); - return (*endp == '\0') && (endp != str) && (errno == 0); -} - -bool cmSystemTools::StringToULong(const char* str, unsigned long* value) -{ - errno = 0; - char* endp; - while (isspace(*str)) { - ++str; - } - if (*str == '-') { - return false; - } - *value = strtoul(str, &endp, 10); - return (*endp == '\0') && (endp != str) && (errno == 0); +#else + return cmSystemTools::RemoveADirectory(dir); +#endif } std::string cmSystemTools::EncodeURL(std::string const& in, bool escapeSlashes) diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 016c266..953a358 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -8,6 +8,7 @@ #include "cmCryptoHash.h" #include "cmDuration.h" #include "cmProcessOutput.h" +#include "cm_string_view.hxx" #include "cmsys/Process.h" #include "cmsys/SystemTools.hxx" // IWYU pragma: export #include <functional> @@ -28,64 +29,13 @@ public: typedef cmProcessOutput::Encoding Encoding; /** - * Expand the ; separated string @a arg into multiple arguments. - * All found arguments are appended to @a argsOut. - */ - static void ExpandListArgument(const std::string& arg, - std::vector<std::string>& argsOut, - bool emptyArgs = false); - - /** - * Expand out any arguments in the string range [@a first, @a last) that have - * ; separated strings into multiple arguments. All found arguments are - * appended to @a argsOut. - */ - template <class InputIt> - static void ExpandLists(InputIt first, InputIt last, - std::vector<std::string>& argsOut) - { - for (; first != last; ++first) { - cmSystemTools::ExpandListArgument(*first, argsOut); - } - } - - /** - * Same as ExpandListArgument but a new vector is created containing - * the expanded arguments from the string @a arg. - */ - static std::vector<std::string> ExpandedListArgument(const std::string& arg, - bool emptyArgs = false); - - /** - * Same as ExpandList but a new vector is created containing the expanded - * versions of all arguments in the string range [@a first, @a last). - */ - template <class InputIt> - static std::vector<std::string> ExpandedLists(InputIt first, InputIt last) - { - std::vector<std::string> argsOut; - for (; first != last; ++first) { - cmSystemTools::ExpandListArgument(*first, argsOut); - } - return argsOut; - } - - /** * Look for and replace registry values in a string */ static void ExpandRegistryValues(std::string& source, KeyWOW64 view = KeyWOW64_Default); - //! Escape quotes in a string. - static std::string EscapeQuotes(const std::string& str); - /** Map help document name to file name. */ - static std::string HelpFileName(std::string); - - /** - * Returns a string that has whitespace removed from the start and the end. - */ - static std::string TrimWhitespace(const std::string& s); + static std::string HelpFileName(cm::string_view); using MessageCallback = std::function<void(const std::string&, const char*)>; /** @@ -144,31 +94,6 @@ public: cmSystemTools::s_ErrorOccured = false; } - /** - * Does a string indicates that CMake/CPack/CTest internally - * forced this value. This is not the same as On, but this - * may be considered as "internally switched on". - */ - static bool IsInternallyOn(const char* val); - /** - * does a string indicate a true or on value ? This is not the same - * as ifdef. - */ - static bool IsOn(const char* val); - static bool IsOn(const std::string& val); - - /** - * does a string indicate a false or off value ? Note that this is - * not the same as !IsOn(...) because there are a number of - * ambiguous values such as "/usr/local/bin" a path will result in - * IsON and IsOff both returning false. Note that the special path - * NOTFOUND, *-NOTFOUND or IGNORE will cause IsOff to return true. - */ - static bool IsOff(const char* val); - static bool IsOff(const std::string& val); - - //! Return true if value is NOTFOUND or ends in -NOTFOUND. - static bool IsNOTFOUND(const char* value); //! Return true if the path is a framework static bool IsPathToFramework(const std::string& value); @@ -299,27 +224,6 @@ public: static void EnableRunCommandOutput() { s_DisableRunCommandOutput = false; } static bool GetRunCommandOutput() { return s_DisableRunCommandOutput; } - /** - * Some constants for different file formats. - */ - enum FileFormat - { - NO_FILE_FORMAT = 0, - C_FILE_FORMAT, - CXX_FILE_FORMAT, - FORTRAN_FILE_FORMAT, - JAVA_FILE_FORMAT, - CUDA_FILE_FORMAT, - HEADER_FILE_FORMAT, - RESOURCE_FILE_FORMAT, - DEFINITION_FILE_FORMAT, - STATIC_LIBRARY_FILE_FORMAT, - SHARED_LIBRARY_FILE_FORMAT, - MODULE_FILE_FORMAT, - OBJECT_FILE_FORMAT, - UNKNOWN_FILE_FORMAT - }; - enum CompareOp { OP_EQUAL = 1, @@ -350,11 +254,6 @@ public: */ static int strverscmp(std::string const& lhs, std::string const& rhs); - /** - * Determine the file type based on the extension - */ - static FileFormat GetFileFormat(std::string const& ext); - /** Windows if this is true, the CreateProcess in RunCommand will * not show new console windows when running programs. */ @@ -401,7 +300,7 @@ public: static std::string ForceToRelativePath(std::string const& local_path, std::string const& remote_path); -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP /** Remove an environment variable */ static bool UnsetEnv(const char* value); @@ -499,6 +398,7 @@ public: /** Try to set the RPATH in an ELF binary. */ static bool ChangeRPath(std::string const& file, std::string const& oldRPath, std::string const& newRPath, + bool removeEnvironmentRPath, std::string* emsg = nullptr, bool* changed = nullptr); @@ -513,14 +413,6 @@ public: /** Remove a directory; repeat a few times in case of locked files. */ static bool RepeatedRemoveDirectory(const std::string& dir); - /** Tokenize a string */ - static std::vector<std::string> tokenize(const std::string& str, - const std::string& sep); - - /** Convert string to long. Expected that the whole string is an integer */ - static bool StringToLong(const char* str, long* value); - static bool StringToULong(const char* str, unsigned long* value); - /** Encode a string as a URL. */ static std::string EncodeURL(std::string const& in, bool escapeSlashes = true); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index a67122c..df37d32 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -12,6 +12,8 @@ #include <string.h> #include <unordered_set> +#include "cm_memory.hxx" + #include "cmAlgorithms.h" #include "cmCustomCommand.h" #include "cmGeneratorExpression.h" @@ -86,8 +88,7 @@ const char* cmTargetPropertyComputer::GetSources<cmTarget>( std::ostringstream ss; const char* sep = ""; for (std::string const& entry : entries) { - std::vector<std::string> files; - cmSystemTools::ExpandListArgument(entry, files); + std::vector<std::string> files = cmExpandedList(entry); for (std::string const& file : files) { if (cmHasLiteralPrefix(file, "$<TARGET_OBJECTS:") && file.back() == '>') { @@ -168,7 +169,8 @@ public: cmPropertyMap Properties; bool IsGeneratorProvided; bool HaveInstallRule; - bool DLLPlatform; + bool IsDLLPlatform; + bool IsAIX; bool IsAndroid; bool IsImportedTarget; bool ImportedGloballyVisible; @@ -217,7 +219,8 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, impl->Name = name; impl->IsGeneratorProvided = false; impl->HaveInstallRule = false; - impl->DLLPlatform = false; + impl->IsDLLPlatform = false; + impl->IsAIX = false; impl->IsAndroid = false; impl->IsImportedTarget = (vis == VisibilityImported || vis == VisibilityImportedGlobally); @@ -225,21 +228,32 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, impl->BuildInterfaceIncludesAppended = false; // Check whether this is a DLL platform. - impl->DLLPlatform = + impl->IsDLLPlatform = !impl->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty(); + // Check whether we are targeting AIX. + impl->IsAIX = + (impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "AIX"); + // Check whether we are targeting an Android platform. impl->IsAndroid = (impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "Android"); - std::string gKey; - gKey.reserve(128); - gKey += "CMAKE_"; - auto InitProperty = [this, mf, &gKey](const std::string& property, - const char* default_value) { + std::string defKey; + defKey.reserve(128); + defKey += "CMAKE_"; + auto initProp = [this, mf, &defKey](const std::string& property) { // Replace everything after "CMAKE_" - gKey.replace(gKey.begin() + 6, gKey.end(), property); - if (const char* value = mf->GetDefinition(gKey)) { + defKey.replace(defKey.begin() + 6, defKey.end(), property); + if (const char* value = mf->GetDefinition(defKey)) { + this->SetProperty(property, value); + } + }; + auto initPropValue = [this, mf, &defKey](const std::string& property, + const char* default_value) { + // Replace everything after "CMAKE_" + defKey.replace(defKey.begin() + 6, defKey.end(), property); + if (const char* value = mf->GetDefinition(defKey)) { this->SetProperty(property, value); } else if (default_value) { this->SetProperty(property, default_value); @@ -249,107 +263,109 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, // Setup default property values. if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && this->GetType() != cmStateEnums::UTILITY) { - InitProperty("ANDROID_API", nullptr); - InitProperty("ANDROID_API_MIN", nullptr); - InitProperty("ANDROID_ARCH", nullptr); - InitProperty("ANDROID_STL_TYPE", nullptr); - InitProperty("ANDROID_SKIP_ANT_STEP", nullptr); - InitProperty("ANDROID_PROCESS_MAX", nullptr); - InitProperty("ANDROID_PROGUARD", nullptr); - InitProperty("ANDROID_PROGUARD_CONFIG_PATH", nullptr); - InitProperty("ANDROID_SECURE_PROPS_PATH", nullptr); - InitProperty("ANDROID_NATIVE_LIB_DIRECTORIES", nullptr); - InitProperty("ANDROID_NATIVE_LIB_DEPENDENCIES", nullptr); - InitProperty("ANDROID_JAVA_SOURCE_DIR", nullptr); - InitProperty("ANDROID_JAR_DIRECTORIES", nullptr); - InitProperty("ANDROID_JAR_DEPENDENCIES", nullptr); - InitProperty("ANDROID_ASSETS_DIRECTORIES", nullptr); - InitProperty("ANDROID_ANT_ADDITIONAL_OPTIONS", nullptr); - InitProperty("BUILD_RPATH", nullptr); - InitProperty("BUILD_RPATH_USE_ORIGIN", nullptr); - InitProperty("INSTALL_NAME_DIR", nullptr); - InitProperty("INSTALL_RPATH", ""); - InitProperty("INSTALL_RPATH_USE_LINK_PATH", "OFF"); - InitProperty("INTERPROCEDURAL_OPTIMIZATION", nullptr); - InitProperty("SKIP_BUILD_RPATH", "OFF"); - InitProperty("BUILD_WITH_INSTALL_RPATH", "OFF"); - InitProperty("ARCHIVE_OUTPUT_DIRECTORY", nullptr); - InitProperty("LIBRARY_OUTPUT_DIRECTORY", nullptr); - InitProperty("RUNTIME_OUTPUT_DIRECTORY", nullptr); - InitProperty("PDB_OUTPUT_DIRECTORY", nullptr); - InitProperty("COMPILE_PDB_OUTPUT_DIRECTORY", nullptr); - InitProperty("FRAMEWORK", nullptr); - InitProperty("Fortran_FORMAT", nullptr); - InitProperty("Fortran_MODULE_DIRECTORY", nullptr); - InitProperty("Fortran_COMPILER_LAUNCHER", nullptr); - InitProperty("GNUtoMS", nullptr); - InitProperty("OSX_ARCHITECTURES", nullptr); - InitProperty("IOS_INSTALL_COMBINED", nullptr); - InitProperty("AUTOMOC", nullptr); - InitProperty("AUTOUIC", nullptr); - InitProperty("AUTORCC", nullptr); - InitProperty("AUTOGEN_ORIGIN_DEPENDS", nullptr); - InitProperty("AUTOGEN_PARALLEL", nullptr); - InitProperty("AUTOMOC_COMPILER_PREDEFINES", nullptr); - InitProperty("AUTOMOC_DEPEND_FILTERS", nullptr); - InitProperty("AUTOMOC_MACRO_NAMES", nullptr); - InitProperty("AUTOMOC_MOC_OPTIONS", nullptr); - InitProperty("AUTOUIC_OPTIONS", nullptr); - InitProperty("AUTOUIC_SEARCH_PATHS", nullptr); - InitProperty("AUTORCC_OPTIONS", nullptr); - InitProperty("LINK_DEPENDS_NO_SHARED", nullptr); - InitProperty("LINK_INTERFACE_LIBRARIES", nullptr); - InitProperty("MSVC_RUNTIME_LIBRARY", nullptr); - InitProperty("WIN32_EXECUTABLE", nullptr); - InitProperty("MACOSX_BUNDLE", nullptr); - InitProperty("MACOSX_RPATH", nullptr); - InitProperty("NO_SYSTEM_FROM_IMPORTED", nullptr); - InitProperty("BUILD_WITH_INSTALL_NAME_DIR", nullptr); - InitProperty("C_CLANG_TIDY", nullptr); - InitProperty("C_COMPILER_LAUNCHER", nullptr); - InitProperty("C_CPPLINT", nullptr); - InitProperty("C_CPPCHECK", nullptr); - InitProperty("C_INCLUDE_WHAT_YOU_USE", nullptr); - InitProperty("LINK_WHAT_YOU_USE", nullptr); - InitProperty("C_STANDARD", nullptr); - InitProperty("C_STANDARD_REQUIRED", nullptr); - InitProperty("C_EXTENSIONS", nullptr); - InitProperty("CXX_CLANG_TIDY", nullptr); - InitProperty("CXX_COMPILER_LAUNCHER", nullptr); - InitProperty("CXX_CPPLINT", nullptr); - InitProperty("CXX_CPPCHECK", nullptr); - InitProperty("CXX_INCLUDE_WHAT_YOU_USE", nullptr); - InitProperty("CXX_STANDARD", nullptr); - InitProperty("CXX_STANDARD_REQUIRED", nullptr); - InitProperty("CXX_EXTENSIONS", nullptr); - InitProperty("CUDA_STANDARD", nullptr); - InitProperty("CUDA_STANDARD_REQUIRED", nullptr); - InitProperty("CUDA_EXTENSIONS", nullptr); - InitProperty("CUDA_COMPILER_LAUNCHER", nullptr); - InitProperty("CUDA_SEPARABLE_COMPILATION", nullptr); - InitProperty("LINK_SEARCH_START_STATIC", nullptr); - InitProperty("LINK_SEARCH_END_STATIC", nullptr); - InitProperty("FOLDER", nullptr); - InitProperty("Swift_MODULE_DIRECTORY", nullptr); - InitProperty("VS_JUST_MY_CODE_DEBUGGING", nullptr); + initProp("ANDROID_API"); + initProp("ANDROID_API_MIN"); + initProp("ANDROID_ARCH"); + initProp("ANDROID_STL_TYPE"); + initProp("ANDROID_SKIP_ANT_STEP"); + initProp("ANDROID_PROCESS_MAX"); + initProp("ANDROID_PROGUARD"); + initProp("ANDROID_PROGUARD_CONFIG_PATH"); + initProp("ANDROID_SECURE_PROPS_PATH"); + initProp("ANDROID_NATIVE_LIB_DIRECTORIES"); + initProp("ANDROID_NATIVE_LIB_DEPENDENCIES"); + initProp("ANDROID_JAVA_SOURCE_DIR"); + initProp("ANDROID_JAR_DIRECTORIES"); + initProp("ANDROID_JAR_DEPENDENCIES"); + initProp("ANDROID_ASSETS_DIRECTORIES"); + initProp("ANDROID_ANT_ADDITIONAL_OPTIONS"); + initProp("BUILD_RPATH"); + initProp("BUILD_RPATH_USE_ORIGIN"); + initProp("INSTALL_NAME_DIR"); + initProp("INSTALL_REMOVE_ENVIRONMENT_RPATH"); + initPropValue("INSTALL_RPATH", ""); + initPropValue("INSTALL_RPATH_USE_LINK_PATH", "OFF"); + initProp("INTERPROCEDURAL_OPTIMIZATION"); + initPropValue("SKIP_BUILD_RPATH", "OFF"); + initPropValue("BUILD_WITH_INSTALL_RPATH", "OFF"); + initProp("ARCHIVE_OUTPUT_DIRECTORY"); + initProp("LIBRARY_OUTPUT_DIRECTORY"); + initProp("RUNTIME_OUTPUT_DIRECTORY"); + initProp("PDB_OUTPUT_DIRECTORY"); + initProp("COMPILE_PDB_OUTPUT_DIRECTORY"); + initProp("FRAMEWORK"); + initProp("Fortran_FORMAT"); + initProp("Fortran_MODULE_DIRECTORY"); + initProp("Fortran_COMPILER_LAUNCHER"); + initProp("GNUtoMS"); + initProp("OSX_ARCHITECTURES"); + initProp("IOS_INSTALL_COMBINED"); + initProp("AUTOMOC"); + initProp("AUTOUIC"); + initProp("AUTORCC"); + initProp("AUTOGEN_ORIGIN_DEPENDS"); + initProp("AUTOGEN_PARALLEL"); + initProp("AUTOMOC_COMPILER_PREDEFINES"); + initProp("AUTOMOC_DEPEND_FILTERS"); + initProp("AUTOMOC_MACRO_NAMES"); + initProp("AUTOMOC_MOC_OPTIONS"); + initProp("AUTOUIC_OPTIONS"); + initProp("AUTOUIC_SEARCH_PATHS"); + initProp("AUTORCC_OPTIONS"); + initProp("LINK_DEPENDS_NO_SHARED"); + initProp("LINK_INTERFACE_LIBRARIES"); + initProp("MSVC_RUNTIME_LIBRARY"); + initProp("WIN32_EXECUTABLE"); + initProp("MACOSX_BUNDLE"); + initProp("MACOSX_RPATH"); + initProp("NO_SYSTEM_FROM_IMPORTED"); + initProp("BUILD_WITH_INSTALL_NAME_DIR"); + initProp("C_CLANG_TIDY"); + initProp("C_COMPILER_LAUNCHER"); + initProp("C_CPPLINT"); + initProp("C_CPPCHECK"); + initProp("C_INCLUDE_WHAT_YOU_USE"); + initProp("LINK_WHAT_YOU_USE"); + initProp("C_STANDARD"); + initProp("C_STANDARD_REQUIRED"); + initProp("C_EXTENSIONS"); + initProp("CXX_CLANG_TIDY"); + initProp("CXX_COMPILER_LAUNCHER"); + initProp("CXX_CPPLINT"); + initProp("CXX_CPPCHECK"); + initProp("CXX_INCLUDE_WHAT_YOU_USE"); + initProp("CXX_STANDARD"); + initProp("CXX_STANDARD_REQUIRED"); + initProp("CXX_EXTENSIONS"); + initProp("CUDA_STANDARD"); + initProp("CUDA_STANDARD_REQUIRED"); + initProp("CUDA_EXTENSIONS"); + initProp("CUDA_COMPILER_LAUNCHER"); + initProp("CUDA_SEPARABLE_COMPILATION"); + initProp("CUDA_RESOLVE_DEVICE_SYMBOLS"); + initProp("LINK_SEARCH_START_STATIC"); + initProp("LINK_SEARCH_END_STATIC"); + initProp("FOLDER"); + initProp("Swift_MODULE_DIRECTORY"); + initProp("VS_JUST_MY_CODE_DEBUGGING"); #ifdef __APPLE__ if (this->GetGlobalGenerator()->IsXcode()) { - InitProperty("XCODE_GENERATE_SCHEME", nullptr); - InitProperty("XCODE_SCHEME_ADDRESS_SANITIZER", nullptr); - InitProperty("XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN", nullptr); - InitProperty("XCODE_SCHEME_THREAD_SANITIZER", nullptr); - InitProperty("XCODE_SCHEME_THREAD_SANITIZER_STOP", nullptr); - InitProperty("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER", nullptr); - InitProperty("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP", nullptr); - InitProperty("XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER", nullptr); - InitProperty("XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP", nullptr); - InitProperty("XCODE_SCHEME_MALLOC_SCRIBBLE", nullptr); - InitProperty("XCODE_SCHEME_MALLOC_GUARD_EDGES", nullptr); - InitProperty("XCODE_SCHEME_GUARD_MALLOC", nullptr); - InitProperty("XCODE_SCHEME_ZOMBIE_OBJECTS", nullptr); - InitProperty("XCODE_SCHEME_MALLOC_STACK", nullptr); - InitProperty("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE", nullptr); - InitProperty("XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS", nullptr); + initProp("XCODE_GENERATE_SCHEME"); + initProp("XCODE_SCHEME_ADDRESS_SANITIZER"); + initProp("XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN"); + initProp("XCODE_SCHEME_THREAD_SANITIZER"); + initProp("XCODE_SCHEME_THREAD_SANITIZER_STOP"); + initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER"); + initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP"); + initProp("XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER"); + initProp("XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP"); + initProp("XCODE_SCHEME_MALLOC_SCRIBBLE"); + initProp("XCODE_SCHEME_MALLOC_GUARD_EDGES"); + initProp("XCODE_SCHEME_GUARD_MALLOC"); + initProp("XCODE_SCHEME_ZOMBIE_OBJECTS"); + initProp("XCODE_SCHEME_MALLOC_STACK"); + initProp("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE"); + initProp("XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS"); } #endif } @@ -375,9 +391,8 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, strcmp(prop, "MAP_IMPORTED_CONFIG_") != 0) { continue; } - std::string property = prop; - property += configUpper; - InitProperty(property, nullptr); + std::string property = cmStrCat(prop, configUpper); + initProp(property); } // Initialize per-configuration name postfix property from the @@ -387,9 +402,9 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, // property directly. if (impl->TargetType != cmStateEnums::EXECUTABLE && impl->TargetType != cmStateEnums::INTERFACE_LIBRARY) { - std::string property = cmSystemTools::UpperCase(configName); - property += "_POSTFIX"; - InitProperty(property, nullptr); + std::string property = + cmStrCat(cmSystemTools::UpperCase(configName), "_POSTFIX"); + initProp(property); } } } @@ -428,16 +443,16 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && this->GetType() != cmStateEnums::UTILITY) { - InitProperty("C_VISIBILITY_PRESET", nullptr); - InitProperty("CXX_VISIBILITY_PRESET", nullptr); - InitProperty("CUDA_VISIBILITY_PRESET", nullptr); - InitProperty("VISIBILITY_INLINES_HIDDEN", nullptr); + initProp("C_VISIBILITY_PRESET"); + initProp("CXX_VISIBILITY_PRESET"); + initProp("CUDA_VISIBILITY_PRESET"); + initProp("VISIBILITY_INLINES_HIDDEN"); } if (impl->TargetType == cmStateEnums::EXECUTABLE) { - InitProperty("ANDROID_GUI", nullptr); - InitProperty("CROSSCOMPILING_EMULATOR", nullptr); - InitProperty("ENABLE_EXPORTS", nullptr); + initProp("ANDROID_GUI"); + initProp("CROSSCOMPILING_EMULATOR"); + initProp("ENABLE_EXPORTS"); } if (impl->TargetType == cmStateEnums::SHARED_LIBRARY || impl->TargetType == cmStateEnums::MODULE_LIBRARY) { @@ -445,12 +460,12 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, } if (impl->TargetType == cmStateEnums::SHARED_LIBRARY || impl->TargetType == cmStateEnums::EXECUTABLE) { - InitProperty("WINDOWS_EXPORT_ALL_SYMBOLS", nullptr); + initProp("WINDOWS_EXPORT_ALL_SYMBOLS"); } if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && this->GetType() != cmStateEnums::UTILITY) { - InitProperty("POSITION_INDEPENDENT_CODE", nullptr); + initProp("POSITION_INDEPENDENT_CODE"); } // Record current policies for later use. @@ -466,12 +481,12 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && this->GetType() != cmStateEnums::UTILITY) { - InitProperty("JOB_POOL_COMPILE", nullptr); - InitProperty("JOB_POOL_LINK", nullptr); + initProp("JOB_POOL_COMPILE"); + initProp("JOB_POOL_LINK"); } if (impl->TargetType <= cmStateEnums::UTILITY) { - InitProperty("DOTNET_TARGET_FRAMEWORK_VERSION", nullptr); + initProp("DOTNET_TARGET_FRAMEWORK_VERSION"); } if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && @@ -483,8 +498,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, if (globals) { const std::string genName = mf->GetGlobalGenerator()->GetName(); if (cmHasLiteralPrefix(genName, "Visual Studio")) { - std::vector<std::string> props; - cmSystemTools::ExpandListArgument(globals, props); + std::vector<std::string> props = cmExpandedList(globals); const std::string vsGlobal = "VS_GLOBAL_"; for (const std::string& i : props) { // split NAME=VALUE @@ -492,7 +506,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, if (assignment != std::string::npos) { const std::string propName = vsGlobal + i.substr(0, assignment); const std::string propValue = i.substr(assignment + 1); - InitProperty(propName, propValue.c_str()); + initPropValue(propName, propValue.c_str()); } } } @@ -726,8 +740,7 @@ public: bool operator()(std::string const& entry) { - std::vector<std::string> files; - cmSystemTools::ExpandListArgument(entry, files); + std::vector<std::string> files = cmExpandedList(entry); std::vector<cmSourceFileLocation> locations; locations.reserve(files.size()); std::transform(files.begin(), files.end(), std::back_inserter(locations), @@ -761,8 +774,7 @@ cmSourceFile* cmTarget::AddSource(const std::string& src, bool before) void cmTarget::ClearDependencyInformation(cmMakefile& mf) { - std::string depname = this->GetName(); - depname += "_LIB_DEPENDS"; + std::string depname = cmStrCat(this->GetName(), "_LIB_DEPENDS"); mf.RemoveCacheDefinition(depname); } @@ -930,8 +942,7 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib, impl->TargetType <= cmStateEnums::MODULE_LIBRARY && (this->GetPolicyStatusCMP0073() == cmPolicies::OLD || this->GetPolicyStatusCMP0073() == cmPolicies::WARN)) { - std::string targetEntry = impl->Name; - targetEntry += "_LIB_DEPENDS"; + std::string targetEntry = cmStrCat(impl->Name, "_LIB_DEPENDS"); std::string dependencies; const char* old_val = mf.GetDefinition(targetEntry); if (old_val) { @@ -1070,21 +1081,19 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) MAKE_STATIC_PROP(TYPE); #undef MAKE_STATIC_PROP if (prop == propMANUALLY_ADDED_DEPENDENCIES) { - std::ostringstream e; - e << "MANUALLY_ADDED_DEPENDENCIES property is read-only\n"; - impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + impl->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + "MANUALLY_ADDED_DEPENDENCIES property is read-only\n"); return; } if (prop == propNAME) { - std::ostringstream e; - e << "NAME property is read-only\n"; - impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, + "NAME property is read-only\n"); return; } if (prop == propTYPE) { - std::ostringstream e; - e << "TYPE property is read-only\n"; - impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, + "TYPE property is read-only\n"); return; } if (prop == propEXPORT_NAME && this->IsImported()) { @@ -1174,7 +1183,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) impl->SourceBacktraces.push_back(lfbt); } } else if (prop == propIMPORTED_GLOBAL) { - if (!cmSystemTools::IsOn(value)) { + if (!cmIsOn(value)) { std::ostringstream e; e << "IMPORTED_GLOBAL property can't be set to FALSE on targets (\"" << impl->Name << "\")\n"; @@ -1211,9 +1220,8 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, return; } if (prop == "NAME") { - std::ostringstream e; - e << "NAME property is read-only\n"; - impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, + "NAME property is read-only\n"); return; } if (prop == "EXPORT_NAME" && this->IsImported()) { @@ -1496,7 +1504,6 @@ const char* cmTarget::GetComputedProperty( const char* cmTarget::GetProperty(const std::string& prop) const { - static std::unordered_set<std::string> specialProps; #define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP MAKE_STATIC_PROP(LINK_LIBRARIES); MAKE_STATIC_PROP(TYPE); @@ -1514,23 +1521,23 @@ const char* cmTarget::GetProperty(const std::string& prop) const MAKE_STATIC_PROP(SOURCE_DIR); MAKE_STATIC_PROP(SOURCES); #undef MAKE_STATIC_PROP - if (specialProps.empty()) { - specialProps.insert(propLINK_LIBRARIES); - specialProps.insert(propTYPE); - specialProps.insert(propINCLUDE_DIRECTORIES); - specialProps.insert(propCOMPILE_FEATURES); - specialProps.insert(propCOMPILE_OPTIONS); - specialProps.insert(propCOMPILE_DEFINITIONS); - specialProps.insert(propLINK_OPTIONS); - specialProps.insert(propLINK_DIRECTORIES); - specialProps.insert(propIMPORTED); - specialProps.insert(propIMPORTED_GLOBAL); - specialProps.insert(propMANUALLY_ADDED_DEPENDENCIES); - specialProps.insert(propNAME); - specialProps.insert(propBINARY_DIR); - specialProps.insert(propSOURCE_DIR); - specialProps.insert(propSOURCES); - } + static std::unordered_set<std::string> const specialProps{ + propLINK_LIBRARIES, + propTYPE, + propINCLUDE_DIRECTORIES, + propCOMPILE_FEATURES, + propCOMPILE_OPTIONS, + propCOMPILE_DEFINITIONS, + propLINK_OPTIONS, + propLINK_DIRECTORIES, + propIMPORTED, + propIMPORTED_GLOBAL, + propMANUALLY_ADDED_DEPENDENCIES, + propNAME, + propBINARY_DIR, + propSOURCE_DIR, + propSOURCES + }; if (specialProps.count(prop)) { if (prop == propLINK_LIBRARIES) { if (impl->LinkImplementationPropertyEntries.empty()) { @@ -1655,7 +1662,7 @@ const char* cmTarget::GetSafeProperty(const std::string& prop) const bool cmTarget::GetPropertyAsBool(const std::string& prop) const { - return cmSystemTools::IsOn(this->GetProperty(prop)); + return cmIsOn(this->GetProperty(prop)); } cmPropertyMap const& cmTarget::GetProperties() const @@ -1663,6 +1670,16 @@ cmPropertyMap const& cmTarget::GetProperties() const return impl->Properties; } +bool cmTarget::IsDLLPlatform() const +{ + return impl->IsDLLPlatform; +} + +bool cmTarget::IsAIX() const +{ + return impl->IsAIX; +} + bool cmTarget::IsImported() const { return impl->IsImportedTarget; @@ -1704,7 +1721,8 @@ const char* cmTarget::GetSuffixVariableInternal( ? "CMAKE_SHARED_LIBRARY_SUFFIX" : "CMAKE_EXECUTABLE_SUFFIX"); case cmStateEnums::ImportLibraryArtifact: - return "CMAKE_IMPORT_LIBRARY_SUFFIX"; + return (impl->IsAIX ? "CMAKE_AIX_IMPORT_FILE_SUFFIX" + : "CMAKE_IMPORT_LIBRARY_SUFFIX"); } break; default: @@ -1744,7 +1762,8 @@ const char* cmTarget::GetPrefixVariableInternal( ? "CMAKE_SHARED_LIBRARY_PREFIX" : ""); case cmStateEnums::ImportLibraryArtifact: - return "CMAKE_IMPORT_LIBRARY_PREFIX"; + return (impl->IsAIX ? "CMAKE_AIX_IMPORT_FILE_PREFIX" + : "CMAKE_IMPORT_LIBRARY_PREFIX"); } break; default: @@ -1778,8 +1797,7 @@ std::string cmTarget::ImportedGetFullPath( if (loc) { result = loc; } else { - std::string impProp = "IMPORTED_LOCATION"; - impProp += suffix; + std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix); if (const char* config_location = this->GetProperty(impProp)) { result = config_location; } else if (const char* location = @@ -1794,8 +1812,7 @@ std::string cmTarget::ImportedGetFullPath( result = imp; } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY || this->IsExecutableWithExports()) { - std::string impProp = "IMPORTED_IMPLIB"; - impProp += suffix; + std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix); if (const char* config_implib = this->GetProperty(impProp)) { result = config_implib; } else if (const char* implib = @@ -1808,8 +1825,7 @@ std::string cmTarget::ImportedGetFullPath( } if (result.empty()) { - result = this->GetName(); - result += "-NOTFOUND"; + result = cmStrCat(this->GetName(), "-NOTFOUND"); } return result; } @@ -1863,24 +1879,23 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, } // Track the configuration-specific property suffix. - suffix = "_"; - suffix += config_upper; + suffix = cmStrCat('_', config_upper); std::vector<std::string> mappedConfigs; { - std::string mapProp = "MAP_IMPORTED_CONFIG_"; - mapProp += config_upper; + std::string mapProp = cmStrCat("MAP_IMPORTED_CONFIG_", config_upper); if (const char* mapValue = this->GetProperty(mapProp)) { - cmSystemTools::ExpandListArgument(mapValue, mappedConfigs, true); + cmExpandList(mapValue, mappedConfigs, true); } } // If we needed to find one of the mapped configurations but did not // On a DLL platform there may be only IMPORTED_IMPLIB for a shared // library or an executable with exports. - bool allowImp = (impl->DLLPlatform && + bool allowImp = (this->IsDLLPlatform() && (this->GetType() == cmStateEnums::SHARED_LIBRARY || - this->IsExecutableWithExports())); + this->IsExecutableWithExports())) || + (this->IsAIX() && this->IsExecutableWithExports()); // If a mapping was found, check its configurations. for (std::vector<std::string>::const_iterator mci = mappedConfigs.begin(); @@ -1899,19 +1914,16 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, } } else { std::string mcUpper = cmSystemTools::UpperCase(*mci); - std::string locProp = locPropBase + "_"; - locProp += mcUpper; + std::string locProp = cmStrCat(locPropBase, '_', mcUpper); *loc = this->GetProperty(locProp); if (allowImp) { - std::string impProp = "IMPORTED_IMPLIB_"; - impProp += mcUpper; + std::string impProp = cmStrCat("IMPORTED_IMPLIB_", mcUpper); *imp = this->GetProperty(impProp); } // If it was found, use it for all properties below. if (*loc || *imp) { - suffix = "_"; - suffix += mcUpper; + suffix = cmStrCat('_', mcUpper); } } } @@ -1928,12 +1940,10 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, // If we have not yet found it then there are no mapped // configurations. Look for an exact-match. if (!*loc && !*imp) { - std::string locProp = locPropBase; - locProp += suffix; + std::string locProp = cmStrCat(locPropBase, suffix); *loc = this->GetProperty(locProp); if (allowImp) { - std::string impProp = "IMPORTED_IMPLIB"; - impProp += suffix; + std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix); *imp = this->GetProperty(impProp); } } @@ -1957,19 +1967,16 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, if (!*loc && !*imp) { std::vector<std::string> availableConfigs; if (const char* iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) { - cmSystemTools::ExpandListArgument(iconfigs, availableConfigs); + cmExpandList(iconfigs, availableConfigs); } for (std::vector<std::string>::const_iterator aci = availableConfigs.begin(); !*loc && !*imp && aci != availableConfigs.end(); ++aci) { - suffix = "_"; - suffix += cmSystemTools::UpperCase(*aci); - std::string locProp = locPropBase; - locProp += suffix; + suffix = cmStrCat('_', cmSystemTools::UpperCase(*aci)); + std::string locProp = cmStrCat(locPropBase, suffix); *loc = this->GetProperty(locProp); if (allowImp) { - std::string impProp = "IMPORTED_IMPLIB"; - impProp += suffix; + std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix); *imp = this->GetProperty(impProp); } } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 2bd9e6d..2b75879 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -6,7 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <iosfwd> -#include <memory> // IWYU pragma: keep +#include <memory> #include <set> #include <string> #include <utility> @@ -16,6 +16,7 @@ #include "cmListFileCache.h" #include "cmPolicies.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmTargetLinkLibraryType.h" class cmCustomCommand; @@ -181,6 +182,12 @@ public: //! Get all properties cmPropertyMap const& GetProperties() const; + //! Return whether or not the target is for a DLL platform. + bool IsDLLPlatform() const; + + //! Return whether or not we are targeting AIX. + bool IsAIX() const; + bool IsImported() const; bool IsImportedGloballyVisible() const; diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx index c4dc838..b64646a 100644 --- a/Source/cmTargetCompileDefinitionsCommand.cxx +++ b/Source/cmTargetCompileDefinitionsCommand.cxx @@ -4,9 +4,9 @@ #include <sstream> -#include "cmAlgorithms.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmStringAlgorithms.h" #include "cmTarget.h" class cmExecutionStatus; diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h index d41483a..25af21d 100644 --- a/Source/cmTargetCompileDefinitionsCommand.h +++ b/Source/cmTargetCompileDefinitionsCommand.h @@ -8,9 +8,11 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + +#include "cmCommand.h" #include "cmTargetPropCommandBase.h" -class cmCommand; class cmExecutionStatus; class cmTarget; @@ -20,7 +22,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmTargetCompileDefinitionsCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmTargetCompileDefinitionsCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmTargetCompileFeaturesCommand.cxx b/Source/cmTargetCompileFeaturesCommand.cxx index c9e394b..976c8cb 100644 --- a/Source/cmTargetCompileFeaturesCommand.cxx +++ b/Source/cmTargetCompileFeaturesCommand.cxx @@ -4,9 +4,9 @@ #include <sstream> -#include "cmAlgorithms.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmStringAlgorithms.h" class cmExecutionStatus; class cmTarget; diff --git a/Source/cmTargetCompileFeaturesCommand.h b/Source/cmTargetCompileFeaturesCommand.h index 45240a5..07948fa 100644 --- a/Source/cmTargetCompileFeaturesCommand.h +++ b/Source/cmTargetCompileFeaturesCommand.h @@ -8,15 +8,20 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + +#include "cmCommand.h" #include "cmTargetPropCommandBase.h" -class cmCommand; class cmExecutionStatus; class cmTarget; class cmTargetCompileFeaturesCommand : public cmTargetPropCommandBase { - cmCommand* Clone() override { return new cmTargetCompileFeaturesCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmTargetCompileFeaturesCommand>(); + } bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx index 8b4763a..7dadb82 100644 --- a/Source/cmTargetCompileOptionsCommand.cxx +++ b/Source/cmTargetCompileOptionsCommand.cxx @@ -4,10 +4,10 @@ #include <sstream> -#include "cmAlgorithms.h" #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmStringAlgorithms.h" #include "cmTarget.h" class cmExecutionStatus; diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h index 6fb151a..a571cfb 100644 --- a/Source/cmTargetCompileOptionsCommand.h +++ b/Source/cmTargetCompileOptionsCommand.h @@ -8,9 +8,11 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + +#include "cmCommand.h" #include "cmTargetPropCommandBase.h" -class cmCommand; class cmExecutionStatus; class cmTarget; @@ -20,7 +22,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmTargetCompileOptionsCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmTargetCompileOptionsCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmTargetDepend.h b/Source/cmTargetDepend.h index 5ea0085..4ca78fa 100644 --- a/Source/cmTargetDepend.h +++ b/Source/cmTargetDepend.h @@ -31,7 +31,7 @@ public: operator cmGeneratorTarget const*() const { return this->Target; } cmGeneratorTarget const* operator->() const { return this->Target; } cmGeneratorTarget const& operator*() const { return *this->Target; } - friend bool operator<(cmTargetDepend l, cmTargetDepend r) + friend bool operator<(cmTargetDepend const& l, cmTargetDepend const& r) { return l.Target < r.Target; } diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index d6918c0..d099349 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -9,6 +9,7 @@ #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -39,9 +40,9 @@ std::string cmTargetIncludeDirectoriesCommand::Join( for (std::string const& it : content) { if (cmSystemTools::FileIsFullPath(it) || cmGeneratorExpression::Find(it) == 0) { - dirs += sep + it; + dirs += cmStrCat(sep, it); } else { - dirs += sep + prefix + it; + dirs += cmStrCat(sep, prefix, it); } sep = ";"; } diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h index 57bf8fc..6defab2 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.h +++ b/Source/cmTargetIncludeDirectoriesCommand.h @@ -8,9 +8,11 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + +#include "cmCommand.h" #include "cmTargetPropCommandBase.h" -class cmCommand; class cmExecutionStatus; class cmTarget; @@ -20,7 +22,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmTargetIncludeDirectoriesCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmTargetIncludeDirectoriesCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmTargetLinkDirectoriesCommand.cxx b/Source/cmTargetLinkDirectoriesCommand.cxx index 269f751..435c392 100644 --- a/Source/cmTargetLinkDirectoriesCommand.cxx +++ b/Source/cmTargetLinkDirectoriesCommand.cxx @@ -4,11 +4,11 @@ #include <sstream> -#include "cmAlgorithms.h" #include "cmGeneratorExpression.h" #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" diff --git a/Source/cmTargetLinkDirectoriesCommand.h b/Source/cmTargetLinkDirectoriesCommand.h index 52c75a0..a2fcfa9 100644 --- a/Source/cmTargetLinkDirectoriesCommand.h +++ b/Source/cmTargetLinkDirectoriesCommand.h @@ -8,9 +8,11 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + +#include "cmCommand.h" #include "cmTargetPropCommandBase.h" -class cmCommand; class cmExecutionStatus; class cmTarget; @@ -20,7 +22,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmTargetLinkDirectoriesCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmTargetLinkDirectoriesCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 3883b52..4fbec90 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -12,6 +12,7 @@ #include "cmPolicies.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmake.h" @@ -237,8 +238,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass( // only there for backwards compatibility when mixing projects built // with old versions of CMake and new) llt = GENERAL_LibraryType; - std::string linkType = args[0]; - linkType += "_LINK_TYPE"; + std::string linkType = cmStrCat(args[0], "_LINK_TYPE"); const char* linkTypeString = this->Makefile->GetDefinition(linkType); if (linkTypeString) { if (strcmp(linkTypeString, "debug") == 0) { @@ -502,8 +502,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, if (llt == DEBUG_LibraryType || llt == GENERAL_LibraryType) { // Put in the DEBUG configuration interfaces. for (std::string const& dc : debugConfigs) { - prop = "LINK_INTERFACE_LIBRARIES_"; - prop += dc; + prop = cmStrCat("LINK_INTERFACE_LIBRARIES_", dc); this->Target->AppendProperty(prop, libRef.c_str()); } } @@ -514,8 +513,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, // Make sure the DEBUG configuration interfaces exist so that the // general one will not be used as a fall-back. for (std::string const& dc : debugConfigs) { - prop = "LINK_INTERFACE_LIBRARIES_"; - prop += dc; + prop = cmStrCat("LINK_INTERFACE_LIBRARIES_", dc); if (!this->Target->GetProperty(prop)) { this->Target->SetProperty(prop, ""); } diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h index 54f8cf4..6698ce0 100644 --- a/Source/cmTargetLinkLibrariesCommand.h +++ b/Source/cmTargetLinkLibrariesCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" #include "cmTargetLinkLibraryType.h" @@ -30,7 +32,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmTargetLinkLibrariesCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmTargetLinkLibrariesCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmTargetLinkOptionsCommand.cxx b/Source/cmTargetLinkOptionsCommand.cxx index 5366486..2866cf1 100644 --- a/Source/cmTargetLinkOptionsCommand.cxx +++ b/Source/cmTargetLinkOptionsCommand.cxx @@ -4,10 +4,10 @@ #include <sstream> -#include "cmAlgorithms.h" #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmStringAlgorithms.h" #include "cmTarget.h" class cmExecutionStatus; diff --git a/Source/cmTargetLinkOptionsCommand.h b/Source/cmTargetLinkOptionsCommand.h index a1fc9fc..3710739 100644 --- a/Source/cmTargetLinkOptionsCommand.h +++ b/Source/cmTargetLinkOptionsCommand.h @@ -8,9 +8,11 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + +#include "cmCommand.h" #include "cmTargetPropCommandBase.h" -class cmCommand; class cmExecutionStatus; class cmTarget; @@ -20,7 +22,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmTargetLinkOptionsCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmTargetLinkOptionsCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index 1b8ee81..3aa845c 100644 --- a/Source/cmTargetPropCommandBase.cxx +++ b/Source/cmTargetPropCommandBase.cxx @@ -32,12 +32,13 @@ bool cmTargetPropCommandBase::HandleArguments( this->HandleMissingTarget(args[0]); return false; } - if ((this->Target->GetType() != cmStateEnums::SHARED_LIBRARY) && + if ((this->Target->GetType() != cmStateEnums::EXECUTABLE) && (this->Target->GetType() != cmStateEnums::STATIC_LIBRARY) && - (this->Target->GetType() != cmStateEnums::OBJECT_LIBRARY) && + (this->Target->GetType() != cmStateEnums::SHARED_LIBRARY) && (this->Target->GetType() != cmStateEnums::MODULE_LIBRARY) && + (this->Target->GetType() != cmStateEnums::OBJECT_LIBRARY) && (this->Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) && - (this->Target->GetType() != cmStateEnums::EXECUTABLE)) { + (this->Target->GetType() != cmStateEnums::UNKNOWN_LIBRARY)) { this->SetError("called with non-compilable target type"); return false; } diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx index 3f763af..baab8da 100644 --- a/Source/cmTargetPropertyComputer.cxx +++ b/Source/cmTargetPropertyComputer.cxx @@ -11,6 +11,7 @@ #include "cmMessenger.h" #include "cmPolicies.h" #include "cmStateSnapshot.h" +#include "cmStringAlgorithms.h" bool cmTargetPropertyComputer::HandleLocationPropertyPolicy( std::string const& tgtName, cmMessenger* messenger, @@ -56,22 +57,21 @@ bool cmTargetPropertyComputer::WhiteListedInterfaceProperty( if (std::islower(prop[0])) { return true; } - static std::unordered_set<std::string> builtIns; - if (builtIns.empty()) { - builtIns.insert("COMPATIBLE_INTERFACE_BOOL"); - builtIns.insert("COMPATIBLE_INTERFACE_NUMBER_MAX"); - builtIns.insert("COMPATIBLE_INTERFACE_NUMBER_MIN"); - builtIns.insert("COMPATIBLE_INTERFACE_STRING"); - builtIns.insert("EXPORT_NAME"); - builtIns.insert("EXPORT_PROPERTIES"); - builtIns.insert("IMPORTED"); - builtIns.insert("IMPORTED_GLOBAL"); - builtIns.insert("MANUALLY_ADDED_DEPENDENCIES"); - builtIns.insert("NAME"); - builtIns.insert("PRIVATE_HEADER"); - builtIns.insert("PUBLIC_HEADER"); - builtIns.insert("TYPE"); - } + static std::unordered_set<std::string> const builtIns{ + "COMPATIBLE_INTERFACE_BOOL", + "COMPATIBLE_INTERFACE_NUMBER_MAX", + "COMPATIBLE_INTERFACE_NUMBER_MIN", + "COMPATIBLE_INTERFACE_STRING", + "EXPORT_NAME", + "EXPORT_PROPERTIES", + "IMPORTED", + "IMPORTED_GLOBAL", + "MANUALLY_ADDED_DEPENDENCIES", + "NAME", + "PRIVATE_HEADER", + "PUBLIC_HEADER", + "TYPE" + }; if (builtIns.count(prop)) { return true; diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h index efbf95f..3b11acd 100644 --- a/Source/cmTargetPropertyComputer.h +++ b/Source/cmTargetPropertyComputer.h @@ -7,9 +7,9 @@ #include <string> -#include "cmAlgorithms.h" #include "cmListFileCache.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmMessenger; diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx index 11e288f..2251a65 100644 --- a/Source/cmTargetSourcesCommand.cxx +++ b/Source/cmTargetSourcesCommand.cxx @@ -4,11 +4,11 @@ #include <sstream> -#include "cmAlgorithms.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -75,9 +75,8 @@ std::vector<std::string> cmTargetSourcesCommand::ConvertToAbsoluteContent( absoluteSrc = src; } else { changedPath = true; - absoluteSrc = this->Makefile->GetCurrentSourceDirectory(); - absoluteSrc += "/"; - absoluteSrc += src; + absoluteSrc = + cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', src); } absoluteContent.push_back(absoluteSrc); } diff --git a/Source/cmTargetSourcesCommand.h b/Source/cmTargetSourcesCommand.h index b01e3ca..90fd45f 100644 --- a/Source/cmTargetSourcesCommand.h +++ b/Source/cmTargetSourcesCommand.h @@ -8,9 +8,11 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + +#include "cmCommand.h" #include "cmTargetPropCommandBase.h" -class cmCommand; class cmExecutionStatus; class cmTarget; @@ -20,7 +22,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmTargetSourcesCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmTargetSourcesCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx index 7d45cf5..d5c61c1 100644 --- a/Source/cmTest.cxx +++ b/Source/cmTest.cxx @@ -5,10 +5,11 @@ #include "cmMakefile.h" #include "cmProperty.h" #include "cmState.h" -#include "cmSystemTools.h" +#include "cmStringAlgorithms.h" cmTest::cmTest(cmMakefile* mf) - : Backtrace(mf->GetBacktrace()) + : CommandExpandLists(false) + , Backtrace(mf->GetBacktrace()) { this->Makefile = mf; this->OldStyle = true; @@ -46,7 +47,7 @@ const char* cmTest::GetProperty(const std::string& prop) const bool cmTest::GetPropertyAsBool(const std::string& prop) const { - return cmSystemTools::IsOn(this->GetProperty(prop)); + return cmIsOn(this->GetProperty(prop)); } void cmTest::SetProperty(const std::string& prop, const char* value) @@ -59,3 +60,13 @@ void cmTest::AppendProperty(const std::string& prop, const char* value, { this->Properties.AppendProperty(prop, value, asString); } + +bool cmTest::GetCommandExpandLists() const +{ + return this->CommandExpandLists; +} + +void cmTest::SetCommandExpandLists(bool b) +{ + this->CommandExpandLists = b; +} diff --git a/Source/cmTest.h b/Source/cmTest.h index 88dc730..02d8f46 100644 --- a/Source/cmTest.h +++ b/Source/cmTest.h @@ -51,10 +51,15 @@ public: bool GetOldStyle() const { return this->OldStyle; } void SetOldStyle(bool b) { this->OldStyle = b; } + /** Set/Get whether lists in command lines should be expanded. */ + bool GetCommandExpandLists() const; + void SetCommandExpandLists(bool b); + private: cmPropertyMap Properties; std::string Name; std::vector<std::string> Command; + bool CommandExpandLists; bool OldStyle; diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index 571cd09..333d4d5 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -2,18 +2,20 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTestGenerator.h" +#include <memory> #include <ostream> #include <utility> +#include <vector> #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmOutputConverter.h" -#include "cmProperty.h" #include "cmPropertyMap.h" #include "cmRange.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTest.h" @@ -76,12 +78,22 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, // Start the test command. os << indent << "add_test(" << this->Test->GetName() << " "; - // Get the test command line to be executed. - std::vector<std::string> const& command = this->Test->GetCommand(); + // Evaluate command line arguments + std::vector<std::string> argv = + EvaluateCommandLineArguments(this->Test->GetCommand(), ge, config); + + // Expand arguments if COMMAND_EXPAND_LISTS is set + if (this->Test->GetCommandExpandLists()) { + argv = cmExpandedLists(argv.begin(), argv.end()); + // Expanding lists on an empty command may have left it empty + if (argv.empty()) { + argv.emplace_back(); + } + } // Check whether the command executable is a target whose name is to // be translated. - std::string exe = command[0]; + std::string exe = argv[0]; cmGeneratorTarget* target = this->LG->FindGeneratorTargetToUse(exe); if (target && target->GetType() == cmStateEnums::EXECUTABLE) { // Use the target file on disk. @@ -90,8 +102,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, // Prepend with the emulator when cross compiling if required. const char* emulator = target->GetProperty("CROSSCOMPILING_EMULATOR"); if (emulator != nullptr && *emulator) { - std::vector<std::string> emulatorWithArgs; - cmSystemTools::ExpandListArgument(emulator, emulatorWithArgs); + std::vector<std::string> emulatorWithArgs = cmExpandedList(emulator); std::string emulatorExe(emulatorWithArgs[0]); cmSystemTools::ConvertToUnixSlashes(emulatorExe); os << cmOutputConverter::EscapeForCMake(emulatorExe) << " "; @@ -101,29 +112,26 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, } } else { // Use the command name given. - exe = ge.Parse(exe)->Evaluate(this->LG, config); cmSystemTools::ConvertToUnixSlashes(exe); } // Generate the command line with full escapes. os << cmOutputConverter::EscapeForCMake(exe); - for (std::string const& arg : cmMakeRange(command).advance(1)) { - os << " " - << cmOutputConverter::EscapeForCMake( - ge.Parse(arg)->Evaluate(this->LG, config)); + + for (auto const& arg : cmMakeRange(argv).advance(1)) { + os << " " << cmOutputConverter::EscapeForCMake(arg); } // Finish the test command. os << ")\n"; // Output properties for the test. - cmPropertyMap& pm = this->Test->GetProperties(); os << indent << "set_tests_properties(" << this->Test->GetName() << " PROPERTIES "; - for (auto const& i : pm) { + for (auto const& i : this->Test->GetProperties().GetList()) { os << " " << i.first << " " << cmOutputConverter::EscapeForCMake( - ge.Parse(i.second.GetValue())->Evaluate(this->LG, config)); + ge.Parse(i.second)->Evaluate(this->LG, config)); } this->GenerateInternalProperties(os); os << ")" << std::endl; @@ -173,12 +181,11 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout, Indent indent) fout << ")" << std::endl; // Output properties for the test. - cmPropertyMap& pm = this->Test->GetProperties(); fout << indent << "set_tests_properties(" << this->Test->GetName() << " PROPERTIES "; - for (auto const& i : pm) { + for (auto const& i : this->Test->GetProperties().GetList()) { fout << " " << i.first << " " - << cmOutputConverter::EscapeForCMake(i.second.GetValue()); + << cmOutputConverter::EscapeForCMake(i.second); } this->GenerateInternalProperties(fout); fout << ")" << std::endl; @@ -208,3 +215,16 @@ void cmTestGenerator::GenerateInternalProperties(std::ostream& os) os << "\""; } + +std::vector<std::string> cmTestGenerator::EvaluateCommandLineArguments( + const std::vector<std::string>& argv, cmGeneratorExpression& ge, + const std::string& config) const +{ + // Evaluate executable name and arguments + auto evaluatedRange = + cmMakeRange(argv).transform([&](const std::string& arg) { + return ge.Parse(arg)->Evaluate(this->LG, config); + }); + + return { evaluatedRange.begin(), evaluatedRange.end() }; +} diff --git a/Source/cmTestGenerator.h b/Source/cmTestGenerator.h index 8b9cf78..7ac68eb 100644 --- a/Source/cmTestGenerator.h +++ b/Source/cmTestGenerator.h @@ -11,6 +11,7 @@ #include <string> #include <vector> +class cmGeneratorExpression; class cmLocalGenerator; class cmTest; @@ -38,6 +39,9 @@ public: private: void GenerateInternalProperties(std::ostream& os); + std::vector<std::string> EvaluateCommandLineArguments( + const std::vector<std::string>& argv, cmGeneratorExpression& ge, + const std::string& config) const; protected: void GenerateScriptConfigs(std::ostream& os, Indent indent) override; diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index da5d21e..a9be729 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -6,6 +6,7 @@ #include <sstream> #include <stdlib.h> +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" std::string cmTimestamp::CurrentTime(const std::string& formatString, @@ -109,7 +110,7 @@ time_t cmTimestamp::CreateUtcTimeTFromTm(struct tm& tm) const time_t result = mktime(&tm); -# ifdef CMAKE_BUILD_WITH_CMAKE +# ifndef CMAKE_BOOTSTRAP if (tz_was_set) { cmSystemTools::PutEnv(tz_old); } else { @@ -131,8 +132,7 @@ std::string cmTimestamp::AddTimestampComponent(char flag, struct tm& timeStruct, const time_t timeT) const { - std::string formatString = "%"; - formatString += flag; + std::string formatString = cmStrCat('%', flag); switch (flag) { case 'a': @@ -168,9 +168,7 @@ std::string cmTimestamp::AddTimestampComponent(char flag, return std::string(); } - std::ostringstream ss; - ss << static_cast<long int>(difftime(timeT, unixEpoch)); - return ss.str(); + return std::to_string(static_cast<long int>(difftime(timeT, unixEpoch))); } default: { return formatString; diff --git a/Source/cmTryCompileCommand.h b/Source/cmTryCompileCommand.h index 8237878..ec9f8b8 100644 --- a/Source/cmTryCompileCommand.h +++ b/Source/cmTryCompileCommand.h @@ -8,9 +8,11 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + +#include "cmCommand.h" #include "cmCoreTryCompile.h" -class cmCommand; class cmExecutionStatus; /** \class cmTryCompileCommand @@ -24,7 +26,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmTryCompileCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmTryCompileCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index a92c2a0..24d0f0f 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -11,6 +11,7 @@ #include "cmRange.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" @@ -137,7 +138,7 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv, // now put the output into the variables if (!this->RunOutputVariable.empty()) { this->Makefile->AddDefinition(this->RunOutputVariable, - runOutputContents.c_str()); + runOutputContents); } if (!this->OutputVariable.empty()) { @@ -148,8 +149,7 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv, if (compileOutput) { runOutputContents = compileOutput + runOutputContents; } - this->Makefile->AddDefinition(this->OutputVariable, - runOutputContents.c_str()); + this->Makefile->AddDefinition(this->OutputVariable, runOutputContents); } } } @@ -170,8 +170,7 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs, const std::string& emulator = this->Makefile->GetSafeDefinition("CMAKE_CROSSCOMPILING_EMULATOR"); if (!emulator.empty()) { - std::vector<std::string> emulatorWithArgs; - cmSystemTools::ExpandListArgument(emulator, emulatorWithArgs); + std::vector<std::string> emulatorWithArgs = cmExpandedList(emulator); finalCommand += cmSystemTools::ConvertToRunCommandPath(emulatorWithArgs[0]); finalCommand += " "; @@ -214,20 +213,17 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, // copy the executable out of the CMakeFiles/ directory, so it is not // removed at the end of TRY_RUN and the user can run it manually // on the target platform. - std::string copyDest = this->Makefile->GetHomeOutputDirectory(); - copyDest += "/CMakeFiles"; - copyDest += "/"; - copyDest += cmSystemTools::GetFilenameWithoutExtension(this->OutputFile); - copyDest += "-"; - copyDest += this->RunResultVariable; - copyDest += cmSystemTools::GetFilenameExtension(this->OutputFile); + std::string copyDest = + cmStrCat(this->Makefile->GetHomeOutputDirectory(), "/CMakeFiles/", + cmSystemTools::GetFilenameWithoutExtension(this->OutputFile), '-', + this->RunResultVariable, + cmSystemTools::GetFilenameExtension(this->OutputFile)); cmSystemTools::CopyFileAlways(this->OutputFile, copyDest); - std::string resultFileName = this->Makefile->GetHomeOutputDirectory(); - resultFileName += "/TryRunResults.cmake"; + std::string resultFileName = + cmStrCat(this->Makefile->GetHomeOutputDirectory(), "/TryRunResults.cmake"); - std::string detailsString = "For details see "; - detailsString += resultFileName; + std::string detailsString = cmStrCat("For details see ", resultFileName); std::string internalRunOutputName = this->RunResultVariable + "__TRYRUN_OUTPUT"; @@ -236,10 +232,10 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, if (!this->Makefile->GetDefinition(this->RunResultVariable)) { // if the variables doesn't exist, create it with a helpful error text // and mark it as advanced - std::string comment; - comment += "Run result of TRY_RUN(), indicates whether the executable " - "would have been able to run on its target platform.\n"; - comment += detailsString; + std::string comment = + cmStrCat("Run result of TRY_RUN(), indicates whether the executable " + "would have been able to run on its target platform.\n", + detailsString); this->Makefile->AddCacheDefinition(this->RunResultVariable, "PLEASE_FILL_OUT-FAILED_TO_RUN", comment.c_str(), cmStateEnums::STRING); @@ -259,11 +255,10 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, if (!this->Makefile->GetDefinition(internalRunOutputName)) { // if the variables doesn't exist, create it with a helpful error text // and mark it as advanced - std::string comment; - comment += + std::string comment = cmStrCat( "Output of TRY_RUN(), contains the text, which the executable " - "would have printed on stdout and stderr on its target platform.\n"; - comment += detailsString; + "would have printed on stdout and stderr on its target platform.\n", + detailsString); this->Makefile->AddCacheDefinition( internalRunOutputName, "PLEASE_FILL_OUT-NOTFOUND", comment.c_str(), @@ -295,15 +290,15 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, /* clang-format on */ } - std::string comment = "\n"; - comment += this->RunResultVariable; - comment += "\n indicates whether the executable would have been able " + std::string comment = + cmStrCat('\n', this->RunResultVariable, + "\n indicates whether the executable would have been able " "to run on its\n" - " target platform. If so, set "; - comment += this->RunResultVariable; - comment += " to\n" + " target platform. If so, set ", + this->RunResultVariable, + " to\n" " the exit code (in many cases 0 for success), otherwise " - "enter \"FAILED_TO_RUN\".\n"; + "enter \"FAILED_TO_RUN\".\n"); if (out) { comment += internalRunOutputName; comment += @@ -344,10 +339,11 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, } firstTryRun = false; - std::string errorMessage = "TRY_RUN() invoked in cross-compiling mode, " - "please set the following cache variables " - "appropriately:\n"; - errorMessage += " " + this->RunResultVariable + " (advanced)\n"; + std::string errorMessage = + cmStrCat("TRY_RUN() invoked in cross-compiling mode, " + "please set the following cache variables " + "appropriately:\n ", + this->RunResultVariable, " (advanced)\n"); if (out) { errorMessage += " " + internalRunOutputName + " (advanced)\n"; } diff --git a/Source/cmTryRunCommand.h b/Source/cmTryRunCommand.h index c54622c..bacfcdb 100644 --- a/Source/cmTryRunCommand.h +++ b/Source/cmTryRunCommand.h @@ -8,9 +8,11 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + +#include "cmCommand.h" #include "cmCoreTryCompile.h" -class cmCommand; class cmExecutionStatus; /** \class cmTryRunCommand @@ -24,7 +26,10 @@ public: /** * This is a virtual constructor for the command. */ - cmCommand* Clone() override { return new cmTryRunCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmTryRunCommand>(); + } /** * This is called when the command is first encountered in diff --git a/Source/cmUVHandlePtr.cxx b/Source/cmUVHandlePtr.cxx index db67463..97c27cb 100644 --- a/Source/cmUVHandlePtr.cxx +++ b/Source/cmUVHandlePtr.cxx @@ -122,7 +122,7 @@ uv_handle_ptr_<T>::operator T*() const return this->handle.get(); } -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP template <> struct uv_handle_deleter<uv_async_t> { @@ -230,7 +230,7 @@ int uv_timer_ptr::start(uv_timer_cb cb, uint64_t timeout, uint64_t repeat) return uv_timer_start(*this, cb, timeout, repeat); } -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP uv_tty_ptr::operator uv_stream_t*() const { return reinterpret_cast<uv_stream_t*>(handle.get()); @@ -259,7 +259,7 @@ UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(process) UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(timer) -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(async) UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(tty) diff --git a/Source/cmUVProcessChain.cxx b/Source/cmUVProcessChain.cxx index 90ece0b..56d6c09 100644 --- a/Source/cmUVProcessChain.cxx +++ b/Source/cmUVProcessChain.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmUVProcessChain.h" -#include "cmAlgorithms.h" #include "cmGetPipes.h" #include "cmUVHandlePtr.h" #include "cmUVStreambuf.h" @@ -10,10 +9,12 @@ #include <assert.h> +#include <istream> // IWYU pragma: keep #include <iterator> -#include <memory> #include <utility> +#include "cm_memory.hxx" + struct cmUVProcessChain::InternalData { struct BasicStreamData diff --git a/Source/cmUVProcessChain.h b/Source/cmUVProcessChain.h index 2b33520..75f8f66 100644 --- a/Source/cmUVProcessChain.h +++ b/Source/cmUVProcessChain.h @@ -7,7 +7,7 @@ #include <array> #include <iosfwd> -#include <memory> // IWYU pragma: keep +#include <memory> #include <string> #include <vector> diff --git a/Source/cmUnexpectedCommand.cxx b/Source/cmUnexpectedCommand.cxx deleted file mode 100644 index a8de9e6..0000000 --- a/Source/cmUnexpectedCommand.cxx +++ /dev/null @@ -1,22 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmUnexpectedCommand.h" - -#include <stdlib.h> - -#include "cmMakefile.h" - -class cmExecutionStatus; - -bool cmUnexpectedCommand::InitialPass(std::vector<std::string> const&, - cmExecutionStatus&) -{ - const char* versionValue = - this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION"); - if (this->Name == "endif" && (!versionValue || atof(versionValue) <= 1.4)) { - return true; - } - - this->SetError(this->Error); - return false; -} diff --git a/Source/cmUnexpectedCommand.h b/Source/cmUnexpectedCommand.h deleted file mode 100644 index 33d6bdc..0000000 --- a/Source/cmUnexpectedCommand.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmUnexpectedCommand_h -#define cmUnexpectedCommand_h - -#include "cmConfigure.h" // IWYU pragma: keep - -#include <string> -#include <utility> -#include <vector> - -#include "cmCommand.h" - -class cmExecutionStatus; - -class cmUnexpectedCommand : public cmCommand -{ -public: - cmUnexpectedCommand(std::string name, const char* error) - : Name(std::move(name)) - , Error(error) - { - } - - cmCommand* Clone() override - { - return new cmUnexpectedCommand(this->Name, this->Error); - } - - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - std::string Name; - const char* Error; -}; - -#endif diff --git a/Source/cmUnsetCommand.cxx b/Source/cmUnsetCommand.cxx index cfaa1fd2..3ba95e9 100644 --- a/Source/cmUnsetCommand.cxx +++ b/Source/cmUnsetCommand.cxx @@ -2,18 +2,17 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmUnsetCommand.h" -#include "cmAlgorithms.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" -class cmExecutionStatus; - // cmUnsetCommand -bool cmUnsetCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmUnsetCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty() || args.size() > 2) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } @@ -24,27 +23,27 @@ bool cmUnsetCommand::InitialPass(std::vector<std::string> const& args, // what is the variable name auto const& envVarName = variable.substr(4, variable.size() - 5); -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP cmSystemTools::UnsetEnv(envVarName.c_str()); #endif return true; } // unset(VAR) if (args.size() == 1) { - this->Makefile->RemoveDefinition(variable); + status.GetMakefile().RemoveDefinition(variable); return true; } // unset(VAR CACHE) if ((args.size() == 2) && (args[1] == "CACHE")) { - this->Makefile->RemoveCacheDefinition(variable); + status.GetMakefile().RemoveCacheDefinition(variable); return true; } // unset(VAR PARENT_SCOPE) if ((args.size() == 2) && (args[1] == "PARENT_SCOPE")) { - this->Makefile->RaiseScope(variable, nullptr); + status.GetMakefile().RaiseScope(variable, nullptr); return true; } // ERROR: second argument isn't CACHE or PARENT_SCOPE - this->SetError("called with an invalid second argument"); + status.SetError("called with an invalid second argument"); return false; } diff --git a/Source/cmUnsetCommand.h b/Source/cmUnsetCommand.h index 4e1208a..be4c166 100644 --- a/Source/cmUnsetCommand.h +++ b/Source/cmUnsetCommand.h @@ -8,29 +8,14 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmUnsetCommand +/** * \brief Unset a CMAKE variable * * cmUnsetCommand unsets or removes a variable. */ -class cmUnsetCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmUnsetCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmUnsetCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx index 4358194..3d83760 100644 --- a/Source/cmUseMangledMesaCommand.cxx +++ b/Source/cmUseMangledMesaCommand.cxx @@ -5,6 +5,7 @@ #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmExecutionStatus; @@ -20,13 +21,9 @@ bool cmUseMangledMesaCommand::InitialPass(std::vector<std::string> const& args, return false; } const std::string& inputDir = args[0]; - std::string glh = inputDir; - glh += "/"; - glh += "gl.h"; + std::string glh = cmStrCat(inputDir, "/gl.h"); if (!cmSystemTools::FileExists(glh)) { - std::string e = "Bad path to Mesa, could not find: "; - e += glh; - e += " "; + std::string e = cmStrCat("Bad path to Mesa, could not find: ", glh, ' '); this->SetError(e); return false; } @@ -39,9 +36,7 @@ bool cmUseMangledMesaCommand::InitialPass(std::vector<std::string> const& args, } cmSystemTools::MakeDirectory(destDir); for (std::string const& f : files) { - std::string path = inputDir; - path += "/"; - path += f; + std::string path = cmStrCat(inputDir, '/', f); this->CopyAndFullPathMesaHeader(path, destDir); } @@ -51,13 +46,11 @@ bool cmUseMangledMesaCommand::InitialPass(std::vector<std::string> const& args, void cmUseMangledMesaCommand::CopyAndFullPathMesaHeader( const std::string& source, const std::string& outdir) { - std::string dir, file; + std::string dir; + std::string file; cmSystemTools::SplitProgramPath(source, dir, file); - std::string outFile = outdir; - outFile += "/"; - outFile += file; - std::string tempOutputFile = outFile; - tempOutputFile += ".tmp"; + std::string outFile = cmStrCat(outdir, '/', file); + std::string tempOutputFile = cmStrCat(outFile, ".tmp"); cmsys::ofstream fout(tempOutputFile.c_str()); if (!fout) { cmSystemTools::Error("Could not open file for write in copy operation: " + diff --git a/Source/cmUseMangledMesaCommand.h b/Source/cmUseMangledMesaCommand.h index e2f1d9b..1c01596 100644 --- a/Source/cmUseMangledMesaCommand.h +++ b/Source/cmUseMangledMesaCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -15,7 +17,10 @@ class cmExecutionStatus; class cmUseMangledMesaCommand : public cmCommand { public: - cmCommand* Clone() override { return new cmUseMangledMesaCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmUseMangledMesaCommand>(); + } bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx index b59a587..d255b67 100644 --- a/Source/cmUtilitySourceCommand.cxx +++ b/Source/cmUtilitySourceCommand.cxx @@ -7,6 +7,7 @@ #include "cmMakefile.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmExecutionStatus; @@ -35,11 +36,11 @@ bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args, if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING")) { haveCacheValue = (cacheValue != nullptr); if (!haveCacheValue) { - std::string msg = "UTILITY_SOURCE is used in cross compiling mode for "; - msg += cacheEntry; - msg += ". If your intention is to run this executable, you need to " - "preload the cache with the full path to a version of that " - "program, which runs on this build machine."; + std::string msg = cmStrCat( + "UTILITY_SOURCE is used in cross compiling mode for ", cacheEntry, + ". If your intention is to run this executable, you need to " + "preload the cache with the full path to a version of that " + "program, which runs on this build machine."); cmSystemTools::Message(msg, "Warning"); } } else { diff --git a/Source/cmUtilitySourceCommand.h b/Source/cmUtilitySourceCommand.h index 165ecef..cef7fed 100644 --- a/Source/cmUtilitySourceCommand.h +++ b/Source/cmUtilitySourceCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -15,7 +17,10 @@ class cmExecutionStatus; class cmUtilitySourceCommand : public cmCommand { public: - cmCommand* Clone() override { return new cmUtilitySourceCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmUtilitySourceCommand>(); + } bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; }; diff --git a/Source/cmUuid.cxx b/Source/cmUuid.cxx index 51ecbd1..0dc6ca7 100644 --- a/Source/cmUuid.cxx +++ b/Source/cmUuid.cxx @@ -114,14 +114,12 @@ std::string cmUuid::BinaryToString(const unsigned char* input) const std::string cmUuid::ByteToHex(unsigned char byte) const { - std::string result; + std::string result(" "); for (int i = 0; i < 2; ++i) { unsigned char rest = byte % 16; byte /= 16; - char c = (rest < 0xA) ? char('0' + rest) : char('a' + (rest - 0xA)); - - result = c + result; + result.at(1 - i) = c; } return result; diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx index c78361e..707ceac 100644 --- a/Source/cmVSSetupHelper.cxx +++ b/Source/cmVSSetupHelper.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmVSSetupHelper.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmsys/Encoding.hxx" #include "cmsys/FStream.hxx" @@ -195,7 +196,7 @@ bool cmVSSetupAPIHelper::GetVSInstanceInfo( if (!fin || !cmSystemTools::GetLineFromStream(fin, vcToolsVersion)) { return false; } - vcToolsVersion = cmSystemTools::TrimWhitespace(vcToolsVersion); + vcToolsVersion = cmTrimWhitespace(vcToolsVersion); std::string const vcToolsDir = vcRoot + "/VC/Tools/MSVC/" + vcToolsVersion; if (!cmSystemTools::FileIsDirectory(vcToolsDir)) { return false; @@ -364,8 +365,8 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance() // We are not looking for a specific instance. // If we've been given a hint then use it. if (!envVSCommonToolsDir.empty()) { - std::string currentVSLocation = instanceInfo.GetInstallLocation(); - currentVSLocation += "/Common7/Tools"; + std::string currentVSLocation = + cmStrCat(instanceInfo.GetInstallLocation(), "/Common7/Tools"); if (cmSystemTools::ComparePath(currentVSLocation, envVSCommonToolsDir)) { chosenInstanceInfo = instanceInfo; diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h index 1bda54a..ad46c75 100644 --- a/Source/cmVSSetupHelper.h +++ b/Source/cmVSSetupHelper.h @@ -74,26 +74,8 @@ class SmartBSTR { public: SmartBSTR() { str = NULL; } - SmartBSTR(const SmartBSTR& src) - { - if (src.str != NULL) { - str = ::SysAllocStringByteLen((char*)str, ::SysStringByteLen(str)); - } else { - str = ::SysAllocStringByteLen(NULL, 0); - } - } - SmartBSTR& operator=(const SmartBSTR& src) - { - if (str != src.str) { - ::SysFreeString(str); - if (src.str != NULL) { - str = ::SysAllocStringByteLen((char*)str, ::SysStringByteLen(str)); - } else { - str = ::SysAllocStringByteLen(NULL, 0); - } - } - return *this; - } + SmartBSTR(const SmartBSTR& src) = delete; + SmartBSTR& operator=(const SmartBSTR& src) = delete; operator BSTR() const { return str; } BSTR* operator&() throw() { return &str; } ~SmartBSTR() throw() { ::SysFreeString(str); } diff --git a/Source/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx index c02157a..c44eeca 100644 --- a/Source/cmVariableRequiresCommand.cxx +++ b/Source/cmVariableRequiresCommand.cxx @@ -4,6 +4,7 @@ #include "cmMakefile.h" #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmExecutionStatus; @@ -42,16 +43,15 @@ bool cmVariableRequiresCommand::InitialPass( // if reqVar is set to true, but requirementsMet is false , then // set reqVar to false. if (!reqVar || (!requirementsMet && this->Makefile->IsOn(reqVar))) { - this->Makefile->AddDefinition(resultVariable, requirementsMet); + this->Makefile->AddDefinitionBool(resultVariable, requirementsMet); } if (!requirementsMet) { - std::string message = "Variable assertion failed:\n"; - message += - testVariable + " Requires that the following unset variables are set:\n"; - message += notSet; - message += "\nPlease set them, or set "; - message += testVariable + " to false, and re-configure.\n"; + std::string message = + cmStrCat("Variable assertion failed:\n", testVariable, + " Requires that the following unset variables are set:\n", + notSet, "\nPlease set them, or set ", testVariable, + " to false, and re-configure.\n"); if (hasAdvanced) { message += "One or more of the required variables is advanced." diff --git a/Source/cmVariableRequiresCommand.h b/Source/cmVariableRequiresCommand.h index 94970c5..38e7490 100644 --- a/Source/cmVariableRequiresCommand.h +++ b/Source/cmVariableRequiresCommand.h @@ -8,6 +8,8 @@ #include <string> #include <vector> +#include "cm_memory.hxx" + #include "cmCommand.h" class cmExecutionStatus; @@ -15,7 +17,10 @@ class cmExecutionStatus; class cmVariableRequiresCommand : public cmCommand { public: - cmCommand* Clone() override { return new cmVariableRequiresCommand; } + std::unique_ptr<cmCommand> Clone() override + { + return cm::make_unique<cmVariableRequiresCommand>(); + } bool InitialPass(std::vector<std::string> const& args, cmExecutionStatus& status) override; }; diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h index 1230101..acac2c1 100644 --- a/Source/cmVariableWatch.h +++ b/Source/cmVariableWatch.h @@ -6,7 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <map> -#include <memory> // IWYU pragma: keep +#include <memory> #include <string> #include <vector> diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx index 5fe55bd..db23efd 100644 --- a/Source/cmVariableWatchCommand.cxx +++ b/Source/cmVariableWatchCommand.cxx @@ -2,7 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmVariableWatchCommand.h" +#include <memory> #include <sstream> +#include <utility> #include "cmExecutionStatus.h" #include "cmListFileCache.h" @@ -54,7 +56,7 @@ static void cmVariableWatchCommandVariableAccessed(const std::string& variable, newLFF.Arguments.emplace_back(stack, cmListFileArgument::Quoted, 9999); newLFF.Name = data->Command; newLFF.Line = 9999; - cmExecutionStatus status; + cmExecutionStatus status(*makefile); if (!makefile->ExecuteCommand(newLFF, status)) { std::ostringstream error; error << "Error in cmake code at\nUnknown:0:\n" @@ -84,21 +86,45 @@ static void deleteVariableWatchCallbackData(void* client_data) delete data; } -cmVariableWatchCommand::cmVariableWatchCommand() = default; - -cmVariableWatchCommand::~cmVariableWatchCommand() +/** This command does not really have a final pass but it needs to + stay alive since it owns variable watch callback information. */ +class FinalAction { - for (std::string const& wv : this->WatchedVariables) { - this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch( - wv, cmVariableWatchCommandVariableAccessed); +public: + FinalAction(cmMakefile* makefile, std::string variable) + : Action(std::make_shared<Impl>(makefile, std::move(variable))) + { } -} -bool cmVariableWatchCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) + void operator()(cmMakefile&) const {} + +private: + struct Impl + { + Impl(cmMakefile* makefile, std::string variable) + : Makefile(makefile) + , Variable(std::move(variable)) + { + } + + ~Impl() + { + this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch( + this->Variable, cmVariableWatchCommandVariableAccessed); + } + + cmMakefile* Makefile; + std::string Variable; + }; + + std::shared_ptr<Impl const> Action; +}; + +bool cmVariableWatchCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("must be called with at least one argument."); + status.SetError("must be called with at least one argument."); return false; } std::string const& variable = args[0]; @@ -109,7 +135,7 @@ bool cmVariableWatchCommand::InitialPass(std::vector<std::string> const& args, if (variable == "CMAKE_CURRENT_LIST_FILE") { std::ostringstream ostr; ostr << "cannot be set on the variable: " << variable; - this->SetError(ostr.str()); + status.SetError(ostr.str()); return false; } @@ -118,13 +144,14 @@ bool cmVariableWatchCommand::InitialPass(std::vector<std::string> const& args, data->InCallback = false; data->Command = command; - this->WatchedVariables.insert(variable); - if (!this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch( + if (!status.GetMakefile().GetCMakeInstance()->GetVariableWatch()->AddWatch( variable, cmVariableWatchCommandVariableAccessed, data, deleteVariableWatchCallbackData)) { deleteVariableWatchCallbackData(data); return false; } + status.GetMakefile().AddFinalAction( + FinalAction(&status.GetMakefile(), variable)); return true; } diff --git a/Source/cmVariableWatchCommand.h b/Source/cmVariableWatchCommand.h index 6a8115d..3f9f244 100644 --- a/Source/cmVariableWatchCommand.h +++ b/Source/cmVariableWatchCommand.h @@ -5,45 +5,16 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <set> #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmVariableWatchCommand +/** * \brief Watch when the variable changes and invoke command * */ -class cmVariableWatchCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmVariableWatchCommand; } - - //! Default constructor - cmVariableWatchCommand(); - - //! Destructor. - ~cmVariableWatchCommand() override; - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - - /** This command does not really have a final pass but it needs to - stay alive since it owns variable watch callback information. */ - bool HasFinalPass() const override { return true; } - -protected: - std::set<std::string> WatchedVariables; -}; +bool cmVariableWatchCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 7d25713..13f6295 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -19,9 +19,10 @@ #include "windows.h" #include <iterator> -#include <memory> // IWYU pragma: keep #include <set> +#include "cm_memory.hxx" + static void ConvertToWindowsSlash(std::string& s); static std::string cmVS10EscapeXML(std::string arg) @@ -363,10 +364,9 @@ void cmVisualStudio10TargetGenerator::Generate() return; } } - std::string path = this->LocalGenerator->GetCurrentBinaryDirectory(); - path += "/"; - path += this->Name; - path += ProjectFileExtension; + std::string path = + cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/', + this->Name, ProjectFileExtension); cmGeneratedFileStream BuildFileStream(path); const std::string PathToProjectFile = path; BuildFileStream.SetCopyIfDifferent(true); @@ -505,6 +505,11 @@ void cmVisualStudio10TargetGenerator::Generate() if (targetFrameworkVersion) { e1.Element("TargetFrameworkVersion", targetFrameworkVersion); } + if (this->ProjectType == vcxproj && + this->GlobalGenerator->TargetsWindowsCE()) { + e1.Element("EnableRedirectPlatform", "true"); + e1.Element("RedirectPlatformValue", this->Platform); + } if (this->ProjectType == csproj && this->GlobalGenerator->TargetsWindowsCE()) { const char* targetFrameworkId = this->GeneratorTarget->GetProperty( @@ -622,9 +627,8 @@ void cmVisualStudio10TargetGenerator::Generate() std::string propsTemplate = GetCMakeFilePath("Templates/MSBuild/nasm.props.in"); - std::string propsLocal; - propsLocal += this->DefaultArtifactDir; - propsLocal += "\\nasm.props"; + std::string propsLocal = + cmStrCat(this->DefaultArtifactDir, "\\nasm.props"); ConvertToWindowsSlash(propsLocal); this->Makefile->ConfigureFile(propsTemplate, propsLocal, false, true, true); @@ -744,7 +748,7 @@ void cmVisualStudio10TargetGenerator::WritePackageReferences(Elem& e0) std::vector<std::string> packageReferences; if (const char* vsPackageReferences = this->GeneratorTarget->GetProperty("VS_PACKAGE_REFERENCES")) { - cmSystemTools::ExpandListArgument(vsPackageReferences, packageReferences); + cmExpandList(vsPackageReferences, packageReferences); } if (!packageReferences.empty()) { Elem e1(e0, "ItemGroup"); @@ -771,14 +775,14 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0) std::vector<std::string> references; if (const char* vsDotNetReferences = this->GeneratorTarget->GetProperty("VS_DOTNET_REFERENCES")) { - cmSystemTools::ExpandListArgument(vsDotNetReferences, references); + cmExpandList(vsDotNetReferences, references); } cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties(); - for (auto const& i : props) { + for (auto const& i : props.GetList()) { if (i.first.find("VS_DOTNET_REFERENCE_") == 0) { std::string name = i.first.substr(20); if (!name.empty()) { - std::string path = i.second.GetValue(); + std::string path = i.second; if (!cmsys::SystemTools::FileIsFullPath(path)) { path = this->Makefile->GetCurrentSourceDirectory() + "/" + path; } @@ -832,7 +836,7 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReference( const char* privateReference = "True"; if (const char* value = this->GeneratorTarget->GetProperty( "VS_DOTNET_REFERENCES_COPY_LOCAL")) { - if (cmSystemTools::IsOff(value)) { + if (cmIsOff(value)) { privateReference = "False"; } } @@ -847,8 +851,8 @@ void cmVisualStudio10TargetGenerator::WriteImports(Elem& e0) const char* imports = this->GeneratorTarget->Target->GetProperty("VS_PROJECT_IMPORT"); if (imports) { - std::vector<std::string> argsSplit; - cmSystemTools::ExpandListArgument(std::string(imports), argsSplit, false); + std::vector<std::string> argsSplit = + cmExpandedList(std::string(imports), false); for (auto& path : argsSplit) { if (!cmsys::SystemTools::FileIsFullPath(path)) { path = this->Makefile->GetCurrentSourceDirectory() + "/" + path; @@ -870,10 +874,10 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferenceCustomTags( typedef std::map<std::string, std::string> CustomTags; CustomTags tags; cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties(); - for (const auto& i : props) { + for (const auto& i : props.GetList()) { if (i.first.find(refPropFullPrefix) == 0) { std::string refTag = i.first.substr(refPropFullPrefix.length()); - std::string refVal = i.second.GetValue(); + std::string refVal = i.second; if (!refTag.empty() && !refVal.empty()) { tags[refTag] = refVal; } @@ -967,12 +971,12 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0) } } const cmPropertyMap& props = oi->GetProperties(); - for (const auto& p : props) { + for (const std::string& p : props.GetKeys()) { static const std::string propNamePrefix = "VS_CSHARP_"; - if (p.first.find(propNamePrefix) == 0) { - std::string tagName = p.first.substr(propNamePrefix.length()); + if (p.find(propNamePrefix) == 0) { + std::string tagName = p.substr(propNamePrefix.length()); if (!tagName.empty()) { - std::string value = props.GetPropertyValue(p.first); + std::string value = props.GetPropertyValue(p); if (!value.empty()) { e2.Element(tagName.c_str(), value); } @@ -1068,7 +1072,7 @@ void cmVisualStudio10TargetGenerator::WriteWinRTReferences(Elem& e0) std::vector<std::string> references; if (const char* vsWinRTReferences = this->GeneratorTarget->GetProperty("VS_WINRT_REFERENCES")) { - cmSystemTools::ExpandListArgument(vsWinRTReferences, references); + cmExpandList(vsWinRTReferences, references); } if (this->GlobalGenerator->TargetsWindowsPhone() && @@ -1266,8 +1270,8 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged( e1.Element("PlatformToolset", toolset); } - std::string postfixName = cmSystemTools::UpperCase(config); - postfixName += "_POSTFIX"; + std::string postfixName = + cmStrCat(cmSystemTools::UpperCase(config), "_POSTFIX"); std::string assemblyName = this->GeneratorTarget->GetOutputName( config, cmStateEnums::RuntimeBinaryArtifact); if (const char* postfix = this->GeneratorTarget->GetProperty(postfixName)) { @@ -1372,9 +1376,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( // preventing dependent rebuilds. this->ForceOld(sourcePath); } else { - std::string error = "Could not create file: ["; - error += sourcePath; - error += "] "; + std::string error = + cmStrCat("Could not create file: [", sourcePath, "] "); cmSystemTools::Error(error + cmSystemTools::GetLastSystemError()); } } @@ -1543,11 +1546,9 @@ void cmVisualStudio10TargetGenerator::WriteGroups() this->AddMissingSourceGroups(groupsUsed, sourceGroups); // Write out group file - std::string path = this->LocalGenerator->GetCurrentBinaryDirectory(); - path += "/"; - path += this->Name; - path += computeProjectFileExtension(this->GeneratorTarget); - path += ".filters"; + std::string path = cmStrCat( + this->LocalGenerator->GetCurrentBinaryDirectory(), '/', this->Name, + computeProjectFileExtension(this->GeneratorTarget), ".filters"); cmGeneratedFileStream fout(path); fout.SetCopyIfDifferent(true); char magic[] = { char(0xEF), char(0xBB), char(0xBF) }; @@ -1942,11 +1943,11 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, const std::string& enableDebug = cge->Evaluate(this->LocalGenerator, this->Configurations[i]); if (!enableDebug.empty()) { - e2.WritePlatformConfigTag( - "EnableDebuggingInformation", - "'$(Configuration)|$(Platform)'=='" + this->Configurations[i] + - "|" + this->Platform + "'", - cmSystemTools::IsOn(enableDebug) ? "true" : "false"); + e2.WritePlatformConfigTag("EnableDebuggingInformation", + "'$(Configuration)|$(Platform)'=='" + + this->Configurations[i] + "|" + + this->Platform + "'", + cmIsOn(enableDebug) ? "true" : "false"); } } } @@ -1963,7 +1964,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, "DisableOptimizations", "'$(Configuration)|$(Platform)'=='" + this->Configurations[i] + "|" + this->Platform + "'", - (cmSystemTools::IsOn(disableOptimizations) ? "true" : "false")); + (cmIsOn(disableOptimizations) ? "true" : "false")); } } } @@ -2228,8 +2229,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( for (std::string const& config : this->Configurations) { std::string configUpper = cmSystemTools::UpperCase(config); std::string configDefines = defines; - std::string defPropName = "COMPILE_DEFINITIONS_"; - defPropName += configUpper; + std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper); if (const char* ccdefs = sf.GetProperty(defPropName)) { if (!configDefines.empty()) { configDefines += ";"; @@ -2419,17 +2419,14 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions( e1.WritePlatformConfigTag( "IntDir", cond, "$(Platform)\\$(Configuration)\\$(ProjectName)\\"); } else { - std::string intermediateDir = - this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); - intermediateDir += "/"; - intermediateDir += config; - intermediateDir += "/"; + std::string intermediateDir = cmStrCat( + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), '/', + config, '/'); std::string outDir; std::string targetNameFull; if (ttype == cmStateEnums::OBJECT_LIBRARY) { outDir = intermediateDir; - targetNameFull = this->GeneratorTarget->GetName(); - targetNameFull += ".lib"; + targetNameFull = cmStrCat(this->GeneratorTarget->GetName(), ".lib"); } else { outDir = this->GeneratorTarget->GetDirectory(config) + "/"; targetNameFull = this->GeneratorTarget->GetFullName(config); @@ -2597,8 +2594,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( std::string langForClCompile; if (this->ProjectType == csproj) { langForClCompile = "CSharp"; - } else if (std::find(cm::cbegin(clLangs), cm::cend(clLangs), linkLanguage) != - cm::cend(clLangs)) { + } else if (cmContains(clLangs, linkLanguage)) { langForClCompile = linkLanguage; } else { std::set<std::string> languages; @@ -2710,9 +2706,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( } // Add a definition for the configuration name. - std::string configDefine = "CMAKE_INTDIR=\""; - configDefine += configName; - configDefine += "\""; + std::string configDefine = cmStrCat("CMAKE_INTDIR=\"", configName, '"'); clOptions.AddDefine(configDefine); if (const std::string* exportMacro = this->GeneratorTarget->GetExportMacro()) { @@ -2737,7 +2731,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( } } if (const char* winRT = clOptions.GetFlag("CompileAsWinRT")) { - if (cmSystemTools::IsOn(winRT)) { + if (cmIsOn(winRT)) { this->TargetCompileAsWinRT = true; } } @@ -3007,9 +3001,7 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions( cudaOptions.AddDefines(targetDefines); // Add a definition for the configuration name. - std::string configDefine = "CMAKE_INTDIR=\""; - configDefine += configName; - configDefine += "\""; + std::string configDefine = cmStrCat("CMAKE_INTDIR=\"", configName, '"'); cudaOptions.AddDefine(configDefine); if (const std::string* exportMacro = this->GeneratorTarget->GetExportMacro()) { @@ -3250,15 +3242,32 @@ void cmVisualStudio10TargetGenerator::WriteManifestOptions( std::vector<cmSourceFile const*> manifest_srcs; this->GeneratorTarget->GetManifests(manifest_srcs, config); - if (!manifest_srcs.empty()) { - std::ostringstream oss; - for (cmSourceFile const* mi : manifest_srcs) { - std::string m = this->ConvertPath(mi->GetFullPath(), false); - ConvertToWindowsSlash(m); - oss << m << ";"; - } + + const char* dpiAware = this->GeneratorTarget->GetProperty("VS_DPI_AWARE"); + + if (!manifest_srcs.empty() || dpiAware) { Elem e2(e1, "Manifest"); - e2.Element("AdditionalManifestFiles", oss.str()); + if (!manifest_srcs.empty()) { + std::ostringstream oss; + for (cmSourceFile const* mi : manifest_srcs) { + std::string m = this->ConvertPath(mi->GetFullPath(), false); + ConvertToWindowsSlash(m); + oss << m << ";"; + } + e2.Element("AdditionalManifestFiles", oss.str()); + } + if (dpiAware) { + if (!strcmp(dpiAware, "PerMonitor")) { + e2.Element("EnableDpiAwareness", "PerMonitorHighDPIAware"); + } else if (cmIsOn(dpiAware)) { + e2.Element("EnableDpiAwareness", "true"); + } else if (cmIsOff(dpiAware)) { + e2.Element("EnableDpiAwareness", "false"); + } else { + cmSystemTools::Error("Bad parameter for VS_DPI_AWARE: " + + std::string(dpiAware)); + } + } } } @@ -3407,9 +3416,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( linkType = "EXE"; } std::string flags; - std::string linkFlagVarBase = "CMAKE_"; - linkFlagVarBase += linkType; - linkFlagVarBase += "_LINKER_FLAGS"; + std::string linkFlagVarBase = cmStrCat("CMAKE_", linkType, "_LINKER_FLAGS"); flags += " "; flags += this->Makefile->GetRequiredDefinition(linkFlagVarBase); std::string linkFlagVar = linkFlagVarBase + "_" + CONFIG; @@ -3421,8 +3428,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( flags += " "; flags += targetLinkFlags; } - std::string flagsProp = "LINK_FLAGS_"; - flagsProp += CONFIG; + std::string flagsProp = cmStrCat("LINK_FLAGS_", CONFIG); if (const char* flagsConfig = this->GeneratorTarget->GetProperty(flagsProp)) { flags += " "; @@ -3447,8 +3453,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( std::vector<std::string> libVec; std::vector<std::string> vsTargetVec; this->AddLibraries(cli, libVec, vsTargetVec, config); - if (std::find(linkClosure->Languages.begin(), linkClosure->Languages.end(), - "CUDA") != linkClosure->Languages.end() && + if (cmContains(linkClosure->Languages, "CUDA") && this->CudaOptions[config] != nullptr) { switch (this->CudaOptions[config]->GetCudaRuntime()) { case cmVisualStudioGeneratorOptions::CudaRuntimeStatic: @@ -3463,9 +3468,8 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( break; } } - std::string standardLibsVar = "CMAKE_"; - standardLibsVar += linkLanguage; - standardLibsVar += "_STANDARD_LIBRARIES"; + std::string standardLibsVar = + cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LIBRARIES"); std::string const& libs = this->Makefile->GetSafeDefinition(standardLibsVar); cmSystemTools::ParseWindowsCommandLine(libs.c_str(), libVec); linkOptions.AddFlag("AdditionalDependencies", libVec); @@ -3529,13 +3533,12 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( linkOptions.AddFlag("GenerateDebugInformation", "false"); - std::string pdb = this->GeneratorTarget->GetPDBDirectory(config); - pdb += "/"; - pdb += targetNames.PDB; - std::string imLib = this->GeneratorTarget->GetDirectory( - config, cmStateEnums::ImportLibraryArtifact); - imLib += "/"; - imLib += targetNames.ImportLibrary; + std::string pdb = cmStrCat(this->GeneratorTarget->GetPDBDirectory(config), + '/', targetNames.PDB); + std::string imLib = + cmStrCat(this->GeneratorTarget->GetDirectory( + config, cmStateEnums::ImportLibraryArtifact), + '/', targetNames.ImportLibrary); linkOptions.AddFlag("ImportLibrary", imLib); linkOptions.AddFlag("ProgramDataBaseFile", pdb); @@ -3735,8 +3738,7 @@ void cmVisualStudio10TargetGenerator::AddTargetsFileAndConfigPair( { for (TargetsFileAndConfigs& i : this->TargetsFileAndConfigsVec) { if (cmSystemTools::ComparePath(targetsFile, i.File)) { - if (std::find(i.Configs.begin(), i.Configs.end(), config) == - i.Configs.end()) { + if (!cmContains(i.Configs, config)) { i.Configs.push_back(config); } return; @@ -3918,10 +3920,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0) if (p) { path = p; } else { - path = lg->GetCurrentBinaryDirectory(); - path += "/"; - path += dt->GetName(); - path += computeProjectFileExtension(dt); + path = cmStrCat(lg->GetCurrentBinaryDirectory(), '/', dt->GetName(), + computeProjectFileExtension(dt)); } ConvertToWindowsSlash(path); Elem e2(e1, "ProjectReference"); @@ -4004,7 +4004,7 @@ void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0) std::unique_ptr<Elem> spe1; if (const char* vsSDKReferences = this->GeneratorTarget->GetProperty("VS_SDK_REFERENCES")) { - cmSystemTools::ExpandListArgument(vsSDKReferences, sdkReferences); + cmExpandList(vsSDKReferences, sdkReferences); spe1 = cm::make_unique<Elem>(e0, "ItemGroup"); for (std::string const& ri : sdkReferences) { Elem(*spe1, "SDKReference").Attribute("Include", ri); @@ -4679,12 +4679,12 @@ void cmVisualStudio10TargetGenerator::GetCSharpSourceProperties( { if (this->ProjectType == csproj) { const cmPropertyMap& props = sf->GetProperties(); - for (auto const& p : props) { + for (const std::string& p : props.GetKeys()) { static const std::string propNamePrefix = "VS_CSHARP_"; - if (p.first.find(propNamePrefix) == 0) { - std::string tagName = p.first.substr(propNamePrefix.length()); + if (p.find(propNamePrefix) == 0) { + std::string tagName = p.substr(propNamePrefix.length()); if (!tagName.empty()) { - const std::string val = props.GetPropertyValue(p.first); + const std::string val = props.GetPropertyValue(p); if (!val.empty()) { tags[tagName] = val; } else { @@ -4728,8 +4728,8 @@ std::string cmVisualStudio10TargetGenerator::GetCMakeFilePath( const char* relativeFilePath) const { // Always search in the standard modules location. - std::string path = cmSystemTools::GetCMakeRoot() + "/"; - path += relativeFilePath; + std::string path = + cmStrCat(cmSystemTools::GetCMakeRoot(), '/', relativeFilePath); ConvertToWindowsSlash(path); return path; diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index e1b0c70..3e423e9 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -193,7 +193,7 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration() std::string arch_name = arch[0]; std::vector<std::string> codes; if (!code.empty()) { - codes = cmSystemTools::tokenize(code[0], ","); + codes = cmTokenize(code[0], ","); } if (codes.empty()) { codes.push_back(arch_name); @@ -220,7 +220,7 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration() cmSystemTools::ReplaceString(entry, "]", ""); cmSystemTools::ReplaceString(entry, "\"", ""); - std::vector<std::string> codes = cmSystemTools::tokenize(entry, ","); + std::vector<std::string> codes = cmTokenize(entry, ","); if (codes.size() >= 2) { auto gencode_arch = cm::cbegin(codes); for (auto ci = gencode_arch + 1; ci != cm::cend(codes); ++ci) { @@ -325,9 +325,9 @@ void cmVisualStudioGeneratorOptions::ParseFinish() // "rtSingleThreadedDLL", "10", /libs:dll // "rtSingleThreadedDebug", "5", /dbglibs /libs:static // "rtSingleThreadedDebugDLL", "11", /dbglibs /libs:dll - std::string rl = "rtMultiThreaded"; - rl += this->FortranRuntimeDebug ? "Debug" : ""; - rl += this->FortranRuntimeDLL ? "DLL" : ""; + std::string rl = + cmStrCat("rtMultiThreaded", this->FortranRuntimeDebug ? "Debug" : "", + this->FortranRuntimeDLL ? "DLL" : ""); this->FlagMap["RuntimeLibrary"] = rl; } diff --git a/Source/cmVisualStudioSlnParser.cxx b/Source/cmVisualStudioSlnParser.cxx index 9353276..9eaee11 100644 --- a/Source/cmVisualStudioSlnParser.cxx +++ b/Source/cmVisualStudioSlnParser.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmVisualStudioSlnParser.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVisualStudioSlnData.h" #include "cmsys/FStream.hxx" @@ -192,8 +193,8 @@ bool cmVisualStudioSlnParser::State::Process( assert(!line.IsComment()); switch (this->Stack.top()) { case FileStateStart: - if (!cmSystemTools::StringStartsWith( - line.GetTag().c_str(), "Microsoft Visual Studio Solution File")) { + if (!cmHasLiteralPrefix(line.GetTag(), + "Microsoft Visual Studio Solution File")) { result.SetError(ResultErrorInputStructure, this->GetCurrentLine()); return false; } @@ -462,7 +463,7 @@ bool cmVisualStudioSlnParser::ParseImpl(std::istream& input, cmSlnData& output, if (!this->ParseBOM(input, line, state)) return false; do { - line = cmSystemTools::TrimWhitespace(line); + line = cmTrimWhitespace(line); if (line.empty()) continue; ParsedLine parsedLine; @@ -578,9 +579,9 @@ bool cmVisualStudioSlnParser::ParseKeyValuePair(const std::string& line, return true; } const std::string& key = line.substr(0, idxEqualSign); - parsedLine.SetTag(cmSystemTools::TrimWhitespace(key)); + parsedLine.SetTag(cmTrimWhitespace(key)); const std::string& value = line.substr(idxEqualSign + 1); - parsedLine.AddValue(cmSystemTools::TrimWhitespace(value)); + parsedLine.AddValue(cmTrimWhitespace(value)); return true; } @@ -589,18 +590,17 @@ bool cmVisualStudioSlnParser::ParseTag(const std::string& fullTag, { size_t idxLeftParen = fullTag.find('('); if (idxLeftParen == fullTag.npos) { - parsedLine.SetTag(cmSystemTools::TrimWhitespace(fullTag)); + parsedLine.SetTag(cmTrimWhitespace(fullTag)); return true; } - parsedLine.SetTag( - cmSystemTools::TrimWhitespace(fullTag.substr(0, idxLeftParen))); + parsedLine.SetTag(cmTrimWhitespace(fullTag.substr(0, idxLeftParen))); size_t idxRightParen = fullTag.rfind(')'); if (idxRightParen == fullTag.npos) { this->LastResult.SetError(ResultErrorInputStructure, state.GetCurrentLine()); return false; } - const std::string& arg = cmSystemTools::TrimWhitespace( + const std::string& arg = cmTrimWhitespace( fullTag.substr(idxLeftParen + 1, idxRightParen - idxLeftParen - 1)); if (arg.front() == '"') { if (arg.back() != '"') { @@ -617,7 +617,7 @@ bool cmVisualStudioSlnParser::ParseTag(const std::string& fullTag, bool cmVisualStudioSlnParser::ParseValue(const std::string& value, ParsedLine& parsedLine) { - const std::string& trimmed = cmSystemTools::TrimWhitespace(value); + const std::string& trimmed = cmTrimWhitespace(value); if (trimmed.empty()) parsedLine.AddValue(trimmed); else if (trimmed.front() == '"' && trimmed.back() == '"') diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx index a01fa6f..a396852 100644 --- a/Source/cmWhileCommand.cxx +++ b/Source/cmWhileCommand.cxx @@ -2,18 +2,45 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmWhileCommand.h" +#include "cm_memory.hxx" +#include "cm_static_string_view.hxx" +#include "cm_string_view.hxx" + #include "cmConditionEvaluator.h" #include "cmExecutionStatus.h" #include "cmExpandedCommandArgument.h" +#include "cmFunctionBlocker.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmSystemTools.h" -#include <memory> // IWYU pragma: keep +#include <string> +#include <utility> + +class cmWhileFunctionBlocker : public cmFunctionBlocker +{ +public: + cmWhileFunctionBlocker(cmMakefile* mf); + ~cmWhileFunctionBlocker() override; + + cm::string_view StartCommandName() const override { return "while"_s; } + cm::string_view EndCommandName() const override { return "endwhile"_s; } + + bool ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile& mf) const override; + + bool Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& inStatus) override; + + std::vector<cmListFileArgument> Args; + +private: + cmMakefile* Makefile; +}; cmWhileFunctionBlocker::cmWhileFunctionBlocker(cmMakefile* mf) : Makefile(mf) - , Depth(0) { this->Makefile->PushLoopBlock(); } @@ -23,122 +50,93 @@ cmWhileFunctionBlocker::~cmWhileFunctionBlocker() this->Makefile->PopLoopBlock(); } -bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, - cmMakefile& mf, - cmExecutionStatus& inStatus) +bool cmWhileFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile&) const { - // at end of for each execute recorded commands - if (lff.Name.Lower == "while") { - // record the number of while commands past this one - this->Depth++; - } else if (lff.Name.Lower == "endwhile") { - // if this is the endwhile for this while loop then execute - if (!this->Depth) { - // Remove the function blocker for this scope or bail. - std::unique_ptr<cmFunctionBlocker> fb( - mf.RemoveFunctionBlocker(this, lff)); - if (!fb) { - return false; - } + return lff.Arguments.empty() || lff.Arguments == this->Args; +} - std::string errorString; - - std::vector<cmExpandedCommandArgument> expandedArguments; - mf.ExpandArguments(this->Args, expandedArguments); - MessageType messageType; - - cmListFileContext execContext = this->GetStartingContext(); - - cmCommandContext commandContext; - commandContext.Line = execContext.Line; - commandContext.Name = execContext.Name; - - cmConditionEvaluator conditionEvaluator(mf, this->GetStartingContext(), - mf.GetBacktrace(commandContext)); - - bool isTrue = - conditionEvaluator.IsTrue(expandedArguments, errorString, messageType); - - while (isTrue) { - if (!errorString.empty()) { - std::string err = "had incorrect arguments: "; - for (cmListFileArgument const& arg : this->Args) { - err += (arg.Delim ? "\"" : ""); - err += arg.Value; - err += (arg.Delim ? "\"" : ""); - err += " "; - } - err += "("; - err += errorString; - err += ")."; - mf.IssueMessage(messageType, err); - if (messageType == MessageType::FATAL_ERROR) { - cmSystemTools::SetFatalErrorOccured(); - return true; - } - } - - // Invoke all the functions that were collected in the block. - for (cmListFileFunction const& fn : this->Functions) { - cmExecutionStatus status; - mf.ExecuteCommand(fn, status); - if (status.GetReturnInvoked()) { - inStatus.SetReturnInvoked(); - return true; - } - if (status.GetBreakInvoked()) { - return true; - } - if (status.GetContinueInvoked()) { - break; - } - if (cmSystemTools::GetFatalErrorOccured()) { - return true; - } - } - expandedArguments.clear(); - mf.ExpandArguments(this->Args, expandedArguments); - isTrue = conditionEvaluator.IsTrue(expandedArguments, errorString, - messageType); - } - return true; - } - // decrement for each nested while that ends - this->Depth--; - } +bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& inStatus) +{ + cmMakefile& mf = inStatus.GetMakefile(); + std::string errorString; - // record the command - this->Functions.push_back(lff); + std::vector<cmExpandedCommandArgument> expandedArguments; + mf.ExpandArguments(this->Args, expandedArguments); + MessageType messageType; - // always return true - return true; -} + cmListFileContext execContext = this->GetStartingContext(); -bool cmWhileFunctionBlocker::ShouldRemove(const cmListFileFunction& lff, - cmMakefile&) -{ - if (lff.Name.Lower == "endwhile") { - // if the endwhile has arguments, then make sure - // they match the arguments of the matching while - if (lff.Arguments.empty() || lff.Arguments == this->Args) { - return true; + cmCommandContext commandContext; + commandContext.Line = execContext.Line; + commandContext.Name = execContext.Name; + + cmConditionEvaluator conditionEvaluator(mf, this->GetStartingContext(), + mf.GetBacktrace(commandContext)); + + bool isTrue = + conditionEvaluator.IsTrue(expandedArguments, errorString, messageType); + + while (isTrue) { + if (!errorString.empty()) { + std::string err = "had incorrect arguments: "; + for (cmListFileArgument const& arg : this->Args) { + err += (arg.Delim ? "\"" : ""); + err += arg.Value; + err += (arg.Delim ? "\"" : ""); + err += " "; + } + err += "("; + err += errorString; + err += ")."; + mf.IssueMessage(messageType, err); + if (messageType == MessageType::FATAL_ERROR) { + cmSystemTools::SetFatalErrorOccured(); + return true; + } } + + // Invoke all the functions that were collected in the block. + for (cmListFileFunction const& fn : functions) { + cmExecutionStatus status(mf); + mf.ExecuteCommand(fn, status); + if (status.GetReturnInvoked()) { + inStatus.SetReturnInvoked(); + return true; + } + if (status.GetBreakInvoked()) { + return true; + } + if (status.GetContinueInvoked()) { + break; + } + if (cmSystemTools::GetFatalErrorOccured()) { + return true; + } + } + expandedArguments.clear(); + mf.ExpandArguments(this->Args, expandedArguments); + isTrue = + conditionEvaluator.IsTrue(expandedArguments, errorString, messageType); } - return false; + return true; } -bool cmWhileCommand::InvokeInitialPass( - const std::vector<cmListFileArgument>& args, cmExecutionStatus&) +bool cmWhileCommand(std::vector<cmListFileArgument> const& args, + cmExecutionStatus& status) { if (args.empty()) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } // create a function blocker - cmWhileFunctionBlocker* f = new cmWhileFunctionBlocker(this->Makefile); - f->Args = args; - this->Makefile->AddFunctionBlocker(f); - + { + cmMakefile& makefile = status.GetMakefile(); + auto fb = cm::make_unique<cmWhileFunctionBlocker>(&makefile); + fb->Args = args; + makefile.AddFunctionBlocker(std::move(fb)); + } return true; } diff --git a/Source/cmWhileCommand.h b/Source/cmWhileCommand.h index 6f6d405..beca652 100644 --- a/Source/cmWhileCommand.h +++ b/Source/cmWhileCommand.h @@ -5,58 +5,13 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include <string> #include <vector> -#include "cmCommand.h" -#include "cmFunctionBlocker.h" -#include "cmListFileCache.h" - class cmExecutionStatus; -class cmMakefile; - -class cmWhileFunctionBlocker : public cmFunctionBlocker -{ -public: - cmWhileFunctionBlocker(cmMakefile* mf); - ~cmWhileFunctionBlocker() override; - bool IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile& mf, - cmExecutionStatus&) override; - bool ShouldRemove(const cmListFileFunction& lff, cmMakefile& mf) override; - - std::vector<cmListFileArgument> Args; - std::vector<cmListFileFunction> Functions; - -private: - cmMakefile* Makefile; - int Depth; -}; +struct cmListFileArgument; /// \brief Starts a while loop -class cmWhileCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmWhileCommand; } - - /** - * This overrides the default InvokeInitialPass implementation. - * It records the arguments before expansion. - */ - bool InvokeInitialPass(const std::vector<cmListFileArgument>& args, - cmExecutionStatus&) override; - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const&, - cmExecutionStatus&) override - { - return false; - } -}; +bool cmWhileCommand(std::vector<cmListFileArgument> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmWorkerPool.cxx b/Source/cmWorkerPool.cxx index cbf070e..baf326a 100644 --- a/Source/cmWorkerPool.cxx +++ b/Source/cmWorkerPool.cxx @@ -3,6 +3,7 @@ #include "cmWorkerPool.h" #include "cmRange.h" +#include "cmStringAlgorithms.h" #include "cmUVHandlePtr.h" #include "cmUVSignalHackRAII.h" // IWYU pragma: keep #include "cm_uv.h" @@ -16,6 +17,8 @@ #include <stddef.h> #include <thread> +#include "cm_memory.hxx" + /** * @brief libuv pipe buffer class */ @@ -304,13 +307,11 @@ void cmUVReadOnlyProcess::UVExit(uv_process_t* handle, int64_t exitStatus, proc.Result()->TermSignal = termSignal; if (!proc.Result()->error()) { if (termSignal != 0) { - proc.Result()->ErrorMessage = "Process was terminated by signal "; - proc.Result()->ErrorMessage += - std::to_string(proc.Result()->TermSignal); + proc.Result()->ErrorMessage = cmStrCat( + "Process was terminated by signal ", proc.Result()->TermSignal); } else if (exitStatus != 0) { - proc.Result()->ErrorMessage = "Process failed with return value "; - proc.Result()->ErrorMessage += - std::to_string(proc.Result()->ExitStatus); + proc.Result()->ErrorMessage = cmStrCat( + "Process failed with return value ", proc.Result()->ExitStatus); } } @@ -330,9 +331,8 @@ void cmUVReadOnlyProcess::UVPipeOutEnd(ssize_t error) { // Process pipe error if ((error != 0) && !Result()->error()) { - Result()->ErrorMessage = - "Reading from stdout pipe failed with libuv error code "; - Result()->ErrorMessage += std::to_string(error); + Result()->ErrorMessage = cmStrCat( + "Reading from stdout pipe failed with libuv error code ", error); } // Try finish UVTryFinish(); @@ -349,9 +349,8 @@ void cmUVReadOnlyProcess::UVPipeErrEnd(ssize_t error) { // Process pipe error if ((error != 0) && !Result()->error()) { - Result()->ErrorMessage = - "Reading from stderr pipe failed with libuv error code "; - Result()->ErrorMessage += std::to_string(error); + Result()->ErrorMessage = cmStrCat( + "Reading from stderr pipe failed with libuv error code ", error); } // Try finish UVTryFinish(); diff --git a/Source/cmWorkerPool.h b/Source/cmWorkerPool.h index f08bb4f..d708118 100644 --- a/Source/cmWorkerPool.h +++ b/Source/cmWorkerPool.h @@ -5,14 +5,13 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include "cmAlgorithms.h" // IWYU pragma: keep - -#include <memory> // IWYU pragma: keep #include <stdint.h> #include <string> #include <utility> #include <vector> +#include "cm_memory.hxx" + // -- Types class cmWorkerPoolInternal; diff --git a/Source/cmWriteFileCommand.cxx b/Source/cmWriteFileCommand.cxx index 49dbf1a..5009b16 100644 --- a/Source/cmWriteFileCommand.cxx +++ b/Source/cmWriteFileCommand.cxx @@ -4,18 +4,18 @@ #include "cmsys/FStream.hxx" +#include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cm_sys_stat.h" -class cmExecutionStatus; - // cmLibraryCommand -bool cmWriteFileCommand::InitialPass(std::vector<std::string> const& args, - cmExecutionStatus&) +bool cmWriteFileCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { if (args.size() < 2) { - this->SetError("called with incorrect number of arguments"); + status.SetError("called with incorrect number of arguments"); return false; } std::string message; @@ -33,10 +33,10 @@ bool cmWriteFileCommand::InitialPass(std::vector<std::string> const& args, } } - if (!this->Makefile->CanIWriteThisFile(fileName)) { + if (!status.GetMakefile().CanIWriteThisFile(fileName)) { std::string e = "attempted to write a file: " + fileName + " into a source directory."; - this->SetError(e); + status.SetError(e); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -65,10 +65,10 @@ bool cmWriteFileCommand::InitialPass(std::vector<std::string> const& args, cmsys::ofstream file(fileName.c_str(), overwrite ? std::ios::out : std::ios::app); if (!file) { - std::string error = "Internal CMake error when trying to open file: "; - error += fileName; - error += " for writing."; - this->SetError(error); + std::string error = + cmStrCat("Internal CMake error when trying to open file: ", fileName, + " for writing."); + status.SetError(error); return false; } file << message << std::endl; diff --git a/Source/cmWriteFileCommand.h b/Source/cmWriteFileCommand.h index 9028f84..3e0e043 100644 --- a/Source/cmWriteFileCommand.h +++ b/Source/cmWriteFileCommand.h @@ -8,28 +8,13 @@ #include <string> #include <vector> -#include "cmCommand.h" - class cmExecutionStatus; -/** \class cmWriteFileCommand +/** * \brief Writes a message to a file * */ -class cmWriteFileCommand : public cmCommand -{ -public: - /** - * This is a virtual constructor for the command. - */ - cmCommand* Clone() override { return new cmWriteFileCommand; } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmWriteFileCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmXCodeObject.h b/Source/cmXCodeObject.h index 51e5d36..0552676 100644 --- a/Source/cmXCodeObject.h +++ b/Source/cmXCodeObject.h @@ -12,6 +12,8 @@ #include <utility> #include <vector> +#include "cmAlgorithms.h" + class cmGeneratorTarget; class cmXCodeObject @@ -80,15 +82,10 @@ public: void SetObject(cmXCodeObject* value) { this->Object = value; } cmXCodeObject* GetObject() { return this->Object; } void AddObject(cmXCodeObject* value) { this->List.push_back(value); } - bool HasObject(cmXCodeObject* o) const - { - return !(std::find(this->List.begin(), this->List.end(), o) == - this->List.end()); - } + bool HasObject(cmXCodeObject* o) const { return cmContains(this->List, o); } void AddUniqueObject(cmXCodeObject* value) { - if (std::find(this->List.begin(), this->List.end(), value) == - this->List.end()) { + if (!cmContains(this->List, value)) { this->List.push_back(value); } } diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx index c33bb7e..a1c64ed 100644 --- a/Source/cmXCodeScheme.cxx +++ b/Source/cmXCodeScheme.cxx @@ -27,14 +27,11 @@ void cmXCodeScheme::WriteXCodeSharedScheme(const std::string& xcProjDir, { // Create shared scheme sub-directory tree // - std::string xcodeSchemeDir = xcProjDir; - xcodeSchemeDir += "/xcshareddata/xcschemes"; + std::string xcodeSchemeDir = cmStrCat(xcProjDir, "/xcshareddata/xcschemes"); cmSystemTools::MakeDirectory(xcodeSchemeDir.c_str()); - std::string xcodeSchemeFile = xcodeSchemeDir; - xcodeSchemeFile += "/"; - xcodeSchemeFile += this->TargetName; - xcodeSchemeFile += ".xcscheme"; + std::string xcodeSchemeFile = + cmStrCat(xcodeSchemeDir, '/', this->TargetName, ".xcscheme"); cmGeneratedFileStream fout(xcodeSchemeFile); fout.SetCopyIfDifferent(true); @@ -217,8 +214,7 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, if (const char* argList = this->Target->GetTarget()->GetProperty("XCODE_SCHEME_ARGUMENTS")) { - std::vector<std::string> arguments; - cmSystemTools::ExpandListArgument(argList, arguments); + std::vector<std::string> arguments = cmExpandedList(argList); if (!arguments.empty()) { xout.StartElement("CommandLineArguments"); @@ -238,8 +234,7 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, if (const char* envList = this->Target->GetTarget()->GetProperty("XCODE_SCHEME_ENVIRONMENT")) { - std::vector<std::string> envs; - cmSystemTools::ExpandListArgument(envList, envs); + std::vector<std::string> envs = cmExpandedList(envList); if (!envs.empty()) { xout.StartElement("EnvironmentVariables"); @@ -393,9 +388,7 @@ std::string cmXCodeScheme::FindConfiguration(const std::string& name) // Try to find the desired configuration by name, // and if it's not found return first from the list // - if (std::find(this->ConfigList.begin(), this->ConfigList.end(), name) == - this->ConfigList.end() && - !this->ConfigList.empty()) { + if (!cmContains(this->ConfigList, name) && !this->ConfigList.empty()) { return this->ConfigList[0]; } diff --git a/Source/cm_codecvt.hxx b/Source/cm_codecvt.hxx index 2df3961..2060584 100644 --- a/Source/cm_codecvt.hxx +++ b/Source/cm_codecvt.hxx @@ -18,7 +18,7 @@ public: ANSI }; -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP codecvt(Encoding e); diff --git a/Source/cm_memory.hxx b/Source/cm_memory.hxx new file mode 100644 index 0000000..9f5e678 --- /dev/null +++ b/Source/cm_memory.hxx @@ -0,0 +1,31 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_memory_hxx +#define cm_memory_hxx + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <memory> // IWYU pragma: export +#if !defined(CMake_HAVE_CXX_MAKE_UNIQUE) +# include <utility> +#endif + +namespace cm { + +#if defined(CMake_HAVE_CXX_MAKE_UNIQUE) + +using std::make_unique; + +#else + +template <typename T, typename... Args> +std::unique_ptr<T> make_unique(Args&&... args) +{ + return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); +} + +#endif + +} // namespace cm + +#endif diff --git a/Source/cm_optional.hxx b/Source/cm_optional.hxx new file mode 100644 index 0000000..295571d --- /dev/null +++ b/Source/cm_optional.hxx @@ -0,0 +1,343 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_optional_hxx +#define cm_optional_hxx + +#include "cmConfigure.h" // IWYU pragma: keep + +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +# define CMake_HAVE_CXX_OPTIONAL +#endif + +#if defined(CMake_HAVE_CXX_OPTIONAL) +# include <optional> +#else +# include "cm_utility.hxx" +# include <memory> +# include <utility> +#endif + +namespace cm { + +#if defined(CMake_HAVE_CXX_OPTIONAL) + +using std::nullopt_t; +using std::nullopt; +using std::optional; +using std::bad_optional_access; +using std::make_optional; + +#else + +class bad_optional_access : public std::exception +{ + using std::exception::exception; +}; + +struct nullopt_t +{ + explicit constexpr nullopt_t(int) {} +}; + +constexpr nullopt_t nullopt{ 0 }; + +template <typename T> +class optional +{ +public: + using value_type = T; + + optional() noexcept = default; + optional(nullopt_t) noexcept; + optional(const optional& other); + optional(optional&& other) noexcept; + + template <typename... Args> + explicit optional(cm::in_place_t, Args&&... args); + + template < + typename U = T, + typename = typename std::enable_if< + std::is_constructible<T, U&&>::value && + !std::is_same<typename std::decay<U>::type, cm::in_place_t>::value && + !std::is_same<typename std::decay<U>::type, + cm::optional<T>>::value>::type> + optional(U&& v); + + ~optional(); + + optional& operator=(nullopt_t) noexcept; + optional& operator=(const optional& other); + optional& operator=(optional&& other) noexcept; + + template < + typename U = T, + typename = typename std::enable_if< + !std::is_same<typename std::decay<U>::type, cm::optional<T>>::value && + std::is_constructible<T, U>::value && std::is_assignable<T&, U>::value && + (!std::is_scalar<T>::value || + !std::is_same<typename std::decay<U>::type, T>::value)>::type> + optional& operator=(U&& v); + + const T* operator->() const; + T* operator->(); + const T& operator*() const&; + T& operator*() &; + const T&& operator*() const&&; + T&& operator*() &&; + + explicit operator bool() const noexcept; + bool has_value() const noexcept; + + T& value() &; + const T& value() const&; + + T&& value() &&; + const T&& value() const&&; + + template <typename U> + T value_or(U&& default_value) const&; + + template <typename U> + T value_or(U&& default_value) &&; + + void swap(optional& other) noexcept; + void reset() noexcept; + + template <typename... Args> + T& emplace(Args&&... args); + +private: + bool _has_value = false; + std::allocator<T> _allocator; + union _mem_union + { + T value; + + // Explicit constructor and destructor is required to make this work + _mem_union() noexcept {} + ~_mem_union() noexcept {} + } _mem; +}; + +template <typename T> +optional<typename std::decay<T>::type> make_optional(T&& value) +{ + return optional<typename std::decay<T>::type>(std::forward<T>(value)); +} + +template <typename T, class... Args> +optional<T> make_optional(Args&&... args) +{ + return optional<T>(in_place, std::forward<Args>(args)...); +} + +template <typename T> +optional<T>::optional(nullopt_t) noexcept +{ +} + +template <typename T> +optional<T>::optional(const optional& other) +{ + *this = other; +} + +template <typename T> +optional<T>::optional(optional&& other) noexcept +{ + *this = std::move(other); +} + +template <typename T> +template <typename... Args> +optional<T>::optional(cm::in_place_t, Args&&... args) +{ + this->emplace(std::forward<Args>(args)...); +} + +template <typename T> +template <typename U, typename> +optional<T>::optional(U&& v) +{ + this->emplace(std::forward<U>(v)); +} + +template <typename T> +optional<T>::~optional() +{ + this->reset(); +} + +template <typename T> +optional<T>& optional<T>::operator=(nullopt_t) noexcept +{ + this->reset(); + return *this; +} + +template <typename T> +optional<T>& optional<T>::operator=(const optional& other) +{ + if (other.has_value()) { + if (this->has_value()) { + this->value() = *other; + } else { + this->emplace(*other); + } + } else { + this->reset(); + } + return *this; +} + +template <typename T> +optional<T>& optional<T>::operator=(optional&& other) noexcept +{ + if (other.has_value()) { + if (this->has_value()) { + this->value() = std::move(*other); + } else { + this->emplace(std::move(*other)); + } + } else { + this->reset(); + } + return *this; +} + +template <typename T> +template <typename U, typename> +optional<T>& optional<T>::operator=(U&& v) +{ + if (this->has_value()) { + this->value() = v; + } else { + this->emplace(std::forward<U>(v)); + } + return *this; +} + +template <typename T> +const T* optional<T>::operator->() const +{ + return &**this; +} + +template <typename T> +T* optional<T>::operator->() +{ + return &**this; +} + +template <typename T> +const T& optional<T>::operator*() const& +{ + return this->_mem.value; +} + +template <typename T> +T& optional<T>::operator*() & +{ + return this->_mem.value; +} + +template <typename T> +const T&& optional<T>::operator*() const&& +{ + return std::move(**this); +} + +template <typename T> +T&& optional<T>::operator*() && +{ + return std::move(**this); +} + +template <typename T> +bool optional<T>::has_value() const noexcept +{ + return this->_has_value; +} + +template <typename T> +optional<T>::operator bool() const noexcept +{ + return this->has_value(); +} + +template <typename T> +T& optional<T>::value() & +{ + if (!this->has_value()) { + throw cm::bad_optional_access{}; + } + return **this; +} + +template <typename T> +const T& optional<T>::value() const& +{ + if (!this->has_value()) { + throw cm::bad_optional_access{}; + } + return **this; +} + +template <typename T> +template <typename U> +T optional<T>::value_or(U&& default_value) const& +{ + return bool(*this) ? **this : static_cast<T>(std::forward<U>(default_value)); +} + +template <typename T> +template <typename U> +T optional<T>::value_or(U&& default_value) && +{ + return bool(*this) ? std::move(**this) + : static_cast<T>(std::forward<U>(default_value)); +} + +template <typename T> +void optional<T>::swap(optional& other) noexcept +{ + if (this->has_value()) { + if (other.has_value()) { + using std::swap; + swap(**this, *other); + } else { + other.emplace(std::move(**this)); + this->reset(); + } + } else if (other.has_value()) { + this->emplace(std::move(*other)); + other.reset(); + } +} + +template <typename T> +void optional<T>::reset() noexcept +{ + if (this->has_value()) { + this->_has_value = false; + std::allocator_traits<std::allocator<T>>::destroy(this->_allocator, + &**this); + } +} + +template <typename T> +template <typename... Args> +T& optional<T>::emplace(Args&&... args) +{ + this->reset(); + std::allocator_traits<std::allocator<T>>::construct( + this->_allocator, &**this, std::forward<Args>(args)...); + this->_has_value = true; + return this->value(); +} + +#endif +} + +#endif diff --git a/Source/cm_utility.hxx b/Source/cm_utility.hxx new file mode 100644 index 0000000..99d7f8b --- /dev/null +++ b/Source/cm_utility.hxx @@ -0,0 +1,35 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_utility_hxx +#define cm_utility_hxx + +#include "cmConfigure.h" // IWYU pragma: keep + +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +# define CMake_HAVE_CXX_IN_PLACE +#endif + +#if defined(CMake_HAVE_CXX_IN_PLACE) +# include <utility> +#endif + +namespace cm { + +#if defined(CMake_HAVE_CXX_IN_PLACE) + +using std::in_place_t; +using std::in_place; + +#else + +struct in_place_t +{ + explicit in_place_t() = default; +}; + +constexpr in_place_t in_place{}; + +#endif +} + +#endif diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 3772f09..4fa98b3 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmake.h" +#include "cm_memory.hxx" + #include "cmAlgorithms.h" #include "cmCommands.h" #include "cmDocumentation.h" @@ -19,15 +21,17 @@ #include "cmMessenger.h" #include "cmState.h" #include "cmStateDirectory.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetLinkLibraryType.h" #include "cmUtils.hxx" #include "cmVersionConfig.h" #include "cmWorkingDirectory.h" +#include "cm_string_view.hxx" #include "cm_sys_stat.h" -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) # include "cm_jsoncpp_writer.h" # include "cmFileAPI.h" @@ -36,11 +40,11 @@ # include <unordered_map> #endif -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) # define CMAKE_USE_ECLIPSE #endif -#if defined(__MINGW32__) && !defined(CMAKE_BUILD_WITH_CMAKE) +#if defined(__MINGW32__) && defined(CMAKE_BOOTSTRAP) # define CMAKE_BOOT_MINGW #endif @@ -68,7 +72,7 @@ # include "cmGlobalWatcomWMakeGenerator.h" #endif #include "cmGlobalUnixMakefileGenerator3.h" -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) # include "cmGlobalNinjaGenerator.h" #endif #include "cmExtraCodeLiteGenerator.h" @@ -88,7 +92,7 @@ #endif #if defined(__APPLE__) -# if defined(CMAKE_BUILD_WITH_CMAKE) +# if !defined(CMAKE_BOOTSTRAP) # include "cmGlobalXCodeGenerator.h" # define CMAKE_USE_XCODE 1 @@ -104,8 +108,6 @@ #include <cstring> #include <initializer_list> #include <iostream> -#include <iterator> -#include <memory> // IWYU pragma: keep #include <sstream> #include <stdio.h> #include <stdlib.h> @@ -113,7 +115,7 @@ namespace { -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) typedef std::unordered_map<std::string, Json::Value> JsonValueMapType; #endif @@ -122,31 +124,25 @@ typedef std::unordered_map<std::string, Json::Value> JsonValueMapType; static bool cmakeCheckStampFile(const std::string& stampName); static bool cmakeCheckStampList(const std::string& stampList); -void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/, - void* ctx, const char* /*unused*/, - const cmMakefile* /*unused*/) +static void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/, + void* ctx, const char* /*unused*/, + const cmMakefile* /*unused*/) { cmake* cm = reinterpret_cast<cmake*>(ctx); cm->MarkCliAsUsed(variable); } cmake::cmake(Role role, cmState::Mode mode) + : FileTimeCache(cm::make_unique<cmFileTimeCache>()) +#ifndef CMAKE_BOOTSTRAP + , VariableWatch(cm::make_unique<cmVariableWatch>()) +#endif + , State(cm::make_unique<cmState>()) + , Messenger(cm::make_unique<cmMessenger>()) { - this->Trace = false; - this->TraceExpand = false; - this->WarnUninitialized = false; - this->WarnUnused = false; - this->WarnUnusedCli = true; - this->CheckSystemVars = false; - this->DebugOutput = false; - this->DebugTryCompile = false; - this->ClearBuildSystem = false; - this->FileTimeCache = new cmFileTimeCache; - - this->State = new cmState; + this->TraceFile.close(); this->State->SetMode(mode); this->CurrentSnapshot = this->State->CreateBaseSnapshot(); - this->Messenger = new cmMessenger; #ifdef __APPLE__ struct rlimit rlp; @@ -158,16 +154,6 @@ cmake::cmake(Role role, cmState::Mode mode) } #endif - this->GlobalGenerator = nullptr; - this->GeneratorInstanceSet = false; - this->GeneratorPlatformSet = false; - this->GeneratorToolsetSet = false; - this->CurrentWorkingMode = NORMAL_MODE; - -#ifdef CMAKE_BUILD_WITH_CMAKE - this->VariableWatch = new cmVariableWatch; -#endif - this->AddDefaultGenerators(); this->AddDefaultExtraGenerators(); if (role == RoleScript || role == RoleProject) { @@ -184,58 +170,41 @@ cmake::cmake(Role role, cmState::Mode mode) // Make sure we can capture the build tool output. cmSystemTools::EnableVSConsoleOutput(); - // Set up a list of source and header extensions - // these are used to find files when the extension - // is not given - // The "c" extension MUST precede the "C" extension. - this->SourceFileExtensions.emplace_back("c"); - this->SourceFileExtensions.emplace_back("C"); - - this->SourceFileExtensions.emplace_back("c++"); - this->SourceFileExtensions.emplace_back("cc"); - this->SourceFileExtensions.emplace_back("cpp"); - this->SourceFileExtensions.emplace_back("cxx"); - this->SourceFileExtensions.emplace_back("cu"); - this->SourceFileExtensions.emplace_back("m"); - this->SourceFileExtensions.emplace_back("M"); - this->SourceFileExtensions.emplace_back("mm"); - - std::copy(this->SourceFileExtensions.begin(), - this->SourceFileExtensions.end(), - std::inserter(this->SourceFileExtensionsSet, - this->SourceFileExtensionsSet.end())); - - this->HeaderFileExtensions.emplace_back("h"); - this->HeaderFileExtensions.emplace_back("hh"); - this->HeaderFileExtensions.emplace_back("h++"); - this->HeaderFileExtensions.emplace_back("hm"); - this->HeaderFileExtensions.emplace_back("hpp"); - this->HeaderFileExtensions.emplace_back("hxx"); - this->HeaderFileExtensions.emplace_back("in"); - this->HeaderFileExtensions.emplace_back("txx"); - - std::copy(this->HeaderFileExtensions.begin(), - this->HeaderFileExtensions.end(), - std::inserter(this->HeaderFileExtensionsSet, - this->HeaderFileExtensionsSet.end())); + // Set up a list of source and header extensions. + // These are used to find files when the extension is not given. + { + auto setupExts = [](FileExtensions& exts, + std::initializer_list<cm::string_view> extList) { + // Fill ordered vector + exts.ordered.reserve(extList.size()); + for (cm::string_view ext : extList) { + exts.ordered.emplace_back(ext); + }; + // Fill unordered set + exts.unordered.insert(exts.ordered.begin(), exts.ordered.end()); + }; + + // The "c" extension MUST precede the "C" extension. + setupExts(this->SourceFileExtensions, + { "c", "C", "c++", "cc", "cpp", "cxx", "cu", "m", "M", "mm" }); + setupExts(this->HeaderFileExtensions, + { "h", "hh", "h++", "hm", "hpp", "hxx", "in", "txx" }); + setupExts(this->CudaFileExtensions, { "cu" }); + setupExts(this->FortranFileExtensions, + { "f", "F", "for", "f77", "f90", "f95", "f03" }); + } } cmake::~cmake() { - delete this->State; - delete this->Messenger; if (this->GlobalGenerator) { delete this->GlobalGenerator; this->GlobalGenerator = nullptr; } cmDeleteAll(this->Generators); -#ifdef CMAKE_BUILD_WITH_CMAKE - delete this->VariableWatch; -#endif - delete this->FileTimeCache; } -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) Json::Value cmake::ReportVersionJson() const { Json::Value version = Json::objectValue; @@ -294,7 +263,7 @@ Json::Value cmake::ReportCapabilitiesJson() const std::string cmake::ReportCapabilities() const { std::string result; -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) Json::FastWriter writer; result = writer.write(this->ReportCapabilitiesJson()); #else @@ -327,7 +296,8 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) return false; } } - std::string var, value; + std::string var; + std::string value; cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED; if (cmState::ParseCacheEntry(entry, var, value, type)) { // The value is transformed if it is a filepath for example, so @@ -460,7 +430,7 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) return false; } // Register fake project commands that hint misuse in script mode. - GetProjectCommandsInScriptMode(this->State); + GetProjectCommandsInScriptMode(this->GetState()); this->ReadListFile(args, path); } else if (arg.find("--find-package", 0) == 0) { findPackageMode = true; @@ -561,8 +531,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args) } } else if (mode == "COMPILE") { std::string includes = mf->GetSafeDefinition("PACKAGE_INCLUDE_DIRS"); - std::vector<std::string> includeDirs; - cmSystemTools::ExpandListArgument(includes, includeDirs); + std::vector<std::string> includeDirs = cmExpandedList(includes); gg->CreateGenerationObjects(); cmLocalGenerator* lg = gg->LocalGenerators[0]; @@ -578,8 +547,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args) tgt->SetProperty("LINKER_LANGUAGE", language.c_str()); std::string libs = mf->GetSafeDefinition("PACKAGE_LIBRARIES"); - std::vector<std::string> libList; - cmSystemTools::ExpandListArgument(libs, libList); + std::vector<std::string> libList = cmExpandedList(libs); for (std::string const& lib : libList) { tgt->AddLinkLibrary(*mf, lib, GENERAL_LibraryType); } @@ -629,16 +597,15 @@ void cmake::LoadEnvironmentPresets() this->EnvironmentGenerator = envGenVar; } - auto readGeneratorVar = [&](std::string name, std::string& key) { + auto readGeneratorVar = [&](std::string const& name, std::string& key) { std::string varValue; if (cmSystemTools::GetEnv(name, varValue)) { if (hasEnvironmentGenerator) { key = varValue; } else if (!this->GetIsInTryCompile()) { - std::string message = "Warning: Environment variable "; - message += name; - message += " will be ignored, because CMAKE_GENERATOR "; - message += "is not set."; + std::string message = + cmStrCat("Warning: Environment variable ", name, + " will be ignored, because CMAKE_GENERATOR is not set."); cmSystemTools::Message(message, "Warning"); } } @@ -772,6 +739,11 @@ void cmake::SetArgs(const std::vector<std::string>& args) cmSystemTools::ConvertToUnixSlashes(file); this->AddTraceSource(file); this->SetTrace(true); + } else if (arg.find("--trace-redirect=", 0) == 0) { + std::string file = arg.substr(strlen("--trace-redirect=")); + cmSystemTools::ConvertToUnixSlashes(file); + this->SetTraceFile(file); + this->SetTrace(true); } else if (arg.find("--trace", 0) == 0) { std::cout << "Running with trace output on.\n"; this->SetTrace(true); @@ -840,8 +812,8 @@ void cmake::SetArgs(const std::vector<std::string>& args) kdevError = "\nThe KDevelop3 generator is not supported anymore."; } - cmSystemTools::Error("Could not create named generator " + value + - kdevError); + cmSystemTools::Error( + cmStrCat("Could not create named generator ", value, kdevError)); this->PrintGeneratorList(); return; } @@ -902,6 +874,20 @@ cmake::LogLevel cmake::StringToLogLevel(const std::string& levelStr) return (it != levels.cend()) ? it->second : LogLevel::LOG_UNDEFINED; } +void cmake::SetTraceFile(const std::string& file) +{ + this->TraceFile.close(); + this->TraceFile.open(file.c_str()); + if (!this->TraceFile) { + std::stringstream ss; + ss << "Error opening trace file " << file << ": " + << cmSystemTools::GetLastSystemError(); + cmSystemTools::Error(ss.str()); + return; + } + std::cout << "Trace will be written to " << file << "\n"; +} + void cmake::SetDirectoriesFromFile(const std::string& arg) { // Check if the argument refers to a CMakeCache.txt or @@ -912,10 +898,8 @@ void cmake::SetDirectoriesFromFile(const std::string& arg) if (cmSystemTools::FileIsDirectory(arg)) { std::string path = cmSystemTools::CollapseFullPath(arg); cmSystemTools::ConvertToUnixSlashes(path); - std::string cacheFile = path; - cacheFile += "/CMakeCache.txt"; - std::string listFile = path; - listFile += "/CMakeLists.txt"; + std::string cacheFile = cmStrCat(path, "/CMakeCache.txt"); + std::string listFile = cmStrCat(path, "/CMakeLists.txt"); if (cmSystemTools::FileExists(cacheFile)) { cachePath = path; } @@ -1000,7 +984,7 @@ int cmake::AddCMakePaths() this->AddCacheEntry("CMAKE_COMMAND", cmSystemTools::GetCMakeCommand().c_str(), "Path to CMake executable.", cmStateEnums::INTERNAL); -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP this->AddCacheEntry( "CMAKE_CTEST_COMMAND", cmSystemTools::GetCTestCommand().c_str(), "Path to ctest program executable.", cmStateEnums::INTERNAL); @@ -1026,7 +1010,7 @@ int cmake::AddCMakePaths() void cmake::AddDefaultExtraGenerators() { -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) this->ExtraGenerators.push_back(cmExtraCodeBlocksGenerator::GetFactory()); this->ExtraGenerators.push_back(cmExtraCodeLiteGenerator::GetFactory()); this->ExtraGenerators.push_back(cmExtraSublimeTextGenerator::GetFactory()); @@ -1170,12 +1154,10 @@ std::string cmake::FindCacheFile(const std::string& binaryDir) { std::string cachePath = binaryDir; cmSystemTools::ConvertToUnixSlashes(cachePath); - std::string cacheFile = cachePath; - cacheFile += "/CMakeCache.txt"; + std::string cacheFile = cmStrCat(cachePath, "/CMakeCache.txt"); if (!cmSystemTools::FileExists(cacheFile)) { // search in parent directories for cache - std::string cmakeFiles = cachePath; - cmakeFiles += "/CMakeFiles"; + std::string cmakeFiles = cmStrCat(cachePath, "/CMakeFiles"); if (cmSystemTools::FileExists(cmakeFiles)) { std::string cachePathFound = cmSystemTools::FileExistsInParentDirectories("CMakeCache.txt", @@ -1230,8 +1212,7 @@ void cmake::SetGlobalGenerator(cmGlobalGenerator* gg) int cmake::DoPreConfigureChecks() { // Make sure the Source directory contains a CMakeLists.txt file. - std::string srcList = this->GetHomeDirectory(); - srcList += "/CMakeLists.txt"; + std::string srcList = cmStrCat(this->GetHomeDirectory(), "/CMakeLists.txt"); if (!cmSystemTools::FileExists(srcList)) { std::ostringstream err; if (cmSystemTools::FileIsDirectory(this->GetHomeDirectory())) { @@ -1253,17 +1234,16 @@ int cmake::DoPreConfigureChecks() // do a sanity check on some values if (this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY")) { std::string cacheStart = - *this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY"); - cacheStart += "/CMakeLists.txt"; - std::string currentStart = this->GetHomeDirectory(); - currentStart += "/CMakeLists.txt"; + cmStrCat(*this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY"), + "/CMakeLists.txt"); + std::string currentStart = + cmStrCat(this->GetHomeDirectory(), "/CMakeLists.txt"); if (!cmSystemTools::SameFile(cacheStart, currentStart)) { - std::string message = "The source \""; - message += currentStart; - message += "\" does not match the source \""; - message += cacheStart; - message += "\" used to generate cache. "; - message += "Re-run cmake with a different source directory."; + std::string message = + cmStrCat("The source \"", currentStart, + "\" does not match the source \"", cacheStart, + "\" used to generate cache. Re-run cmake with a different " + "source directory."); cmSystemTools::Error(message); return -2; } @@ -1282,8 +1262,7 @@ struct SaveCacheEntry int cmake::HandleDeleteCacheVariables(const std::string& var) { - std::vector<std::string> argsSplit; - cmSystemTools::ExpandListArgument(std::string(var), argsSplit, true); + std::vector<std::string> argsSplit = cmExpandedList(std::string(var), true); // erase the property to avoid infinite recursion this->State->SetGlobalProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", ""); if (this->State->GetIsInTryCompile()) { @@ -1397,18 +1376,16 @@ int cmake::Configure() // so we cannot rely on command line options alone. Always ensure our // messenger is in sync with the cache. const char* value = this->State->GetCacheEntryValue("CMAKE_WARN_DEPRECATED"); - this->Messenger->SetSuppressDeprecatedWarnings(value && - cmSystemTools::IsOff(value)); + this->Messenger->SetSuppressDeprecatedWarnings(value && cmIsOff(value)); value = this->State->GetCacheEntryValue("CMAKE_ERROR_DEPRECATED"); - this->Messenger->SetDeprecatedWarningsAsErrors(cmSystemTools::IsOn(value)); + this->Messenger->SetDeprecatedWarningsAsErrors(cmIsOn(value)); value = this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_WARNINGS"); - this->Messenger->SetSuppressDevWarnings(cmSystemTools::IsOn(value)); + this->Messenger->SetSuppressDevWarnings(cmIsOn(value)); value = this->State->GetCacheEntryValue("CMAKE_SUPPRESS_DEVELOPER_ERRORS"); - this->Messenger->SetDevWarningsAsErrors(value && - cmSystemTools::IsOff(value)); + this->Messenger->SetDevWarningsAsErrors(value && cmIsOff(value)); int ret = this->ActualConfigure(); const char* delCacheVars = @@ -1468,12 +1445,11 @@ int cmake::ActualConfigure() this->State->GetInitializedCacheValue("CMAKE_GENERATOR"); if (genName) { if (!this->GlobalGenerator->MatchesGeneratorName(*genName)) { - std::string message = "Error: generator : "; - message += this->GlobalGenerator->GetName(); - message += "\nDoes not match the generator used previously: "; - message += *genName; - message += "\nEither remove the CMakeCache.txt file and CMakeFiles " - "directory or choose a different binary directory."; + std::string message = + cmStrCat("Error: generator : ", this->GlobalGenerator->GetName(), + "\nDoes not match the generator used previously: ", *genName, + "\nEither remove the CMakeCache.txt file and CMakeFiles " + "directory or choose a different binary directory."); cmSystemTools::Error(message); return -2; } @@ -1491,12 +1467,11 @@ int cmake::ActualConfigure() if (const std::string* instance = this->State->GetInitializedCacheValue("CMAKE_GENERATOR_INSTANCE")) { if (this->GeneratorInstanceSet && this->GeneratorInstance != *instance) { - std::string message = "Error: generator instance: "; - message += this->GeneratorInstance; - message += "\nDoes not match the instance used previously: "; - message += *instance; - message += "\nEither remove the CMakeCache.txt file and CMakeFiles " - "directory or choose a different binary directory."; + std::string message = + cmStrCat("Error: generator instance: ", this->GeneratorInstance, + "\nDoes not match the instance used previously: ", *instance, + "\nEither remove the CMakeCache.txt file and CMakeFiles " + "directory or choose a different binary directory."); cmSystemTools::Error(message); return -2; } @@ -1510,12 +1485,11 @@ int cmake::ActualConfigure() this->State->GetInitializedCacheValue("CMAKE_GENERATOR_PLATFORM")) { if (this->GeneratorPlatformSet && this->GeneratorPlatform != *platformName) { - std::string message = "Error: generator platform: "; - message += this->GeneratorPlatform; - message += "\nDoes not match the platform used previously: "; - message += *platformName; - message += "\nEither remove the CMakeCache.txt file and CMakeFiles " - "directory or choose a different binary directory."; + std::string message = cmStrCat( + "Error: generator platform: ", this->GeneratorPlatform, + "\nDoes not match the platform used previously: ", *platformName, + "\nEither remove the CMakeCache.txt file and CMakeFiles " + "directory or choose a different binary directory."); cmSystemTools::Error(message); return -2; } @@ -1528,12 +1502,11 @@ int cmake::ActualConfigure() if (const std::string* tsName = this->State->GetInitializedCacheValue("CMAKE_GENERATOR_TOOLSET")) { if (this->GeneratorToolsetSet && this->GeneratorToolset != *tsName) { - std::string message = "Error: generator toolset: "; - message += this->GeneratorToolset; - message += "\nDoes not match the toolset used previously: "; - message += *tsName; - message += "\nEither remove the CMakeCache.txt file and CMakeFiles " - "directory or choose a different binary directory."; + std::string message = + cmStrCat("Error: generator toolset: ", this->GeneratorToolset, + "\nDoes not match the toolset used previously: ", *tsName, + "\nEither remove the CMakeCache.txt file and CMakeFiles " + "directory or choose a different binary directory."); cmSystemTools::Error(message); return -2; } @@ -1553,7 +1526,7 @@ int cmake::ActualConfigure() this->TruncateOutputLog("CMakeError.log"); } -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) this->FileAPI = cm::make_unique<cmFileAPI>(this); this->FileAPI->ReadQueries(); #endif @@ -1791,8 +1764,8 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure) "Build files cannot be regenerated correctly."); return ret; } - std::string message = "Build files have been written to: "; - message += this->GetHomeOutputDirectory(); + std::string message = cmStrCat("Build files have been written to: ", + this->GetHomeOutputDirectory()); this->UpdateProgress(message, -1); return ret; } @@ -1821,7 +1794,7 @@ int cmake::Generate() // for the Visual Studio and Xcode generators.) this->SaveCache(this->GetHomeOutputDirectory()); -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) this->FileAPI->WriteReplies(); #endif @@ -1836,15 +1809,13 @@ void cmake::AddCacheEntry(const std::string& key, const char* value, this->UnwatchUnusedCli(key); if (key == "CMAKE_WARN_DEPRECATED") { - this->Messenger->SetSuppressDeprecatedWarnings( - value && cmSystemTools::IsOff(value)); + this->Messenger->SetSuppressDeprecatedWarnings(value && cmIsOff(value)); } else if (key == "CMAKE_ERROR_DEPRECATED") { - this->Messenger->SetDeprecatedWarningsAsErrors(cmSystemTools::IsOn(value)); + this->Messenger->SetDeprecatedWarningsAsErrors(cmIsOn(value)); } else if (key == "CMAKE_SUPPRESS_DEVELOPER_WARNINGS") { - this->Messenger->SetSuppressDevWarnings(cmSystemTools::IsOn(value)); + this->Messenger->SetSuppressDevWarnings(cmIsOn(value)); } else if (key == "CMAKE_SUPPRESS_DEVELOPER_ERRORS") { - this->Messenger->SetDevWarningsAsErrors(value && - cmSystemTools::IsOff(value)); + this->Messenger->SetDevWarningsAsErrors(value && cmIsOff(value)); } } @@ -1898,12 +1869,12 @@ const char* cmake::GetCacheDefinition(const std::string& name) const void cmake::AddScriptingCommands() { - GetScriptingCommands(this->State); + GetScriptingCommands(this->GetState()); } void cmake::AddProjectCommands() { - GetProjectCommands(this->State); + GetProjectCommands(this->GetState()); } void cmake::AddDefaultGenerators() @@ -1927,7 +1898,7 @@ void cmake::AddDefaultGenerators() this->Generators.push_back(cmGlobalMinGWMakefileGenerator::NewFactory()); #endif this->Generators.push_back(cmGlobalUnixMakefileGenerator3::NewFactory()); -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) # if defined(__linux__) || defined(_WIN32) this->Generators.push_back(cmGlobalGhsMultiGenerator::NewFactory()); # endif @@ -1953,8 +1924,8 @@ int cmake::LoadCache() // could we not read the cache if (!this->LoadCache(this->GetHomeOutputDirectory())) { // if it does exist, but isn't readable then warn the user - std::string cacheFile = this->GetHomeOutputDirectory(); - cacheFile += "/CMakeCache.txt"; + std::string cacheFile = + cmStrCat(this->GetHomeOutputDirectory(), "/CMakeCache.txt"); if (cmSystemTools::FileExists(cacheFile)) { cmSystemTools::Error( "There is a CMakeCache.txt file for the current binary tree but " @@ -2040,8 +2011,7 @@ void cmake::AppendGlobalGeneratorsDocumentation( for (cmGlobalGeneratorFactory* g : this->Generators) { cmDocumentationEntry e; g->GetDocumentation(e); - if (!foundDefaultOne && - cmSystemTools::StringStartsWith(e.Name, defaultName.c_str())) { + if (!foundDefaultOne && cmHasPrefix(e.Name, defaultName)) { e.CustomNamePrefix = '*'; foundDefaultOne = true; } @@ -2087,7 +2057,7 @@ std::vector<cmDocumentationEntry> cmake::GetGeneratorsDocumentation() void cmake::PrintGeneratorList() { -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP cmDocumentation doc; auto generators = this->GetGeneratorsDocumentation(); doc.AppendSection("Generators", generators); @@ -2109,7 +2079,8 @@ void cmake::UpdateConversionPathTable() ". CMake can not open file."); cmSystemTools::ReportLastSystemError("CMake can not open file."); } else { - std::string a, b; + std::string a; + std::string b; while (!table.eof()) { // two entries per line table >> a; @@ -2132,9 +2103,7 @@ int cmake::CheckBuildSystem() // If no file is provided for the check, we have to rerun. if (this->CheckBuildSystemArgument.empty()) { if (verbose) { - std::ostringstream msg; - msg << "Re-run cmake no build system arguments\n"; - cmSystemTools::Stdout(msg.str()); + cmSystemTools::Stdout("Re-run cmake no build system arguments\n"); } return 1; } @@ -2192,7 +2161,7 @@ int cmake::CheckBuildSystem() // If any byproduct of makefile generation is missing we must re-run. std::vector<std::string> products; if (const char* productStr = mf.GetDefinition("CMAKE_MAKEFILE_PRODUCTS")) { - cmSystemTools::ExpandListArgument(productStr, products); + cmExpandList(productStr, products); } for (std::string const& p : products) { if (!(cmSystemTools::FileExists(p) || cmSystemTools::FileIsSymlink(p))) { @@ -2211,16 +2180,14 @@ int cmake::CheckBuildSystem() const char* dependsStr = mf.GetDefinition("CMAKE_MAKEFILE_DEPENDS"); const char* outputsStr = mf.GetDefinition("CMAKE_MAKEFILE_OUTPUTS"); if (dependsStr && outputsStr) { - cmSystemTools::ExpandListArgument(dependsStr, depends); - cmSystemTools::ExpandListArgument(outputsStr, outputs); + cmExpandList(dependsStr, depends); + cmExpandList(outputsStr, outputs); } if (depends.empty() || outputs.empty()) { // Not enough information was provided to do the test. Just rerun. if (verbose) { - std::ostringstream msg; - msg << "Re-run cmake no CMAKE_MAKEFILE_DEPENDS " - "or CMAKE_MAKEFILE_OUTPUTS :\n"; - cmSystemTools::Stdout(msg.str()); + cmSystemTools::Stdout("Re-run cmake no CMAKE_MAKEFILE_DEPENDS " + "or CMAKE_MAKEFILE_OUTPUTS :\n"); } return 1; } @@ -2236,9 +2203,8 @@ int cmake::CheckBuildSystem() } } else { if (verbose) { - std::ostringstream msg; - msg << "Re-run cmake: build system dependency is missing\n"; - cmSystemTools::Stdout(msg.str()); + cmSystemTools::Stdout( + "Re-run cmake: build system dependency is missing\n"); } return 1; } @@ -2255,9 +2221,8 @@ int cmake::CheckBuildSystem() } } else { if (verbose) { - std::ostringstream msg; - msg << "Re-run cmake: build system output is missing\n"; - cmSystemTools::Stdout(msg.str()); + cmSystemTools::Stdout( + "Re-run cmake: build system output is missing\n"); } return 1; } @@ -2284,9 +2249,7 @@ int cmake::CheckBuildSystem() void cmake::TruncateOutputLog(const char* fname) { - std::string fullPath = this->GetHomeOutputDirectory(); - fullPath += "/"; - fullPath += fname; + std::string fullPath = cmStrCat(this->GetHomeOutputDirectory(), '/', fname); struct stat st; if (::stat(fullPath.c_str(), &st)) { return; @@ -2303,14 +2266,6 @@ void cmake::TruncateOutputLog(const char* fname) } } -inline std::string removeQuotes(const std::string& s) -{ - if (s.front() == '\"' && s.back() == '\"') { - return s.substr(1, s.size() - 2); - } - return s; -} - void cmake::MarkCliAsUsed(const std::string& variable) { this->UsedCliVariables[variable] = true; @@ -2318,13 +2273,13 @@ void cmake::MarkCliAsUsed(const std::string& variable) void cmake::GenerateGraphViz(const std::string& fileName) const { -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP cmGraphVizWriter gvWriter(this->GetGlobalGenerator()); - std::string settingsFile = this->GetHomeOutputDirectory(); - settingsFile += "/CMakeGraphVizOptions.cmake"; - std::string fallbackSettingsFile = this->GetHomeDirectory(); - fallbackSettingsFile += "/CMakeGraphVizOptions.cmake"; + std::string settingsFile = + cmStrCat(this->GetHomeOutputDirectory(), "/CMakeGraphVizOptions.cmake"); + std::string fallbackSettingsFile = + cmStrCat(this->GetHomeDirectory(), "/CMakeGraphVizOptions.cmake"); gvWriter.ReadSettings(settingsFile, fallbackSettingsFile); gvWriter.WritePerTargetFiles(fileName); @@ -2421,8 +2376,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args) // no option assume it is the output file else { if (!cmSystemTools::FileIsFullPath(arg)) { - resultFile = cwd; - resultFile += "/"; + resultFile = cmStrCat(cwd, '/'); } resultFile += arg; writeToStdout = false; @@ -2431,12 +2385,10 @@ int cmake::GetSystemInformation(std::vector<std::string>& args) // we have to find the module directory, so we can copy the files this->AddCMakePaths(); - std::string modulesPath = cmSystemTools::GetCMakeRoot(); - modulesPath += "/Modules"; - std::string inFile = modulesPath; - inFile += "/SystemInformation.cmake"; - std::string outFile = destPath; - outFile += "/CMakeLists.txt"; + std::string modulesPath = + cmStrCat(cmSystemTools::GetCMakeRoot(), "/Modules"); + std::string inFile = cmStrCat(modulesPath, "/SystemInformation.cmake"); + std::string outFile = cmStrCat(destPath, "/CMakeLists.txt"); // Copy file if (!cmsys::SystemTools::CopyFileAlways(inFile, outFile)) { @@ -2447,8 +2399,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args) // do we write to a file or to stdout? if (resultFile.empty()) { - resultFile = cwd; - resultFile += "/__cmake_systeminformation/results.txt"; + resultFile = cmStrCat(cwd, "/__cmake_systeminformation/results.txt"); } { @@ -2504,8 +2455,7 @@ static bool cmakeCheckStampFile(const std::string& stampName) // conjunction with cmLocalVisualStudio7Generator to avoid // repeatedly re-running CMake when the user rebuilds the entire // solution. - std::string stampDepends = stampName; - stampDepends += ".depend"; + std::string stampDepends = cmStrCat(stampName, ".depend"); #if defined(_WIN32) || defined(__CYGWIN__) cmsys::ifstream fin(stampDepends.c_str(), std::ios::in | std::ios::binary); #else @@ -2596,7 +2546,7 @@ std::vector<std::string> cmake::GetDebugConfigs() if (const char* config_list = this->State->GetGlobalProperty("DEBUG_CONFIGURATIONS")) { // Expand the specified list and convert to upper-case. - cmSystemTools::ExpandListArgument(config_list, configs); + cmExpandList(config_list, configs); std::transform(configs.begin(), configs.end(), configs.begin(), cmSystemTools::UpperCase); } @@ -2607,11 +2557,6 @@ std::vector<std::string> cmake::GetDebugConfigs() return configs; } -cmMessenger* cmake::GetMessenger() const -{ - return this->Messenger; -} - int cmake::Build(int jobs, const std::string& dir, const std::vector<std::string>& targets, const std::string& config, @@ -2672,7 +2617,7 @@ int cmake::Build(int jobs, const std::string& dir, const char* cachedVerbose = this->State->GetCacheEntryValue("CMAKE_VERBOSE_MAKEFILE"); - if (cmSystemTools::IsOn(cachedVerbose)) { + if (cmIsOn(cachedVerbose)) { verbose = true; } @@ -2720,8 +2665,8 @@ int cmake::Build(int jobs, const std::string& dir, "Build files cannot be regenerated correctly."); return ret; } - std::string message = "Build files have been written to: "; - message += this->GetHomeOutputDirectory(); + std::string message = cmStrCat("Build files have been written to: ", + this->GetHomeOutputDirectory()); this->UpdateProgress(message, -1); // Restore the previously set directories to their original value. @@ -2782,9 +2727,9 @@ bool cmake::Open(const std::string& dir, bool dryRun) void cmake::WatchUnusedCli(const std::string& var) { -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP this->VariableWatch->AddWatch(var, cmWarnUnusedCliWarning, this); - if (this->UsedCliVariables.find(var) == this->UsedCliVariables.end()) { + if (!cmContains(this->UsedCliVariables, var)) { this->UsedCliVariables[var] = false; } #endif @@ -2792,7 +2737,7 @@ void cmake::WatchUnusedCli(const std::string& var) void cmake::UnwatchUnusedCli(const std::string& var) { -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP this->VariableWatch->RemoveWatch(var, cmWarnUnusedCliWarning); this->UsedCliVariables.erase(var); #endif @@ -2800,7 +2745,7 @@ void cmake::UnwatchUnusedCli(const std::string& var) void cmake::RunCheckForUnusedVariables() { -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP bool haveUnused = false; std::ostringstream msg; msg << "Manually-specified variables were not used by the project:"; diff --git a/Source/cmake.h b/Source/cmake.h index fa4409a..081e120 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -7,12 +7,13 @@ #include <functional> #include <map> -#include <memory> // IWYU pragma: keep +#include <memory> #include <set> #include <string> #include <unordered_set> #include <vector> +#include "cmGeneratedFileStream.h" #include "cmInstalledFile.h" #include "cmListFileCache.h" #include "cmMessageType.h" @@ -20,7 +21,7 @@ #include "cmStateSnapshot.h" #include "cmStateTypes.h" -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) # include "cm_jsoncpp_value.h" #endif @@ -121,6 +122,17 @@ public: bool isAlias; }; + struct FileExtensions + { + bool Test(std::string const& ext) const + { + return (this->unordered.find(ext) != this->unordered.end()); + } + + std::vector<std::string> ordered; + std::unordered_set<std::string> unordered; + }; + typedef std::map<std::string, cmInstalledFile> InstalledFilesMap; static const int NO_BUILD_PARALLEL_LEVEL = -1; @@ -134,7 +146,7 @@ public: cmake(cmake const&) = delete; cmake& operator=(cmake const&) = delete; -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) Json::Value ReportVersionJson() const; Json::Value ReportCapabilitiesJson() const; #endif @@ -233,24 +245,42 @@ public: const std::vector<std::string>& GetSourceExtensions() const { - return this->SourceFileExtensions; + return this->SourceFileExtensions.ordered; } bool IsSourceExtension(const std::string& ext) const { - return this->SourceFileExtensionsSet.find(ext) != - this->SourceFileExtensionsSet.end(); + return this->SourceFileExtensions.Test(ext); } const std::vector<std::string>& GetHeaderExtensions() const { - return this->HeaderFileExtensions; + return this->HeaderFileExtensions.ordered; } bool IsHeaderExtension(const std::string& ext) const { - return this->HeaderFileExtensionsSet.find(ext) != - this->HeaderFileExtensionsSet.end(); + return this->HeaderFileExtensions.Test(ext); + } + + const std::vector<std::string>& GetCudaExtensions() const + { + return this->CudaFileExtensions.ordered; + } + + bool IsCudaExtension(const std::string& ext) const + { + return this->CudaFileExtensions.Test(ext); + } + + const std::vector<std::string>& GetFortranExtensions() const + { + return this->FortranFileExtensions.ordered; + } + + bool IsFortranExtension(const std::string& ext) const + { + return this->FortranFileExtensions.Test(ext); } // Strips the extension (if present and known) from a filename @@ -305,9 +335,9 @@ public: //! this is called by generators to update the progress void UpdateProgress(const std::string& msg, float prog); -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) //! Get the variable watch object - cmVariableWatch* GetVariableWatch() { return this->VariableWatch; } + cmVariableWatch* GetVariableWatch() { return this->VariableWatch.get(); } #endif std::vector<cmDocumentationEntry> GetGeneratorsDocumentation(); @@ -348,18 +378,18 @@ public: /** * Get the file comparison class */ - cmFileTimeCache* GetFileTimeCache() { return this->FileTimeCache; } + cmFileTimeCache* GetFileTimeCache() { return this->FileTimeCache.get(); } - // Get the selected log level for `message()` commands during the cmake run. + //! Get the selected log level for `message()` commands during the cmake run. LogLevel GetLogLevel() const { return this->MessageLogLevel; } void SetLogLevel(LogLevel level) { this->MessageLogLevel = level; } static LogLevel StringToLogLevel(const std::string& levelStr); - // Do we want debug output during the cmake run. + //! Do we want debug output during the cmake run. bool GetDebugOutput() { return this->DebugOutput; } void SetDebugOutputOn(bool b) { this->DebugOutput = b; } - // Do we want trace output during the cmake run. + //! Do we want trace output during the cmake run. bool GetTrace() { return this->Trace; } void SetTrace(bool b) { this->Trace = b; } bool GetTraceExpand() { return this->TraceExpand; } @@ -372,6 +402,9 @@ public: { return this->TraceOnlyThisSources; } + cmGeneratedFileStream& GetTraceFile() { return this->TraceFile; } + void SetTraceFile(std::string const& file); + bool GetWarnUninitialized() { return this->WarnUninitialized; } void SetWarnUninitialized(bool b) { this->WarnUninitialized = b; } bool GetWarnUnused() { return this->WarnUnused; } @@ -396,31 +429,31 @@ public: return this->CMakeEditCommand; } - cmMessenger* GetMessenger() const; + cmMessenger* GetMessenger() const { return this->Messenger.get(); } - /* + /** * Get the state of the suppression of developer (author) warnings. * Returns false, by default, if developer warnings should be shown, true * otherwise. */ bool GetSuppressDevWarnings() const; - /* + /** * Set the state of the suppression of developer (author) warnings. */ void SetSuppressDevWarnings(bool v); - /* + /** * Get the state of the suppression of deprecated warnings. * Returns false, by default, if deprecated warnings should be shown, true * otherwise. */ bool GetSuppressDeprecatedWarnings() const; - /* + /** * Set the state of the suppression of deprecated warnings. */ void SetSuppressDeprecatedWarnings(bool v); - /* + /** * Get the state of treating developer (author) warnings as errors. * Returns false, by default, if warnings should not be treated as errors, * true otherwise. @@ -431,7 +464,7 @@ public: */ void SetDevWarningsAsErrors(bool v); - /* + /** * Get the state of treating deprecated warnings as errors. * Returns false, by default, if warnings should not be treated as errors, * true otherwise. @@ -459,7 +492,7 @@ public: void UnwatchUnusedCli(const std::string& var); void WatchUnusedCli(const std::string& var); - cmState* GetState() const { return this->State; } + cmState* GetState() const { return this->State.get(); } void SetCurrentSnapshot(cmStateSnapshot const& snapshot) { this->CurrentSnapshot = snapshot; @@ -480,14 +513,14 @@ protected: void AddDefaultGenerators(); void AddDefaultExtraGenerators(); - cmGlobalGenerator* GlobalGenerator; + cmGlobalGenerator* GlobalGenerator = nullptr; std::map<std::string, DiagLevel> DiagLevels; std::string GeneratorInstance; std::string GeneratorPlatform; std::string GeneratorToolset; - bool GeneratorInstanceSet; - bool GeneratorPlatformSet; - bool GeneratorToolsetSet; + bool GeneratorInstanceSet = false; + bool GeneratorPlatformSet = false; + bool GeneratorToolsetSet = false; //! read in a cmake list file to initialize the cache void ReadListFile(const std::vector<std::string>& args, @@ -514,14 +547,15 @@ protected: private: ProgressCallbackType ProgressCallback; - WorkingMode CurrentWorkingMode; - bool DebugOutput; - bool Trace; - bool TraceExpand; - bool WarnUninitialized; - bool WarnUnused; - bool WarnUnusedCli; - bool CheckSystemVars; + WorkingMode CurrentWorkingMode = NORMAL_MODE; + bool DebugOutput = false; + bool Trace = false; + bool TraceExpand = false; + cmGeneratedFileStream TraceFile; + bool WarnUninitialized = false; + bool WarnUnused = false; + bool WarnUnusedCli = true; + bool CheckSystemVars = false; std::map<std::string, bool> UsedCliVariables; std::string CMakeEditCommand; std::string CXXEnvironment; @@ -531,24 +565,24 @@ private: std::string CheckStampList; std::string VSSolutionFile; std::string EnvironmentGenerator; - std::vector<std::string> SourceFileExtensions; - std::unordered_set<std::string> SourceFileExtensionsSet; - std::vector<std::string> HeaderFileExtensions; - std::unordered_set<std::string> HeaderFileExtensionsSet; - bool ClearBuildSystem; - bool DebugTryCompile; - cmFileTimeCache* FileTimeCache; + FileExtensions SourceFileExtensions; + FileExtensions HeaderFileExtensions; + FileExtensions CudaFileExtensions; + FileExtensions FortranFileExtensions; + bool ClearBuildSystem = false; + bool DebugTryCompile = false; + std::unique_ptr<cmFileTimeCache> FileTimeCache; std::string GraphVizFile; InstalledFilesMap InstalledFiles; -#if defined(CMAKE_BUILD_WITH_CMAKE) - cmVariableWatch* VariableWatch; +#if !defined(CMAKE_BOOTSTRAP) + std::unique_ptr<cmVariableWatch> VariableWatch; std::unique_ptr<cmFileAPI> FileAPI; #endif - cmState* State; + std::unique_ptr<cmState> State; cmStateSnapshot CurrentSnapshot; - cmMessenger* Messenger; + std::unique_ptr<cmMessenger> Messenger; std::vector<std::string> TraceOnlyThisSources; @@ -556,7 +590,7 @@ private: void UpdateConversionPathTable(); - // Print a list of valid generators to stderr. + //! Print a list of valid generators to stderr. void PrintGeneratorList(); std::unique_ptr<cmGlobalGenerator> EvaluateDefaultGlobalGenerator(); diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index a6348b3..2b51a2a 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -7,11 +7,12 @@ #include "cmMakefile.h" #include "cmState.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmake.h" #include "cmcmd.h" -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP # include "cmDocumentation.h" # include "cmDynamicLoader.h" #endif @@ -19,7 +20,7 @@ #include "cm_uv.h" #include "cmsys/Encoding.hxx" -#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) +#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP) # include "cmsys/ConsoleBuf.hxx" #endif @@ -31,13 +32,14 @@ #include <string> #include <vector> -#ifdef CMAKE_BUILD_WITH_CMAKE -static const char* cmDocumentationName[][2] = { +namespace { +#ifndef CMAKE_BOOTSTRAP +const char* cmDocumentationName[][2] = { { nullptr, " cmake - Cross-Platform Makefile Generator." }, { nullptr, nullptr } }; -static const char* cmDocumentationUsage[][2] = { +const char* cmDocumentationUsage[][2] = { { nullptr, " cmake [options] <path-to-source>\n" " cmake [options] <path-to-existing-build>\n" @@ -49,40 +51,12 @@ static const char* cmDocumentationUsage[][2] = { { nullptr, nullptr } }; -static const char* cmDocumentationUsageNote[][2] = { +const char* cmDocumentationUsageNote[][2] = { { nullptr, "Run 'cmake --help' for more information." }, { nullptr, nullptr } }; -# define CMAKE_BUILD_OPTIONS \ - " <dir> = Project binary directory to be built.\n" \ - " --parallel [<jobs>], -j [<jobs>]\n" \ - " = Build in parallel using the given number of jobs. \n" \ - " If <jobs> is omitted the native build tool's \n" \ - " default number is used.\n" \ - " The CMAKE_BUILD_PARALLEL_LEVEL environment " \ - "variable\n" \ - " specifies a default parallel level when this " \ - "option\n" \ - " is not given.\n" \ - " --target <tgt>..., -t <tgt>... \n" \ - " = Build <tgt> instead of default targets.\n" \ - " --config <cfg> = For multi-configuration tools, choose <cfg>.\n" \ - " --clean-first = Build target 'clean' first, then build.\n" \ - " (To clean only, use --target 'clean'.)\n" \ - " --verbose, -v = Enable verbose output - if supported - including\n" \ - " the build commands to be executed. \n" \ - " -- = Pass remaining options to the native tool.\n" - -# define CMAKE_INSTALL_OPTIONS \ - " <dir> = Project binary directory to install.\n" \ - " --config <cfg> = For multi-configuration tools, choose <cfg>.\n" \ - " --component <comp> = Component-based install. Only install <comp>.\n" \ - " --prefix <prefix> = The installation prefix CMAKE_INSTALL_PREFIX.\n" \ - " --strip = Performing install/strip.\n" \ - " -v --verbose = Enable verbose output.\n" - -static const char* cmDocumentationOptions[][2] = { +const char* cmDocumentationOptions[][2] = { CMAKE_STANDARD_OPTIONS_TABLE, { "-E", "CMake command mode." }, { "-L[A][H]", "List non-advanced cached variables." }, @@ -106,6 +80,8 @@ static const char* cmDocumentationOptions[][2] = { { "--trace-expand", "Put cmake in trace mode with variable expansion." }, { "--trace-source=<file>", "Trace only this CMake file/module. Multiple options allowed." }, + { "--trace-redirect=<file>", + "Redirect trace output to a file instead of stderr." }, { "--warn-uninitialized", "Warn about uninitialized values." }, { "--warn-unused-vars", "Warn about unused variables." }, { "--no-warn-unused-cli", "Don't warn about command line options." }, @@ -117,7 +93,7 @@ static const char* cmDocumentationOptions[][2] = { #endif -static int do_command(int ac, char const* const* av) +int do_command(int ac, char const* const* av) { std::vector<std::string> args; args.reserve(ac - 1); @@ -126,12 +102,7 @@ static int do_command(int ac, char const* const* av) return cmcmd::ExecuteCMakeCommand(args); } -int do_cmake(int ac, char const* const* av); -static int do_build(int ac, char const* const* av); -static int do_install(int ac, char const* const* av); -static int do_open(int ac, char const* const* av); - -static cmMakefile* cmakemainGetMakefile(cmake* cm) +cmMakefile* cmakemainGetMakefile(cmake* cm) { if (cm && cm->GetDebugOutput()) { cmGlobalGenerator* gg = cm->GetGlobalGenerator(); @@ -142,7 +113,7 @@ static cmMakefile* cmakemainGetMakefile(cmake* cm) return nullptr; } -static std::string cmakemainGetStack(cmake* cm) +std::string cmakemainGetStack(cmake* cm) { std::string msg; cmMakefile* mf = cmakemainGetMakefile(cm); @@ -156,70 +127,25 @@ static std::string cmakemainGetStack(cmake* cm) return msg; } -static void cmakemainMessageCallback(const std::string& m, - const char* /*unused*/, cmake* cm) +void cmakemainMessageCallback(const std::string& m, const char* /*unused*/, + cmake* cm) { - std::cerr << m << cmakemainGetStack(cm) << std::endl << std::flush; + std::cerr << m << cmakemainGetStack(cm) << std::endl; } -static void cmakemainProgressCallback(const std::string& m, float prog, - cmake* cm) +void cmakemainProgressCallback(const std::string& m, float prog, cmake* cm) { cmMakefile* mf = cmakemainGetMakefile(cm); std::string dir; if (mf && cmHasLiteralPrefix(m, "Configuring") && (prog < 0)) { - dir = " "; - dir += mf->GetCurrentSourceDirectory(); + dir = cmStrCat(' ', mf->GetCurrentSourceDirectory()); } else if (mf && cmHasLiteralPrefix(m, "Generating")) { - dir = " "; - dir += mf->GetCurrentBinaryDirectory(); + dir = cmStrCat(' ', mf->GetCurrentBinaryDirectory()); } if ((prog < 0) || (!dir.empty())) { std::cout << "-- " << m << dir << cmakemainGetStack(cm) << std::endl; } - - std::cout.flush(); -} - -int main(int ac, char const* const* av) -{ - cmSystemTools::EnsureStdPipes(); -#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) - // Replace streambuf so we can output Unicode to console - cmsys::ConsoleBuf::Manager consoleOut(std::cout); - consoleOut.SetUTF8Pipes(); - cmsys::ConsoleBuf::Manager consoleErr(std::cerr, true); - consoleErr.SetUTF8Pipes(); -#endif - cmsys::Encoding::CommandLineArguments args = - cmsys::Encoding::CommandLineArguments::Main(ac, av); - ac = args.argc(); - av = args.argv(); - - cmSystemTools::EnableMSVCDebugHook(); - cmSystemTools::InitializeLibUV(); - cmSystemTools::FindCMakeResources(av[0]); - if (ac > 1) { - if (strcmp(av[1], "--build") == 0) { - return do_build(ac, av); - } - if (strcmp(av[1], "--install") == 0) { - return do_install(ac, av); - } - if (strcmp(av[1], "--open") == 0) { - return do_open(ac, av); - } - if (strcmp(av[1], "-E") == 0) { - return do_command(ac, av); - } - } - int ret = do_cmake(ac, av); -#ifdef CMAKE_BUILD_WITH_CMAKE - cmDynamicLoader::FlushCache(); -#endif - uv_loop_close(uv_default_loop()); - return ret; } int do_cmake(int ac, char const* const* av) @@ -230,7 +156,7 @@ int do_cmake(int ac, char const* const* av) return 1; } -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP cmDocumentation doc; doc.addCMakeStandardDocSections(); if (doc.CheckOptions(ac, av)) { @@ -381,7 +307,6 @@ int do_cmake(int ac, char const* const* av) return 0; } -namespace { int extract_job_number(int& index, char const* current, char const* next, int len_of_flag) { @@ -396,7 +321,7 @@ int extract_job_number(int& index, char const* current, char const* next, unsigned long numJobs = 0; if (jobString.empty()) { jobs = cmake::DEFAULT_BUILD_PARALLEL_LEVEL; - } else if (cmSystemTools::StringToULong(jobString.c_str(), &numJobs)) { + } else if (cmStrToULong(jobString, &numJobs)) { if (numJobs == 0) { std::cerr << "The <jobs> value requires a positive integer argument.\n\n"; @@ -411,11 +336,10 @@ int extract_job_number(int& index, char const* current, char const* next, } return jobs; } -} -static int do_build(int ac, char const* const* av) +int do_build(int ac, char const* const* av) { -#ifndef CMAKE_BUILD_WITH_CMAKE +#ifdef CMAKE_BOOTSTRAP std::cerr << "This cmake does not support --build\n"; return -1; #else @@ -515,7 +439,7 @@ static int do_build(int ac, char const* const* av) jobs = cmake::DEFAULT_BUILD_PARALLEL_LEVEL; } else { unsigned long numJobs = 0; - if (cmSystemTools::StringToULong(parallel.c_str(), &numJobs)) { + if (cmStrToULong(parallel, &numJobs)) { if (numJobs == 0) { std::cerr << "The CMAKE_BUILD_PARALLEL_LEVEL environment variable " "requires a positive integer argument.\n\n"; @@ -541,7 +465,24 @@ static int do_build(int ac, char const* const* av) std::cerr << "Usage: cmake --build <dir> [options] [-- [native-options]]\n" "Options:\n" - CMAKE_BUILD_OPTIONS + " <dir> = Project binary directory to be built.\n" + " --parallel [<jobs>], -j [<jobs>]\n" + " = Build in parallel using the given number of jobs. \n" + " If <jobs> is omitted the native build tool's \n" + " default number is used.\n" + " The CMAKE_BUILD_PARALLEL_LEVEL environment " + "variable\n" + " specifies a default parallel level when this " + "option\n" + " is not given.\n" + " --target <tgt>..., -t <tgt>... \n" + " = Build <tgt> instead of default targets.\n" + " --config <cfg> = For multi-configuration tools, choose <cfg>.\n" + " --clean-first = Build target 'clean' first, then build.\n" + " (To clean only, use --target 'clean'.)\n" + " --verbose, -v = Enable verbose output - if supported - including\n" + " the build commands to be executed. \n" + " -- = Pass remaining options to the native tool.\n" ; /* clang-format on */ return 1; @@ -560,9 +501,9 @@ static int do_build(int ac, char const* const* av) #endif } -static int do_install(int ac, char const* const* av) +int do_install(int ac, char const* const* av) { -#ifndef CMAKE_BUILD_WITH_CMAKE +#ifdef CMAKE_BOOTSTRAP std::cerr << "This cmake does not support --install\n"; return -1; #else @@ -627,8 +568,18 @@ static int do_install(int ac, char const* const* av) } if (dir.empty()) { - std::cerr << "Usage: cmake --install <dir> " - "[options]\nOptions:\n" CMAKE_INSTALL_OPTIONS; + /* clang-format off */ + std::cerr << + "Usage: cmake --install <dir> [options]\n" + "Options:\n" + " <dir> = Project binary directory to install.\n" + " --config <cfg> = For multi-configuration tools, choose <cfg>.\n" + " --component <comp> = Component-based install. Only install <comp>.\n" + " --prefix <prefix> = The installation prefix CMAKE_INSTALL_PREFIX.\n" + " --strip = Performing install/strip.\n" + " -v --verbose = Enable verbose output.\n" + ; + /* clang-format on */ return 1; } @@ -671,9 +622,9 @@ static int do_install(int ac, char const* const* av) #endif } -static int do_open(int ac, char const* const* av) +int do_open(int ac, char const* const* av) { -#ifndef CMAKE_BUILD_WITH_CMAKE +#ifdef CMAKE_BOOTSTRAP std::cerr << "This cmake does not support --open\n"; return -1; #else @@ -713,3 +664,44 @@ static int do_open(int ac, char const* const* av) return cm.Open(dir, false) ? 0 : 1; #endif } +} // namespace + +int main(int ac, char const* const* av) +{ + cmSystemTools::EnsureStdPipes(); +#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP) + // Replace streambuf so we can output Unicode to console + cmsys::ConsoleBuf::Manager consoleOut(std::cout); + consoleOut.SetUTF8Pipes(); + cmsys::ConsoleBuf::Manager consoleErr(std::cerr, true); + consoleErr.SetUTF8Pipes(); +#endif + cmsys::Encoding::CommandLineArguments args = + cmsys::Encoding::CommandLineArguments::Main(ac, av); + ac = args.argc(); + av = args.argv(); + + cmSystemTools::EnableMSVCDebugHook(); + cmSystemTools::InitializeLibUV(); + cmSystemTools::FindCMakeResources(av[0]); + if (ac > 1) { + if (strcmp(av[1], "--build") == 0) { + return do_build(ac, av); + } + if (strcmp(av[1], "--install") == 0) { + return do_install(ac, av); + } + if (strcmp(av[1], "--open") == 0) { + return do_open(ac, av); + } + if (strcmp(av[1], "-E") == 0) { + return do_command(ac, av); + } + } + int ret = do_cmake(ac, av); +#ifndef CMAKE_BOOTSTRAP + cmDynamicLoader::FlushCache(); +#endif + uv_loop_close(uv_default_loop()); + return ret; +} diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 86082e5..2be8bae 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -13,23 +13,24 @@ #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmUtils.hxx" #include "cmVersion.h" #include "cmake.h" -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) # include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback. # include "cmServer.h" # include "cmServerConnection.h" #endif -#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32) +#if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32) # include "bindexplib.h" # include "cmsys/ConsoleBuf.hxx" #endif -#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32) && !defined(__CYGWIN__) +#if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32) && !defined(__CYGWIN__) # include "cmVisualStudioWCEPlatformParser.h" #endif @@ -37,11 +38,9 @@ #include "cmsys/FStream.hxx" #include "cmsys/Process.h" #include "cmsys/Terminal.h" -#include <algorithm> #include <array> #include <iostream> -#include <iterator> -#include <memory> // IWYU pragma: keep +#include <memory> #include <sstream> #include <stdio.h> #include <stdlib.h> @@ -60,7 +59,7 @@ void CMakeCommandUsage(const char* program) { std::ostringstream errorStream; -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP /* clang-format off */ errorStream << "cmake version " << cmVersion::GetCMakeVersion() << "\n"; @@ -114,6 +113,8 @@ void CMakeCommandUsage(const char* program) << " touch <file>... - touch a <file>.\n" << " touch_nocreate <file>... - touch a <file> but do not create it.\n" << " create_symlink old new - create a symbolic link new -> old\n" + << " true - do nothing with an exit code of 0\n" + << " false - do nothing with an exit code of 1\n" #if defined(_WIN32) && !defined(__CYGWIN__) << "Available on Windows only:\n" << " delete_regv key - delete registry value\n" @@ -171,8 +172,7 @@ static int HandleIWYU(const std::string& runCmd, { // Construct the iwyu command line by taking what was given // and adding all the arguments we give to the compiler. - std::vector<std::string> iwyu_cmd; - cmSystemTools::ExpandListArgument(runCmd, iwyu_cmd, true); + std::vector<std::string> iwyu_cmd = cmExpandedList(runCmd, true); cmAppend(iwyu_cmd, orig_cmd.begin() + 1, orig_cmd.end()); // Run the iwyu command line. Capture its stderr and hide its stdout. // Ignore its return code because the tool always returns non-zero. @@ -201,8 +201,7 @@ static int HandleTidy(const std::string& runCmd, const std::string& sourceFile, // automatically skip over the compiler itself and extract the // options. int ret; - std::vector<std::string> tidy_cmd = - cmSystemTools::ExpandedListArgument(runCmd, true); + std::vector<std::string> tidy_cmd = cmExpandedList(runCmd, true); tidy_cmd.push_back(sourceFile); tidy_cmd.emplace_back("--"); cmAppend(tidy_cmd, orig_cmd); @@ -262,8 +261,7 @@ static int HandleCppLint(const std::string& runCmd, const std::vector<std::string>&) { // Construct the cpplint command line. - std::vector<std::string> cpplint_cmd; - cmSystemTools::ExpandListArgument(runCmd, cpplint_cmd, true); + std::vector<std::string> cpplint_cmd = cmExpandedList(runCmd, true); cpplint_cmd.push_back(sourceFile); // Run the cpplint command line. Capture its output. @@ -291,8 +289,7 @@ static int HandleCppCheck(const std::string& runCmd, const std::vector<std::string>& orig_cmd) { // Construct the cpplint command line. - std::vector<std::string> cppcheck_cmd; - cmSystemTools::ExpandListArgument(runCmd, cppcheck_cmd, true); + std::vector<std::string> cppcheck_cmd = cmExpandedList(runCmd, true); // extract all the -D, -U, and -I options from the compile line for (auto const& opt : orig_cmd) { if (opt.size() > 2) { @@ -405,7 +402,7 @@ int cmcmd::HandleCoCompileCommands(std::vector<std::string> const& args) if (cmHasLiteralPrefix(arg, "--source=")) { sourceFile = arg.substr(9); } else if (cmHasLiteralPrefix(arg, "--launcher=")) { - cmSystemTools::ExpandListArgument(arg.substr(11), launchers, true); + cmExpandList(arg.substr(11), launchers, true); } else { // if it was not a co-compiler or --source/--launcher then error std::cerr << "__run_co_compile given unknown argument: " << arg @@ -558,7 +555,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) return 0; } -#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) +#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP) else if (args[1] == "__create_def") { if (args.size() < 4) { std::cerr @@ -651,7 +648,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) return 1; } -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) if (args[1] == "environment") { for (auto const& env : cmSystemTools::GetEnvironmentVariables()) { std::cout << env << std::endl; @@ -763,8 +760,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) if (args[1] == "time" && args.size() > 2) { std::vector<std::string> command(args.begin() + 2, args.end()); - clock_t clock_start, clock_finish; - time_t time_start, time_finish; + clock_t clock_start; + clock_t clock_finish; + time_t time_start; + time_t time_finish; time(&time_start); clock_start = clock(); @@ -835,8 +834,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) // Command to start progress for a build if (args[1] == "cmake_progress_start" && args.size() == 4) { // basically remove the directory - std::string dirName = args[2]; - dirName += "/Progress"; + std::string dirName = cmStrCat(args[2], "/Progress"); cmSystemTools::RemoveADirectory(dirName); // is the last argument a filename that exists? @@ -853,8 +851,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) if (count) { cmSystemTools::MakeDirectory(dirName); // write the count into the directory - std::string fName = dirName; - fName += "/count.txt"; + std::string fName = cmStrCat(dirName, "/count.txt"); FILE* progFile = cmsys::SystemTools::Fopen(fName, "w"); if (progFile) { fprintf(progFile, "%i\n", count); @@ -891,6 +888,16 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) return 0; } + // Command to do nothing with an exit code of 0. + if (args[1] == "true") { + return 0; + } + + // Command to do nothing with an exit code of 1. + if (args[1] == "false") { + return 1; + } + // Internal CMake shared library support. if (args[1] == "cmake_symlink_library" && args.size() == 5) { return cmcmd::SymlinkLibrary(args); @@ -933,8 +940,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) if (args.size() >= 9 && args[8].length() >= 8 && args[8].substr(0, 8) == "--color=") { // Enable or disable color based on the switch value. - color = - (args[8].size() == 8 || cmSystemTools::IsOn(args[8].substr(8))); + color = (args[8].size() == 8 || cmIsOn(args[8].substr(8))); } } else { // Support older signature for existing makefiles: @@ -981,7 +987,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) return cmcmd::ExecuteLinkScript(args); } -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP // Internal CMake ninja dependency scanning support. if (args[1] == "cmake_ninja_depends") { return cmcmd_cmake_ninja_depends(args.begin() + 2, args.end()); @@ -1016,7 +1022,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) return cmcmd::ExecuteEchoColor(args); } -#ifdef CMAKE_BUILD_WITH_CMAKE +#ifndef CMAKE_BOOTSTRAP if ((args[1] == "cmake_autogen") && (args.size() >= 4)) { cmQtAutoMocUic autoGen; std::string const& infoDir = args[2]; @@ -1063,11 +1069,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) } } else if (cmHasLiteralPrefix(arg, "--format=")) { format = arg.substr(9); - bool isKnown = - std::find(cm::cbegin(knownFormats), cm::cend(knownFormats), - format) != cm::cend(knownFormats); - - if (!isKnown) { + if (!cmContains(knownFormats, format)) { cmSystemTools::Error("Unknown -E tar --format= argument: " + format); return 1; @@ -1197,7 +1199,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) return 1; } } -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) cmConnection* conn; if (isDebug) { conn = new cmServerStdIoConnection; @@ -1218,7 +1220,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) return 1; } -#if defined(CMAKE_BUILD_WITH_CMAKE) +#if !defined(CMAKE_BOOTSTRAP) // Internal CMake Fortran module support. if (args[1] == "cmake_copy_f90_mod" && args.size() >= 4) { return cmDependsFortran::CopyModule(args) ? 0 : 1; @@ -1339,14 +1341,12 @@ bool cmcmd::SymlinkInternal(std::string const& file, std::string const& link) static void cmcmdProgressReport(std::string const& dir, std::string const& num) { - std::string dirName = dir; - dirName += "/Progress"; + std::string dirName = cmStrCat(dir, "/Progress"); std::string fName; FILE* progFile; // read the count - fName = dirName; - fName += "/count.txt"; + fName = cmStrCat(dirName, "/count.txt"); progFile = cmsys::SystemTools::Fopen(fName, "r"); int count = 0; if (!progFile) { @@ -1361,8 +1361,7 @@ static void cmcmdProgressReport(std::string const& dir, std::string const& num) for (const char* c = last;; ++c) { if (*c == ',' || *c == '\0') { if (c != last) { - fName = dirName; - fName += "/"; + fName = cmStrCat(dirName, '/'); fName.append(last, c - last); progFile = cmsys::SystemTools::Fopen(fName, "w"); if (progFile) { @@ -1399,7 +1398,7 @@ int cmcmd::ExecuteEchoColor(std::vector<std::string> const& args) // Enable or disable color based on the switch value. std::string value = arg.substr(9); if (!value.empty()) { - enabled = cmSystemTools::IsOn(value); + enabled = cmIsOn(value); } } else if (cmHasLiteralPrefix(arg, "--progress-dir=")) { progressDir = arg.substr(15); @@ -1451,7 +1450,7 @@ int cmcmd::ExecuteLinkScript(std::vector<std::string> const& args) bool verbose = false; if (args.size() >= 4) { if (args[3].find("--verbose=") == 0) { - if (!cmSystemTools::IsOff(args[3].substr(10))) { + if (!cmIsOff(args[3].substr(10))) { verbose = true; } } @@ -1534,7 +1533,7 @@ int cmcmd::ExecuteLinkScript(std::vector<std::string> const& args) int cmcmd::WindowsCEEnvironment(const char* version, const std::string& name) { -#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(_WIN32) && !defined(__CYGWIN__) +#if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32) && !defined(__CYGWIN__) cmVisualStudioWCEPlatformParser parser(name.c_str()); parser.ParseVersion(version); if (parser.Found()) { @@ -1592,7 +1591,7 @@ private: // still works. int cmcmd::VisualStudioLink(std::vector<std::string> const& args, int type) { -#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) +#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP) // Replace streambuf so we output in the system codepage. CMake is set up // to output in Unicode (see SetUTF8Pipes) but the Visual Studio linker // outputs using the system codepage so we need to change behavior when diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 3b3630f..a69ba15 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -8,7 +8,7 @@ #include "cmSystemTools.h" #include "cmsys/Encoding.hxx" -#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) +#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP) # include "cmsys/ConsoleBuf.hxx" #endif #include <iostream> @@ -83,7 +83,9 @@ static const char* cmDocumentationOptions[][2] = { { "-T <action>, --test-action <action>", "Sets the dashboard action to " "perform" }, - { "--track <track>", "Specify the track to submit dashboard to" }, + { "--group <group>", + "Specify what build group on the dashboard you'd like to " + "submit results to." }, { "-S <script>, --script <script>", "Execute a dashboard for a " "configuration" }, @@ -144,7 +146,7 @@ static const char* cmDocumentationOptions[][2] = { int main(int argc, char const* const* argv) { cmSystemTools::EnsureStdPipes(); -#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) +#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP) // Replace streambuf so we can output Unicode to console cmsys::ConsoleBuf::Manager consoleOut(std::cout); consoleOut.SetUTF8Pipes(); diff --git a/Source/kwsys/CommandLineArguments.cxx b/Source/kwsys/CommandLineArguments.cxx index a97f7a8..dc9f01d 100644 --- a/Source/kwsys/CommandLineArguments.cxx +++ b/Source/kwsys/CommandLineArguments.cxx @@ -67,10 +67,10 @@ class CommandLineArgumentsInternal { public: CommandLineArgumentsInternal() + : UnknownArgumentCallback{ KWSYS_NULLPTR } + , ClientData{ KWSYS_NULLPTR } + , LastArgument{ 0 } { - this->UnknownArgumentCallback = KWSYS_NULLPTR; - this->ClientData = KWSYS_NULLPTR; - this->LastArgument = 0; } typedef CommandLineArgumentsVectorOfStrings VectorOfStrings; diff --git a/Source/kwsys/RegularExpression.cxx b/Source/kwsys/RegularExpression.cxx index 5f84b19..3e10765 100644 --- a/Source/kwsys/RegularExpression.cxx +++ b/Source/kwsys/RegularExpression.cxx @@ -337,7 +337,6 @@ bool RegularExpression::compile(const char* exp) { const char* scan; const char* longest; - size_t len; int flags; if (exp == KWSYS_NULLPTR) { @@ -412,7 +411,7 @@ bool RegularExpression::compile(const char* exp) // if (flags & SPSTART) { longest = KWSYS_NULLPTR; - len = 0; + size_t len = 0; for (; scan != KWSYS_NULLPTR; scan = regnext(scan)) if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) { longest = OPERAND(scan); diff --git a/Source/kwsys/RegularExpression.hxx.in b/Source/kwsys/RegularExpression.hxx.in index b7b93f9..ed86418 100644 --- a/Source/kwsys/RegularExpression.hxx.in +++ b/Source/kwsys/RegularExpression.hxx.in @@ -407,8 +407,12 @@ private: * Create an empty regular expression. */ inline RegularExpression::RegularExpression() + : regstart{} + , reganch{} + , regmust{} + , program{ 0 } + , progsize{} { - this->program = 0; } /** @@ -416,8 +420,12 @@ inline RegularExpression::RegularExpression() * compiles s. */ inline RegularExpression::RegularExpression(const char* s) + : regstart{} + , reganch{} + , regmust{} + , program{ 0 } + , progsize{} { - this->program = 0; if (s) { this->compile(s); } @@ -428,8 +436,12 @@ inline RegularExpression::RegularExpression(const char* s) * compiles s. */ inline RegularExpression::RegularExpression(const std::string& s) + : regstart{} + , reganch{} + , regmust{} + , program{ 0 } + , progsize{} { - this->program = 0; this->compile(s); } diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index ae7a18a..36f24c7 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -3403,11 +3403,7 @@ static void SystemToolsAppendComponents( out_components.emplace_back(std::move(*i)); } } else if (!i->empty() && *i != cur) { -#if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L) - out_components.push_back(std::move(*i)); -#else - out_components.push_back(*i); -#endif + out_components.emplace_back(std::move(*i)); } } } @@ -4743,7 +4739,7 @@ void SystemTools::ClassInitialize() // Test progressively shorter logical-to-physical mappings. std::string cwd_str = cwd; std::string pwd_path; - Realpath(pwd_str.c_str(), pwd_path); + Realpath(pwd_str, pwd_path); while (cwd_str == pwd_path && cwd_str != pwd_str) { // The current pair of paths is a working logical mapping. cwd_changed = cwd_str; @@ -4753,7 +4749,7 @@ void SystemTools::ClassInitialize() // mapping still works. pwd_str = SystemTools::GetFilenamePath(pwd_str); cwd_str = SystemTools::GetFilenamePath(cwd_str); - Realpath(pwd_str.c_str(), pwd_path); + Realpath(pwd_str, pwd_path); } // Add the translation to keep the logical path name. diff --git a/Tests/Assembler/CMakeLists.txt b/Tests/Assembler/CMakeLists.txt index fb17ebb..21b265c 100644 --- a/Tests/Assembler/CMakeLists.txt +++ b/Tests/Assembler/CMakeLists.txt @@ -7,9 +7,10 @@ set(SRCS) # (at least) the following toolchains can process assembler files directly # and also generate assembler files from C: -if("${CMAKE_GENERATOR}" MATCHES "Makefile|Xcode" AND +if("${CMAKE_GENERATOR}" MATCHES "Makefile|Xcode|Ninja" AND NOT CMAKE_OSX_ARCHITECTURES) - if((CMAKE_C_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang|HP|SunPro|XL)$") OR (CMAKE_C_COMPILER_ID STREQUAL "Intel" AND UNIX)) + if((CMAKE_C_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang|HP|SunPro|XL)$") OR (CMAKE_C_COMPILER_ID STREQUAL "Intel" AND UNIX) + AND NOT (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")) set(C_FLAGS "${CMAKE_C_FLAGS}") separate_arguments(C_FLAGS) if(CMAKE_OSX_SYSROOT AND CMAKE_C_SYSROOT_FLAG AND NOT ";${C_FLAGS};" MATCHES ";${CMAKE_C_SYSROOT_FLAG};") diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt index a25f25a..204810e 100644 --- a/Tests/CMakeLib/CMakeLists.txt +++ b/Tests/CMakeLib/CMakeLists.txt @@ -9,7 +9,9 @@ set(CMakeLib_TESTS testGeneratedFileStream.cxx testRST.cxx testRange.cxx + testOptional.cxx testString.cxx + testStringAlgorithms.cxx testSystemTools.cxx testUTF8.cxx testXMLParser.cxx diff --git a/Tests/CMakeLib/testOptional.cxx b/Tests/CMakeLib/testOptional.cxx new file mode 100644 index 0000000..a5e30fb --- /dev/null +++ b/Tests/CMakeLib/testOptional.cxx @@ -0,0 +1,690 @@ +#include "cm_optional.hxx" +#include "cm_utility.hxx" + +#include <iostream> +#include <type_traits> +#include <utility> +#include <vector> + +class EventLogger; + +class Event +{ +public: + enum EventType + { + DEFAULT_CONSTRUCT, + COPY_CONSTRUCT, + MOVE_CONSTRUCT, + VALUE_CONSTRUCT, + + DESTRUCT, + + COPY_ASSIGN, + MOVE_ASSIGN, + VALUE_ASSIGN, + + REFERENCE, + CONST_REFERENCE, + RVALUE_REFERENCE, + CONST_RVALUE_REFERENCE, + + SWAP, + }; + + EventType Type; + const EventLogger* Logger1; + const EventLogger* Logger2; + int Value; + + bool operator==(const Event& other) const; + bool operator!=(const Event& other) const; +}; + +bool Event::operator==(const Event& other) const +{ + return this->Type == other.Type && this->Logger1 == other.Logger1 && + this->Logger2 == other.Logger2 && this->Value == other.Value; +} + +bool Event::operator!=(const Event& other) const +{ + return !(*this == other); +} + +static std::vector<Event> events; + +class EventLogger +{ +public: + EventLogger(); + EventLogger(const EventLogger& other); + EventLogger(EventLogger&& other); + EventLogger(int value); + + ~EventLogger(); + + EventLogger& operator=(const EventLogger& other); + EventLogger& operator=(EventLogger&& other); + EventLogger& operator=(int value); + + void Reference() &; + void Reference() const&; + void Reference() &&; + void Reference() const&&; + + int Value = 0; +}; + +// Certain builds of GCC generate false -Wmaybe-uninitialized warnings when +// doing a release build with the system version of std::optional. These +// warnings do not manifest when using our own cm::optional implementation. +// Silence these false warnings. +#if defined(__GNUC__) && !defined(__clang__) +# define BEGIN_IGNORE_UNINITIALIZED \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define END_IGNORE_UNINITIALIZED _Pragma("GCC diagnostic pop") +#else +# define BEGIN_IGNORE_UNINITIALIZED +# define END_IGNORE_UNINITIALIZED +#endif + +void swap(EventLogger& e1, EventLogger& e2) +{ + BEGIN_IGNORE_UNINITIALIZED + events.push_back({ Event::SWAP, &e1, &e2, e2.Value }); + END_IGNORE_UNINITIALIZED + auto tmp = e1.Value; + e1.Value = e2.Value; + e2.Value = tmp; +} + +EventLogger::EventLogger() + : Value(0) +{ + events.push_back({ Event::DEFAULT_CONSTRUCT, this, nullptr, 0 }); +} + +EventLogger::EventLogger(const EventLogger& other) + : Value(other.Value) +{ + events.push_back({ Event::COPY_CONSTRUCT, this, &other, other.Value }); +} + +BEGIN_IGNORE_UNINITIALIZED +EventLogger::EventLogger(EventLogger&& other) + : Value(other.Value) +{ + events.push_back({ Event::MOVE_CONSTRUCT, this, &other, other.Value }); +} +END_IGNORE_UNINITIALIZED + +EventLogger::EventLogger(int value) + : Value(value) +{ + events.push_back({ Event::VALUE_CONSTRUCT, this, nullptr, value }); +} + +EventLogger::~EventLogger() +{ + BEGIN_IGNORE_UNINITIALIZED + events.push_back({ Event::DESTRUCT, this, nullptr, this->Value }); + END_IGNORE_UNINITIALIZED +} + +EventLogger& EventLogger::operator=(const EventLogger& other) +{ + events.push_back({ Event::COPY_ASSIGN, this, &other, other.Value }); + this->Value = other.Value; + return *this; +} + +EventLogger& EventLogger::operator=(EventLogger&& other) +{ + events.push_back({ Event::MOVE_ASSIGN, this, &other, other.Value }); + this->Value = other.Value; + return *this; +} + +EventLogger& EventLogger::operator=(int value) +{ + events.push_back({ Event::VALUE_ASSIGN, this, nullptr, value }); + this->Value = value; + return *this; +} + +void EventLogger::Reference() & +{ + events.push_back({ Event::REFERENCE, this, nullptr, this->Value }); +} + +void EventLogger::Reference() const& +{ + events.push_back({ Event::CONST_REFERENCE, this, nullptr, this->Value }); +} + +void EventLogger::Reference() && +{ + events.push_back({ Event::RVALUE_REFERENCE, this, nullptr, this->Value }); +} + +void EventLogger::Reference() const&& +{ + events.push_back( + { Event::CONST_RVALUE_REFERENCE, this, nullptr, this->Value }); +} + +static bool testDefaultConstruct(std::vector<Event>& expected) +{ + const cm::optional<EventLogger> o{}; + + expected = {}; + return true; +} + +static bool testNulloptConstruct(std::vector<Event>& expected) +{ + const cm::optional<EventLogger> o{ cm::nullopt }; + + expected = {}; + return true; +} + +static bool testValueConstruct(std::vector<Event>& expected) +{ + const cm::optional<EventLogger> o{ 4 }; + + expected = { + { Event::VALUE_CONSTRUCT, &*o, nullptr, 4 }, + { Event::DESTRUCT, &*o, nullptr, 4 }, + }; + return true; +} + +static bool testInPlaceConstruct(std::vector<Event>& expected) +{ + const cm::optional<EventLogger> o1{ cm::in_place, 4 }; + const cm::optional<EventLogger> o2{ cm::in_place_t{}, 4 }; + + expected = { + { Event::VALUE_CONSTRUCT, &*o1, nullptr, 4 }, + { Event::VALUE_CONSTRUCT, &*o2, nullptr, 4 }, + { Event::DESTRUCT, &*o2, nullptr, 4 }, + { Event::DESTRUCT, &*o1, nullptr, 4 }, + }; + return true; +} + +static bool testCopyConstruct(std::vector<Event>& expected) +{ + const cm::optional<EventLogger> o1{ 4 }; + const cm::optional<EventLogger> o2{ o1 }; + const cm::optional<EventLogger> o3{}; + const cm::optional<EventLogger> o4{ o3 }; + + expected = { + { Event::VALUE_CONSTRUCT, &*o1, nullptr, 4 }, + { Event::COPY_CONSTRUCT, &*o2, &o1.value(), 4 }, + { Event::DESTRUCT, &*o2, nullptr, 4 }, + { Event::DESTRUCT, &*o1, nullptr, 4 }, + }; + return true; +} + +static bool testMoveConstruct(std::vector<Event>& expected) +{ + cm::optional<EventLogger> o1{ 4 }; + const cm::optional<EventLogger> o2{ std::move(o1) }; + cm::optional<EventLogger> o3{}; + const cm::optional<EventLogger> o4{ std::move(o3) }; + + expected = { + { Event::VALUE_CONSTRUCT, &*o1, nullptr, 4 }, + { Event::MOVE_CONSTRUCT, &*o2, &o1.value(), 4 }, + { Event::DESTRUCT, &*o2, nullptr, 4 }, + { Event::DESTRUCT, &*o1, nullptr, 4 }, + }; + return true; +} + +static bool testNulloptAssign(std::vector<Event>& expected) +{ + cm::optional<EventLogger> o1{ 4 }; + o1 = cm::nullopt; + cm::optional<EventLogger> o2{}; + o2 = cm::nullopt; + + expected = { + { Event::VALUE_CONSTRUCT, &*o1, nullptr, 4 }, + { Event::DESTRUCT, &*o1, nullptr, 4 }, + }; + return true; +} + +static bool testCopyAssign(std::vector<Event>& expected) +{ + cm::optional<EventLogger> o1{}; + const cm::optional<EventLogger> o2{ 4 }; + o1 = o2; + const cm::optional<EventLogger> o3{ 5 }; + o1 = o3; + const cm::optional<EventLogger> o4{}; + o1 = o4; + o1 = o4; // Intentionally duplicated to test assigning an empty optional to + // an empty optional + + expected = { + { Event::VALUE_CONSTRUCT, &*o2, nullptr, 4 }, + { Event::COPY_CONSTRUCT, &*o1, &*o2, 4 }, + { Event::VALUE_CONSTRUCT, &*o3, nullptr, 5 }, + { Event::COPY_ASSIGN, &*o1, &*o3, 5 }, + { Event::DESTRUCT, &*o1, nullptr, 5 }, + { Event::DESTRUCT, &o3.value(), nullptr, 5 }, + { Event::DESTRUCT, &o2.value(), nullptr, 4 }, + }; + return true; +} + +static bool testMoveAssign(std::vector<Event>& expected) +{ + cm::optional<EventLogger> o1{}; + cm::optional<EventLogger> o2{ 4 }; + o1 = std::move(o2); + cm::optional<EventLogger> o3{ 5 }; + o1 = std::move(o3); + cm::optional<EventLogger> o4{}; + o1 = std::move(o4); + + expected = { + { Event::VALUE_CONSTRUCT, &*o2, nullptr, 4 }, + { Event::MOVE_CONSTRUCT, &*o1, &*o2, 4 }, + { Event::VALUE_CONSTRUCT, &*o3, nullptr, 5 }, + { Event::MOVE_ASSIGN, &*o1, &*o3, 5 }, + { Event::DESTRUCT, &*o1, nullptr, 5 }, + { Event::DESTRUCT, &*o3, nullptr, 5 }, + { Event::DESTRUCT, &*o2, nullptr, 4 }, + }; + return true; +} + +static bool testPointer(std::vector<Event>& expected) +{ + cm::optional<EventLogger> o1{ 4 }; + const cm::optional<EventLogger> o2{ 5 }; + + o1->Reference(); + o2->Reference(); + + expected = { + { Event::VALUE_CONSTRUCT, &*o1, nullptr, 4 }, + { Event::VALUE_CONSTRUCT, &*o2, nullptr, 5 }, + { Event::REFERENCE, &*o1, nullptr, 4 }, + { Event::CONST_REFERENCE, &*o2, nullptr, 5 }, + { Event::DESTRUCT, &*o2, nullptr, 5 }, + { Event::DESTRUCT, &*o1, nullptr, 4 }, + }; + return true; +} + +#if !__GNUC__ || __GNUC__ > 4 +# define ALLOW_CONST_RVALUE +#endif + +static bool testDereference(std::vector<Event>& expected) +{ + cm::optional<EventLogger> o1{ 4 }; + const cm::optional<EventLogger> o2{ 5 }; + + (*o1).Reference(); + (*o2).Reference(); + (*std::move(o1)).Reference(); +#ifdef ALLOW_CONST_RVALUE + (*std::move(o2)).Reference(); // Broken in GCC 4.9.0. Sigh... +#endif + + expected = { + { Event::VALUE_CONSTRUCT, &*o1, nullptr, 4 }, + { Event::VALUE_CONSTRUCT, &*o2, nullptr, 5 }, + { Event::REFERENCE, &*o1, nullptr, 4 }, + { Event::CONST_REFERENCE, &*o2, nullptr, 5 }, + { Event::RVALUE_REFERENCE, &*o1, nullptr, 4 }, +#ifdef ALLOW_CONST_RVALUE + { Event::CONST_RVALUE_REFERENCE, &*o2, nullptr, 5 }, +#endif + { Event::DESTRUCT, &*o2, nullptr, 5 }, + { Event::DESTRUCT, &*o1, nullptr, 4 }, + }; + return true; +} + +static bool testHasValue(std::vector<Event>& expected) +{ + bool retval = true; + + const cm::optional<EventLogger> o1{ 4 }; + const cm::optional<EventLogger> o2{}; + + if (!o1.has_value()) { + std::cout << "o1 should have a value" << std::endl; + retval = false; + } + + if (!o1) { + std::cout << "(bool)o1 should be true" << std::endl; + retval = false; + } + + if (o2.has_value()) { + std::cout << "o2 should not have a value" << std::endl; + retval = false; + } + + if (o2) { + std::cout << "(bool)o2 should be false" << std::endl; + retval = false; + } + + expected = { + { Event::VALUE_CONSTRUCT, &*o1, nullptr, 4 }, + { Event::DESTRUCT, &*o1, nullptr, 4 }, + }; + return retval; +} + +static bool testValue(std::vector<Event>& expected) +{ + bool retval = true; + + cm::optional<EventLogger> o1{ 4 }; + const cm::optional<EventLogger> o2{ 5 }; + cm::optional<EventLogger> o3{}; + const cm::optional<EventLogger> o4{}; + + o1.value().Reference(); + o2.value().Reference(); + + bool thrown = false; + try { + (void)o3.value(); + } catch (cm::bad_optional_access&) { + thrown = true; + } + if (!thrown) { + std::cout << "o3.value() did not throw" << std::endl; + retval = false; + } + + thrown = false; + try { + (void)o4.value(); + } catch (cm::bad_optional_access&) { + thrown = true; + } + if (!thrown) { + std::cout << "o4.value() did not throw" << std::endl; + retval = false; + } + + expected = { + { Event::VALUE_CONSTRUCT, &*o1, nullptr, 4 }, + { Event::VALUE_CONSTRUCT, &*o2, nullptr, 5 }, + { Event::REFERENCE, &*o1, nullptr, 4 }, + { Event::CONST_REFERENCE, &*o2, nullptr, 5 }, + { Event::DESTRUCT, &*o2, nullptr, 5 }, + { Event::DESTRUCT, &*o1, nullptr, 4 }, + }; + return retval; +} + +static bool testValueOr() +{ + bool retval = true; + + const cm::optional<EventLogger> o1{ 4 }; + cm::optional<EventLogger> o2{ 5 }; + const cm::optional<EventLogger> o3{}; + cm::optional<EventLogger> o4{}; + + EventLogger e1{ 6 }; + EventLogger e2{ 7 }; + EventLogger e3{ 8 }; + EventLogger e4{ 9 }; + + EventLogger r1 = o1.value_or(e1); + if (r1.Value != 4) { + std::cout << "r1.Value should be 4" << std::endl; + retval = false; + } + EventLogger r2 = std::move(o2).value_or(e2); + if (r2.Value != 5) { + std::cout << "r2.Value should be 5" << std::endl; + retval = false; + } + EventLogger r3 = o3.value_or(e3); + if (r3.Value != 8) { + std::cout << "r3.Value should be 8" << std::endl; + retval = false; + } + EventLogger r4 = std::move(o4).value_or(e4); + if (r4.Value != 9) { + std::cout << "r4.Value should be 9" << std::endl; + retval = false; + } + + return retval; +} + +static bool testSwap(std::vector<Event>& expected) +{ + bool retval = true; + + cm::optional<EventLogger> o1{ 4 }; + cm::optional<EventLogger> o2{}; + + o1.swap(o2); + + if (o1.has_value()) { + std::cout << "o1 should not have value" << std::endl; + retval = false; + } + if (!o2.has_value()) { + std::cout << "o2 should have value" << std::endl; + retval = false; + } + if (o2.value().Value != 4) { + std::cout << "value of o2 should be 4" << std::endl; + retval = false; + } + + o1.swap(o2); + + if (!o1.has_value()) { + std::cout << "o1 should have value" << std::endl; + retval = false; + } + if (o1.value().Value != 4) { + std::cout << "value of o1 should be 4" << std::endl; + retval = false; + } + if (o2.has_value()) { + std::cout << "o2 should not have value" << std::endl; + retval = false; + } + + o2.emplace(5); + o1.swap(o2); + + if (!o1.has_value()) { + std::cout << "o1 should have value" << std::endl; + retval = false; + } + if (o1.value().Value != 5) { + std::cout << "value of o1 should be 5" << std::endl; + retval = false; + } + if (!o2.has_value()) { + std::cout << "o2 should not have value" << std::endl; + retval = false; + } + if (o2.value().Value != 4) { + std::cout << "value of o2 should be 4" << std::endl; + retval = false; + } + + o1.reset(); + o2.reset(); + o1.swap(o2); + + if (o1.has_value()) { + std::cout << "o1 should not have value" << std::endl; + retval = false; + } + if (o2.has_value()) { + std::cout << "o2 should not have value" << std::endl; + retval = false; + } + + expected = { + { Event::VALUE_CONSTRUCT, &*o1, nullptr, 4 }, + { Event::MOVE_CONSTRUCT, &*o2, &*o1, 4 }, + { Event::DESTRUCT, &*o1, nullptr, 4 }, + { Event::MOVE_CONSTRUCT, &*o1, &*o2, 4 }, + { Event::DESTRUCT, &*o2, nullptr, 4 }, + { Event::VALUE_CONSTRUCT, &*o2, nullptr, 5 }, + { Event::SWAP, &*o1, &*o2, 5 }, + { Event::DESTRUCT, &*o1, nullptr, 5 }, + { Event::DESTRUCT, &*o2, nullptr, 4 }, + }; + return retval; +} + +static bool testReset(std::vector<Event>& expected) +{ + bool retval = true; + + cm::optional<EventLogger> o{ 4 }; + + o.reset(); + + if (o.has_value()) { + std::cout << "o should not have value" << std::endl; + retval = false; + } + + o.reset(); + + expected = { + { Event::VALUE_CONSTRUCT, &*o, nullptr, 4 }, + { Event::DESTRUCT, &*o, nullptr, 4 }, + }; + return retval; +} + +static bool testEmplace(std::vector<Event>& expected) +{ + cm::optional<EventLogger> o{ 4 }; + + o.emplace(5); + o.reset(); + o.emplace(); + + expected = { + { Event::VALUE_CONSTRUCT, &*o, nullptr, 4 }, + { Event::DESTRUCT, &*o, nullptr, 4 }, + { Event::VALUE_CONSTRUCT, &*o, nullptr, 5 }, + { Event::DESTRUCT, &*o, nullptr, 5 }, + { Event::DEFAULT_CONSTRUCT, &*o, nullptr, 0 }, + { Event::DESTRUCT, &*o, nullptr, 0 }, + }; + return true; +} + +static bool testMakeOptional(std::vector<Event>& expected) +{ + EventLogger e{ 4 }; + cm::optional<EventLogger> o1 = cm::make_optional<EventLogger>(e); + cm::optional<EventLogger> o2 = cm::make_optional<EventLogger>(5); + + expected = { + { Event::VALUE_CONSTRUCT, &e, nullptr, 4 }, + { Event::COPY_CONSTRUCT, &*o1, &e, 4 }, + { Event::VALUE_CONSTRUCT, &*o2, nullptr, 5 }, + { Event::DESTRUCT, &*o2, nullptr, 5 }, + { Event::DESTRUCT, &*o1, nullptr, 4 }, + { Event::DESTRUCT, &e, nullptr, 4 }, + }; + return true; +} + +static bool testMemoryRange(std::vector<Event>& expected) +{ + bool retval = true; + + cm::optional<EventLogger> o{ 4 }; + + auto* ostart = &o; + auto* oend = ostart + 1; + auto* estart = &o.value(); + auto* eend = estart + 1; + + if (static_cast<void*>(estart) < static_cast<void*>(ostart) || + static_cast<void*>(eend) > static_cast<void*>(oend)) { + std::cout << "value is not within memory range of optional" << std::endl; + retval = false; + } + + expected = { + { Event::VALUE_CONSTRUCT, &*o, nullptr, 4 }, + { Event::DESTRUCT, &*o, nullptr, 4 }, + }; + return retval; +} + +int testOptional(int /*unused*/, char* /*unused*/ []) +{ + int retval = 0; + +#define DO_EVENT_TEST(name) \ + do { \ + events.clear(); \ + std::vector<Event> expected; \ + if (!name(expected)) { \ + std::cout << "in " #name << std::endl; \ + retval = 1; \ + } else if (expected != events) { \ + std::cout << #name " did not produce expected events" << std::endl; \ + retval = 1; \ + } \ + } while (0) + +#define DO_TEST(name) \ + do { \ + if (!name()) { \ + std::cout << "in " #name << std::endl; \ + retval = 1; \ + } \ + } while (0) + + DO_EVENT_TEST(testDefaultConstruct); + DO_EVENT_TEST(testNulloptConstruct); + DO_EVENT_TEST(testValueConstruct); + DO_EVENT_TEST(testInPlaceConstruct); + DO_EVENT_TEST(testCopyConstruct); + DO_EVENT_TEST(testMoveConstruct); + DO_EVENT_TEST(testNulloptAssign); + DO_EVENT_TEST(testCopyAssign); + DO_EVENT_TEST(testMoveAssign); + DO_EVENT_TEST(testPointer); + DO_EVENT_TEST(testDereference); + DO_EVENT_TEST(testHasValue); + DO_EVENT_TEST(testValue); + DO_TEST(testValueOr); + DO_EVENT_TEST(testSwap); + DO_EVENT_TEST(testReset); + DO_EVENT_TEST(testEmplace); + DO_EVENT_TEST(testMakeOptional); + DO_EVENT_TEST(testMemoryRange); + + return retval; +} diff --git a/Tests/CMakeLib/testStringAlgorithms.cxx b/Tests/CMakeLib/testStringAlgorithms.cxx new file mode 100644 index 0000000..a92a910 --- /dev/null +++ b/Tests/CMakeLib/testStringAlgorithms.cxx @@ -0,0 +1,229 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include <cmConfigure.h> // IWYU pragma: keep + +#include "cm_string_view.hxx" +#include <iostream> +#include <sstream> +#include <string> +#include <vector> + +#include "cmStringAlgorithms.h" + +int testStringAlgorithms(int /*unused*/, char* /*unused*/ []) +{ + int failed = 0; + + auto assert_ok = [&failed](bool test, cm::string_view title) { + if (test) { + std::cout << "Passed: " << title << "\n"; + } else { + std::cout << "Failed: " << title << "\n"; + ++failed; + } + }; + + auto assert_string = [&failed](cm::string_view generated, + cm::string_view expected, + cm::string_view title) { + if (generated == expected) { + std::cout << "Passed: " << title << "\n"; + } else { + std::cout << "Failed: " << title << "\n"; + std::cout << "Expected: " << expected << "\n"; + std::cout << "Got: " << generated << "\n"; + ++failed; + } + }; + + // ---------------------------------------------------------------------- + // Test cmTrimWhitespace + { + std::string base = "base"; + std::string spaces = " \f\f\n\n\r\r\t\t\v\v"; + assert_string(cmTrimWhitespace(spaces + base), base, + "cmTrimWhitespace front"); + assert_string(cmTrimWhitespace(base + spaces), base, + "cmTrimWhitespace back"); + assert_string(cmTrimWhitespace(spaces + base + spaces), base, + "cmTrimWhitespace front and back"); + } + + // ---------------------------------------------------------------------- + // Test cmRemoveQuotes + { + auto test = [&assert_string](cm::string_view source, + cm::string_view expected, + cm::string_view title) { + assert_string(cmRemoveQuotes(source), expected, title); + }; + + test("", "", "cmRemoveQuotes empty"); + test("\"", "\"", "cmRemoveQuotes single quote"); + test("\"\"", "", "cmRemoveQuotes double quote"); + test("\"a", "\"a", "cmRemoveQuotes quote char"); + test("\"ab", "\"ab", "cmRemoveQuotes quote char char"); + test("a\"", "a\"", "cmRemoveQuotes char quote"); + test("ab\"", "ab\"", "cmRemoveQuotes char char quote"); + test("a", "a", "cmRemoveQuotes single char"); + test("ab", "ab", "cmRemoveQuotes two chars"); + test("abc", "abc", "cmRemoveQuotes three chars"); + test("\"abc\"", "abc", "cmRemoveQuotes quoted chars"); + test("\"\"abc\"\"", "\"abc\"", "cmRemoveQuotes quoted quoted chars"); + } + + // ---------------------------------------------------------------------- + // Test cmEscapeQuotes + { + assert_string(cmEscapeQuotes("plain"), "plain", "cmEscapeQuotes plain"); + std::string base = "\"base\"\""; + std::string result = "\\\"base\\\"\\\""; + assert_string(cmEscapeQuotes(base), result, "cmEscapeQuotes escaped"); + } + + // ---------------------------------------------------------------------- + // Test cmJoin + { + typedef std::string ST; + typedef std::vector<std::string> VT; + assert_string(cmJoin(ST("abc"), ";"), "a;b;c", "cmJoin std::string"); + assert_string(cmJoin(VT{}, ";"), "", "cmJoin std::vector empty"); + assert_string(cmJoin(VT{ "a" }, ";"), "a", "cmJoin std::vector single"); + assert_string(cmJoin(VT{ "a", "b", "c" }, ";"), "a;b;c", + "cmJoin std::vector multiple"); + assert_string(cmJoin(VT{ "a", "b", "c" }, "<=>"), "a<=>b<=>c", + "cmJoin std::vector long sep"); + } + + // ---------------------------------------------------------------------- + // Test cmTokenize + { + typedef std::vector<std::string> VT; + assert_ok(cmTokenize("", ";") == VT{ "" }, "cmTokenize empty"); + assert_ok(cmTokenize(";", ";") == VT{ "" }, "cmTokenize sep"); + assert_ok(cmTokenize("abc", ";") == VT{ "abc" }, "cmTokenize item"); + assert_ok(cmTokenize("abc;", ";") == VT{ "abc" }, "cmTokenize item sep"); + assert_ok(cmTokenize(";abc", ";") == VT{ "abc" }, "cmTokenize sep item"); + assert_ok(cmTokenize("abc;;efg", ";") == VT{ "abc", "efg" }, + "cmTokenize item sep sep item"); + assert_ok(cmTokenize("a1;a2;a3;a4", ";") == VT{ "a1", "a2", "a3", "a4" }, + "cmTokenize multiple items"); + } + + // ---------------------------------------------------------------------- + // Test cmStrCat + { + int ni = -1100; + unsigned int nui = 1100u; + long int nli = -12000l; + unsigned long int nuli = 12000ul; + long long int nlli = -130000ll; + unsigned long long int nulli = 130000ull; + std::string val = + cmStrCat("<test>", ni, ',', nui, ',', nli, ",", nuli, ", ", nlli, + std::string(", "), nulli, cm::string_view("</test>")); + std::string expect = + "<test>-1100,1100,-12000,12000, -130000, 130000</test>"; + assert_string(val, expect, "cmStrCat strings and integers"); + } + { + float const val = 1.5f; + float const div = 0.00001f; + float f = 0.0f; + std::istringstream(cmStrCat("", val)) >> f; + f -= val; + assert_ok((f < div) && (f > -div), "cmStrCat float"); + } + { + double const val = 1.5; + double const div = 0.00001; + double d = 0.0; + std::istringstream(cmStrCat("", val)) >> d; + d -= val; + assert_ok((d < div) && (d > -div), "cmStrCat double"); + } + + // ---------------------------------------------------------------------- + // Test cmWrap + { + typedef std::vector<std::string> VT; + assert_string(cmWrap("<", VT{}, ">", "; "), // + "", // + "cmWrap empty, string prefix and suffix"); + assert_string(cmWrap("<", VT{ "abc" }, ">", "; "), // + "<abc>", // + "cmWrap single, string prefix and suffix"); + assert_string(cmWrap("<", VT{ "a1", "a2", "a3" }, ">", "; "), // + "<a1>; <a2>; <a3>", // + "cmWrap multiple, string prefix and suffix"); + + assert_string(cmWrap('<', VT{}, '>', "; "), // + "", // + "cmWrap empty, char prefix and suffix"); + assert_string(cmWrap('<', VT{ "abc" }, '>', "; "), // + "<abc>", // + "cmWrap single, char prefix and suffix"); + assert_string(cmWrap('<', VT{ "a1", "a2", "a3" }, '>', "; "), // + "<a1>; <a2>; <a3>", // + "cmWrap multiple, char prefix and suffix"); + } + + // ---------------------------------------------------------------------- + // Test cmHas(Literal)Prefix and cmHas(Literal)Suffix + { + std::string str("abc"); + assert_ok(cmHasPrefix(str, 'a'), "cmHasPrefix char"); + assert_ok(!cmHasPrefix(str, 'c'), "cmHasPrefix char not"); + assert_ok(cmHasPrefix(str, "ab"), "cmHasPrefix string"); + assert_ok(!cmHasPrefix(str, "bc"), "cmHasPrefix string not"); + assert_ok(cmHasPrefix(str, str), "cmHasPrefix complete string"); + assert_ok(cmHasLiteralPrefix(str, "ab"), "cmHasLiteralPrefix string"); + assert_ok(!cmHasLiteralPrefix(str, "bc"), "cmHasLiteralPrefix string not"); + + assert_ok(cmHasSuffix(str, 'c'), "cmHasSuffix char"); + assert_ok(!cmHasSuffix(str, 'a'), "cmHasSuffix char not"); + assert_ok(cmHasSuffix(str, "bc"), "cmHasSuffix string"); + assert_ok(!cmHasSuffix(str, "ab"), "cmHasSuffix string not"); + assert_ok(cmHasSuffix(str, str), "cmHasSuffix complete string"); + assert_ok(cmHasLiteralSuffix(str, "bc"), "cmHasLiteralSuffix string"); + assert_ok(!cmHasLiteralSuffix(str, "ab"), "cmHasLiteralPrefix string not"); + } + + // ---------------------------------------------------------------------- + // Test cmStrToLong + { + long value; + assert_ok(cmStrToLong("1", &value) && value == 1, + "cmStrToLong parses a positive decimal integer."); + assert_ok(cmStrToLong(" 1", &value) && value == 1, + "cmStrToLong parses a decimal integer after whitespace."); + + assert_ok(cmStrToLong("-1", &value) && value == -1, + "cmStrToLong parses a negative decimal integer."); + assert_ok( + cmStrToLong(" -1", &value) && value == -1, + "cmStrToLong parses a negative decimal integer after whitespace."); + + assert_ok(!cmStrToLong("1x", &value), + "cmStrToLong rejects trailing content."); + } + + // ---------------------------------------------------------------------- + // Test cmStrToULong + { + unsigned long value; + assert_ok(cmStrToULong("1", &value) && value == 1, + "cmStrToULong parses a decimal integer."); + assert_ok(cmStrToULong(" 1", &value) && value == 1, + "cmStrToULong parses a decimal integer after whitespace."); + assert_ok(!cmStrToULong("-1", &value), + "cmStrToULong rejects a negative number."); + assert_ok(!cmStrToULong(" -1", &value), + "cmStrToULong rejects a negative number after whitespace."); + assert_ok(!cmStrToULong("1x", &value), + "cmStrToULong rejects trailing content."); + } + + return failed; +} diff --git a/Tests/CMakeLib/testSystemTools.cxx b/Tests/CMakeLib/testSystemTools.cxx index 121e639..0a757df 100644 --- a/Tests/CMakeLib/testSystemTools.cxx +++ b/Tests/CMakeLib/testSystemTools.cxx @@ -94,21 +94,5 @@ int testSystemTools(int /*unused*/, char* /*unused*/ []) cmPassed("cmSystemTools::strverscmp working"); } - // ---------------------------------------------------------------------- - // Test cmSystemTools::StringToULong - { - unsigned long value; - cmAssert(cmSystemTools::StringToULong("1", &value) && value == 1, - "StringToULong parses a decimal integer."); - cmAssert(cmSystemTools::StringToULong(" 1", &value) && value == 1, - "StringToULong parses a decimal integer after whitespace."); - cmAssert(!cmSystemTools::StringToULong("-1", &value), - "StringToULong rejects a negative number."); - cmAssert(!cmSystemTools::StringToULong(" -1", &value), - "StringToULong rejects a negative number after whitespace."); - cmAssert(!cmSystemTools::StringToULong("1x", &value), - "StringToULong rejects trailing content."); - } - return failed; } diff --git a/Tests/CMakeLib/testUVProcessChain.cxx b/Tests/CMakeLib/testUVProcessChain.cxx index 72ae602..63c9943 100644 --- a/Tests/CMakeLib/testUVProcessChain.cxx +++ b/Tests/CMakeLib/testUVProcessChain.cxx @@ -1,6 +1,5 @@ #include "cmUVProcessChain.h" -#include "cmAlgorithms.h" #include "cmGetPipes.h" #include "cmUVHandlePtr.h" #include "cmUVStreambuf.h" @@ -16,6 +15,8 @@ #include <csignal> +#include "cm_memory.hxx" + struct ExpectedStatus { bool Finished; diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index e73b277..34858b8 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -14,8 +14,8 @@ macro(ADD_TEST_MACRO NAME) ${build_generator_args} --build-project ${proj} ${${NAME}_CTEST_OPTIONS} - --build-options ${build_options} - ${${NAME}_BUILD_OPTIONS} + --build-options + ${${NAME}_BUILD_OPTIONS} ${_test_command}) unset(_test_command) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/${dir}") @@ -127,9 +127,10 @@ if(BUILD_TESTING) ) endif() - set(build_options) if(CMake_TEST_EXPLICIT_MAKE_PROGRAM) - list(APPEND build_options -DCMAKE_MAKE_PROGRAM:FILEPATH=${CMake_TEST_EXPLICIT_MAKE_PROGRAM}) + list(APPEND build_generator_args + --build-makeprogram ${CMake_TEST_EXPLICIT_MAKE_PROGRAM} + ) endif() # Look for rpmbuild to use for tests. @@ -528,7 +529,6 @@ if(BUILD_TESTING) "${CMake_BINARY_DIR}/Tests/BundleUtilities" ${build_generator_args} --build-project BundleUtilities - --build-options ${build_options} ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/BundleUtilities") @@ -541,9 +541,9 @@ if(BUILD_TESTING) "${CMake_BINARY_DIR}/Tests/Qt4Deploy" ${build_generator_args} --build-project Qt4Deploy - --build-options ${build_options} - -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} - -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} + --build-options + -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} + -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4Deploy") endif() @@ -590,7 +590,7 @@ if(BUILD_TESTING) --build-project ExternalDataTest --build-noclean --force-new-ctest-process - --build-options ${build_options} + --build-options -DMAKE_SUPPORTS_SPACES=${MAKE_SUPPORTS_SPACES} --test-command ${CMAKE_CTEST_COMMAND} -C \${CTEST_CONFIGURATION_TYPE} -V ) @@ -633,7 +633,6 @@ if(BUILD_TESTING) "${CMake_BINARY_DIR}/Tests/Visibility" ${build_generator_args} --build-project Visibility - --build-options ${build_options} ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Visibility" @@ -648,7 +647,7 @@ if(BUILD_TESTING) ${build_generator_args} --build-project LinkFlags --build-target LinkFlags - --build-options ${build_options} + --build-options -DTEST_CONFIG=\${CTEST_CONFIGURATION_TYPE} ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/LinkFlags") @@ -709,7 +708,6 @@ if(BUILD_TESTING) --build-generator-platform "${CMAKE_GENERATOR_PLATFORM}" --build-generator-toolset "${CMAKE_GENERATOR_TOOLSET}" --build-project Simple - --build-options ${build_options} --test-command Simple) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/${extraGeneratorTestName}") endif () @@ -729,7 +727,6 @@ if(BUILD_TESTING) --build-project SubProject ${build_generator_args} --build-target car - --build-options ${build_options} --test-command car ) @@ -755,7 +752,6 @@ if(BUILD_TESTING) --build-project foo --build-target foo --build-exe-dir "${CMake_BINARY_DIR}/Tests/SubProject/foo" - --build-options ${build_options} --test-command foo ) set_tests_properties ( SubProject-Stage2 PROPERTIES DEPENDS SubProject) @@ -797,7 +793,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-two-config ${build_generator_args} --build-project Framework - --build-options ${build_options} + --build-options "-DCMAKE_INSTALL_PREFIX:PATH=${CMake_BINARY_DIR}/Tests/Framework/Install" --test-command bar) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Framework") @@ -809,7 +805,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-two-config ${build_generator_args} --build-project TargetName - --build-options ${build_options} --test-command ${CMAKE_CMAKE_COMMAND} -E compare_files ${CMake_SOURCE_DIR}/Tests/TargetName/scripts/hello_world ${CMake_BINARY_DIR}/Tests/TargetName/scripts/hello_world) @@ -823,7 +818,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project LibName --build-exe-dir "${CMake_BINARY_DIR}/Tests/LibName/lib" - --build-options ${build_options} --test-command foobar ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/LibName") @@ -836,7 +830,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project CustComDepend --build-exe-dir "${CMake_BINARY_DIR}/Tests/CustComDepend/bin" - --build-options ${build_options} --test-command foo bar.c ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CustComDepend") @@ -848,7 +841,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project ArgumentExpansion --build-exe-dir "${CMake_BINARY_DIR}/Tests/ArgumentExpansion/bin" - --build-options ${build_options} ) set_tests_properties(ArgumentExpansion PROPERTIES FAIL_REGULAR_EXPRESSION "Unexpected: ") @@ -861,7 +853,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/GeneratorExpression" ${build_generator_args} --build-project GeneratorExpression - --build-options ${build_options} + --build-options -DCMAKE_BUILD_TYPE=\${CTEST_CONFIGURATION_TYPE} --test-command ${CMAKE_CTEST_COMMAND} -C \${CTEST_CONFIGURATION_TYPE} -V ) @@ -875,7 +867,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project CustomCommand --build-exe-dir "${CMake_BINARY_DIR}/Tests/CustomCommand/bin" - --build-options ${build_options} + --build-options --test-command CustomCommand ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CustomCommand") @@ -893,7 +885,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-two-config ${build_generator_args} --build-project TestWorkingDir - --build-options ${build_options} --test-command working ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CustomCommandWorkingDirectory") @@ -905,7 +896,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project OutOfSource --build-two-config - --build-options ${build_options} --test-command "${CMake_BINARY_DIR}/Tests/OutOfSource/SubDir/OutOfSourceSubdir/simple") list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/OutOfSource") @@ -918,7 +908,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/BuildDepends" ${build_generator_args} --build-project BuildDepends - --build-options ${build_options} ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/BuildDepends") @@ -931,7 +920,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project TestMissingInstall --build-two-config - --build-options ${build_options} + --build-options "-DCMAKE_INSTALL_PREFIX:PATH=${MissingInstallInstallDir}") list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/MissingInstall") @@ -977,7 +966,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/CPackWiXGenerator" ${build_generator_args} --build-project CPackWiXGenerator - --build-options ${build_options} + --build-options --test-command ${CMAKE_CMAKE_COMMAND} "-DCPackWiXGenerator_BINARY_DIR:PATH=${CMake_BINARY_DIR}/Tests/CPackWiXGenerator" "-Dconfig=\${CTEST_CONFIGURATION_TYPE}" @@ -997,7 +986,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project CPackUseDefaultVersion --build-two-config - --build-options ${build_options} + --build-options ${CPackUseDefaultVersion_BUILD_OPTIONS}) set_tests_properties(CPackUseDefaultVersion PROPERTIES PASS_REGULAR_EXPRESSION "CPACK_PACKAGE_VERSION=0\\.1\\.1") list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CPackUseDefaultVersion") @@ -1009,7 +998,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project CPackUseProjectVersion --build-two-config - --build-options ${build_options} + --build-options ${CPackUseProjectVersion_BUILD_OPTIONS}) set_tests_properties(CPackUseProjectVersion PROPERTIES PASS_REGULAR_EXPRESSION "CPACK_PACKAGE_VERSION=1\\.2\\.3") list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CPackUseProjectVersion") @@ -1021,7 +1010,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project CPackUseShortProjectVersion --build-two-config - --build-options ${build_options} + --build-options ${CPackUseProjectVersion_BUILD_OPTIONS}) set_tests_properties(CPackUseShortProjectVersion PROPERTIES PASS_REGULAR_EXPRESSION "CPACK_PACKAGE_VERSION=2") list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CPackUseShortProjectVersion") @@ -1049,7 +1038,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-project CPackComponents --build-two-config --build-target package - --build-options ${build_options} + --build-options -DCPACK_BINARY_DEB:BOOL=${CPACK_BINARY_DEB} -DCPACK_BINARY_RPM:BOOL=${CPACK_BINARY_RPM} ${CPackComponents_BUILD_OPTIONS} @@ -1109,7 +1098,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/CPackComponentsForAll/build${CPackGen}-${CPackComponentWay}" ${build_generator_args} --build-project CPackComponentsForAll - --build-options ${build_options} + --build-options -DCPACK_GENERATOR:STRING=${CPACK_GENERATOR_STRING_${CPackGen}} -DCPACK_BINARY_${CPackGen}:BOOL=ON ${CPackRun_CPackComponentWay} @@ -1148,7 +1137,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/${DEB_TEST_NAMES}/build${CPackGen}-${CPackDEBConfiguration}" ${build_generator_args} --build-project CPackComponentsDEB - --build-options ${build_options} + --build-options -DCPACK_GENERATOR:STRING=${CPackGen} -DCPACK_BINARY_${CPackGen}:BOOL=ON ${CPackRun_CPackDEBConfiguration} @@ -1188,7 +1177,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/CPackTestAllGenerators" ${build_generator_args} --build-project CPackTestAllGenerators - --build-options ${build_options} --test-command ${CMAKE_CMAKE_COMMAND} -D dir=${CMake_BINARY_DIR}/Tests/CPackTestAllGenerators @@ -1219,7 +1207,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-project CPackComponentsPrefix --build-two-config --build-target package - --build-options ${build_options} + --build-options -DCPACK_BINARY_DEB:BOOL=${CPACK_BINARY_DEB} -DCPACK_BINARY_RPM:BOOL=${CPACK_BINARY_RPM} -DCPACK_BINARY_ZIP:BOOL=ON @@ -1242,7 +1230,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-project UseX11 --build-two-config ${X11_build_target_arg} - --build-options ${build_options} --test-command UseX11) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/X11") @@ -1285,7 +1272,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/LoadCommandOneConfig" ${build_generator_args} --build-project LoadCommand - --build-options ${build_options} --test-command LoadedCommand ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/LoadCommandOneConfig") @@ -1300,7 +1286,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project Complex --build-exe-dir "${CMake_BINARY_DIR}/Tests/Complex/bin" - --build-options ${build_options} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} --test-command complex ) @@ -1313,7 +1298,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project Complex --build-exe-dir "${CMake_BINARY_DIR}/Tests/ComplexOneConfig/bin" - --build-options ${build_options} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} --test-command complex) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ComplexOneConfig") @@ -1328,7 +1312,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-project EnvironmentProj --build-exe-dir "${CMake_BINARY_DIR}/Tests/Environment" --force-new-ctest-process - --build-options ${build_options} --test-command ${CMAKE_CTEST_COMMAND} -V ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Environment") @@ -1339,7 +1322,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/QtAutomocNoQt" ${build_generator_args} --build-project QtAutomocNoQt - --build-options ${build_options} + --build-options -DCMAKE_BUILD_TYPE=\${CTEST_CONFIGURATION_TYPE} ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/QtAutomocNoQt") @@ -1364,7 +1347,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-project Qt4Targets --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt4Targets" --force-new-ctest-process - --build-options ${build_options} + --build-options -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE} --test-command ${CMAKE_CTEST_COMMAND} -V ) @@ -1379,7 +1362,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-project Qt4And5Automoc --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt4And5AutomocForward" --force-new-ctest-process - --build-options ${build_options} --test-command ${CMAKE_CTEST_COMMAND} -V ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4And5AutomocForward") @@ -1391,191 +1373,74 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-project Qt4And5Automoc --build-exe-dir "${CMake_BINARY_DIR}/Tests/Qt4And5AutomocReverse" --force-new-ctest-process - --build-options ${build_options} -DQT_REVERSE_FIND_ORDER=1 + --build-options -DQT_REVERSE_FIND_ORDER=1 --test-command ${CMAKE_CTEST_COMMAND} -V ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4And5AutomocReverse") endif() endif() - if(CMake_TEST_FindALSA) - add_subdirectory(FindALSA) - endif() + # test for Find modules, simple cases + foreach(_mod IN ITEMS + ALSA + Boost + BZip2 + CURL + Cups + Doxygen + EnvModules + EXPAT + Fontconfig + Freetype + GDAL + GIF + Git + GLEW + GSL + GTK2 + Iconv + ICU + JPEG + JsonCpp + LibLZMA + LibRHash + Libinput + LibUV + LibXml2 + LTTngUST + ODBC + OpenACC + OpenCL + OpenGL + OpenMP + OpenSSL + MPI + PNG + Patch + PostgreSQL + Protobuf + SQLite3 + TIFF + Vulkan + X11 + XalanC + XercesC + ) + if(CMake_TEST_Find${_mod}) + add_subdirectory(Find${_mod}) + endif() + endforeach() if(CMake_TEST_CUDA) add_subdirectory(Cuda) add_subdirectory(CudaOnly) endif() - if(CMake_TEST_FindBoost) - add_subdirectory(FindBoost) - endif() - - if(CMake_TEST_FindBZip2) - add_subdirectory(FindBZip2) - endif() - - if(CMake_TEST_FindCURL) - add_subdirectory(FindCURL) - endif() - - if(CMake_TEST_FindCups) - add_subdirectory(FindCups) - endif() - - if(CMake_TEST_FindDoxygen) - add_subdirectory(FindDoxygen) - endif() - - if(CMake_TEST_FindEnvModules) - add_subdirectory(FindEnvModules) - endif() - - if(CMake_TEST_FindEXPAT) - add_subdirectory(FindEXPAT) - endif() - - if(CMake_TEST_FindFontconfig) - add_subdirectory(FindFontconfig) - endif() - - if(CMake_TEST_FindFreetype) - add_subdirectory(FindFreetype) - endif() - - if(CMake_TEST_FindGDAL) - add_subdirectory(FindGDAL) - endif() - - if(CMake_TEST_FindGIF) - add_subdirectory(FindGIF) - endif() - - if(CMake_TEST_FindGit) - add_subdirectory(FindGit) - endif() - - if(CMake_TEST_FindGLEW) - add_subdirectory(FindGLEW) - endif() - - if(CMake_TEST_FindGSL) - add_subdirectory(FindGSL) - endif() - if(CMake_TEST_FindGTest) add_subdirectory(FindGTest) add_subdirectory(GoogleTest) endif() - if(CMake_TEST_FindGTK2) - add_subdirectory(FindGTK2) - endif() - - if(CMake_TEST_FindIconv) - add_subdirectory(FindIconv) - endif() - - if(CMake_TEST_FindICU) - add_subdirectory(FindICU) - endif() - - if(CMake_TEST_FindJPEG) - add_subdirectory(FindJPEG) - endif() - - if(CMake_TEST_FindJsonCpp) - add_subdirectory(FindJsonCpp) - endif() - - if(CMake_TEST_FindLibLZMA) - add_subdirectory(FindLibLZMA) - endif() - - if(CMake_TEST_FindLibRHash) - add_subdirectory(FindLibRHash) - endif() - - if(CMake_TEST_FindLibinput) - add_subdirectory(FindLibinput) - endif() - - if(CMake_TEST_FindLibUV) - add_subdirectory(FindLibUV) - endif() - - if(CMake_TEST_FindLibXml2) - add_subdirectory(FindLibXml2) - endif() - - if(CMake_TEST_FindLTTngUST) - add_subdirectory(FindLTTngUST) - endif() - - if(CMake_TEST_FindODBC) - add_subdirectory(FindODBC) - endif() - - if(CMake_TEST_FindOpenCL) - add_subdirectory(FindOpenCL) - endif() - - if(CMake_TEST_FindOpenGL) - add_subdirectory(FindOpenGL) - endif() - - if(CMake_TEST_FindOpenMP) - add_subdirectory(FindOpenMP) - endif() - - if(CMake_TEST_FindOpenSSL) - add_subdirectory(FindOpenSSL) - endif() - - if(CMake_TEST_FindMPI) - add_subdirectory(FindMPI) - endif() - - if(CMake_TEST_FindPNG) - add_subdirectory(FindPNG) - endif() - - if(CMake_TEST_FindPatch) - add_subdirectory(FindPatch) - endif() - - if(CMake_TEST_FindPostgreSQL) - add_subdirectory(FindPostgreSQL) - endif() - - if(CMake_TEST_FindProtobuf) - add_subdirectory(FindProtobuf) - endif() - - if(CMake_TEST_FindSQLite3) - add_subdirectory(FindSQLite3) - endif() - - if(CMake_TEST_FindTIFF) - add_subdirectory(FindTIFF) - endif() - - if(CMake_TEST_FindVulkan) - add_subdirectory(FindVulkan) - endif() - - if(CMake_TEST_FindX11) - add_subdirectory(FindX11) - endif() - - if(CMake_TEST_FindXalanC) - add_subdirectory(FindXalanC) - endif() - - if(CMake_TEST_FindXercesC) - add_subdirectory(FindXercesC) - endif() - if(CMake_TEST_FindPython OR CMake_TEST_FindPython_NumPy) add_subdirectory(FindPython) endif() @@ -1591,16 +1456,16 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH # CMake_TEST_FindMatlab_ROOT_DIR: indicates an optional root directory for Matlab, allows to select a version. # CMake_TEST_FindMatlab_MCR: indicates the MCR is installed # CMake_TEST_FindMatlab_MCR_ROOT_DIR: indicates an optional root directory for the MCR, required on Linux - if(CMake_TEST_FindMatlab OR (NOT "${CMake_TEST_FindMatlab_ROOT_DIR}" STREQUAL "") OR - CMake_TEST_FindMatlab_MCR OR (NOT "${CMake_TEST_FindMatlab_MCR_ROOT_DIR}" STREQUAL "")) + if(CMake_TEST_FindMatlab OR CMake_TEST_FindMatlab_ROOT_DIR OR + CMake_TEST_FindMatlab_MCR OR CMake_TEST_FindMatlab_MCR_ROOT_DIR) set(FindMatlab_additional_test_options ) - if(CMake_TEST_FindMatlab_MCR OR NOT "${CMake_TEST_FindMatlab_MCR_ROOT_DIR}" STREQUAL "") + if(CMake_TEST_FindMatlab_MCR OR CMake_TEST_FindMatlab_MCR_ROOT_DIR) set(FindMatlab_additional_test_options -DIS_MCR=TRUE) endif() - if(NOT "${CMake_TEST_FindMatlab_ROOT_DIR}" STREQUAL "") + if(CMake_TEST_FindMatlab_ROOT_DIR) set(FindMatlab_additional_test_options ${FindMatlab_additional_test_options} "-DMatlab_ROOT_DIR=${CMake_TEST_FindMatlab_ROOT_DIR}") endif() - if(NOT "${CMake_TEST_FindMatlab_MCR_ROOT_DIR}" STREQUAL "") + if(CMake_TEST_FindMatlab_MCR_ROOT_DIR) set(FindMatlab_additional_test_options ${FindMatlab_additional_test_options} "-DMCR_ROOT:FILEPATH=${CMake_TEST_FindMatlab_MCR_ROOT_DIR}") endif() set(FindMatlab.basic_checks_BUILD_OPTIONS ${FindMatlab_additional_test_options}) @@ -1623,7 +1488,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-project ExternalProjectTest --build-exe-dir "${CMake_BINARY_DIR}/Tests/ExternalProject" --force-new-ctest-process - --build-options ${build_options} --test-command ${CMAKE_CTEST_COMMAND} -V ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProject") @@ -1639,7 +1503,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project ExternalProjectSubdir --force-new-ctest-process - --build-options ${build_options} ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectSubdir") @@ -1651,7 +1514,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project ExternalProjectSourceSubdir --force-new-ctest-process - --build-options ${build_options} ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectSourceSubdir") @@ -1663,7 +1525,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project ExternalProjectSourceSubdirNotCMake --force-new-ctest-process - --build-options ${build_options} ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectSourceSubdirNotCMake") @@ -1675,7 +1536,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-project ExternalProjectLocalTest --build-exe-dir "${CMake_BINARY_DIR}/Tests/ExternalProjectLocal" --force-new-ctest-process - --build-options ${build_options} --test-command ${CMAKE_CTEST_COMMAND} -V ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectLocal") @@ -1691,7 +1551,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-project ExternalProjectUpdateTest --build-exe-dir "${CMake_BINARY_DIR}/Tests/ExternalProjectUpdate" --force-new-ctest-process - --build-options ${build_options} --test-command ${CMAKE_CTEST_COMMAND} -V ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectUpdate") @@ -1729,17 +1588,17 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH endif() add_test(${tutorial_test_name} ${CMAKE_CTEST_COMMAND} --build-and-test - "${CMake_SOURCE_DIR}/Tests/Tutorial/${step_name}" + "${CMake_SOURCE_DIR}/Help/guide/tutorial/${step_name}" ${tutorial_build_dir}_Build ${build_generator_args} --build-project Tutorial - --build-options ${build_options} ${tutorial_build_options} + --build-options ${tutorial_build_options} --test-command Tutorial 25.0) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/${tutorial_build_dir}_Build") endfunction() if(NOT CMake_TEST_EXTERNAL_CMAKE) - foreach(STP RANGE 1 11) + foreach(STP RANGE 2 11) add_tutorial_test(Step${STP} TRUE) endforeach() add_tutorial_test(Complete TRUE) @@ -1755,7 +1614,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/Testing" ${build_generator_args} --build-project Testing - --build-options ${build_options} --test-command ${CMAKE_CTEST_COMMAND} -C \${CTEST_CONFIGURATION_TYPE} ) set_tests_properties(testing PROPERTIES PASS_REGULAR_EXPRESSION "Passed") @@ -1768,7 +1626,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project Wrapping --build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin" - --build-options ${build_options} --test-command wrapping ) add_test(qtwrapping ${CMAKE_CTEST_COMMAND} @@ -1778,7 +1635,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project Wrapping --build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin" - --build-options ${build_options} --test-command qtwrapping ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Wrapping") @@ -1790,7 +1646,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin" --build-project TestDriverTest - --build-options ${build_options} --test-command TestDriverTest test1 ) @@ -1801,7 +1656,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin" --build-project TestDriverTest - --build-options ${build_options} --test-command TestDriverTest test2 ) @@ -1812,7 +1666,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-exe-dir "${CMake_BINARY_DIR}/Tests/Wrapping/bin" --build-project TestDriverTest - --build-options ${build_options} --test-command TestDriverTest subdir/test3 ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/TestDriver") @@ -1824,7 +1677,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-exe-dir "${CMake_BINARY_DIR}/Tests/Dependency/Exec" ${build_generator_args} --build-project Dependency - --build-options ${build_options} --test-command exec ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Dependency") @@ -1854,8 +1706,8 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-exe-dir "${CMake_BINARY_DIR}/Tests/Jump/WithLibOut/Executable" --build-project Jump ${build_generator_args} - --build-options ${build_options} - -DLIBRARY_OUTPUT_PATH:PATH=${CMake_BINARY_DIR}/Tests/Jump/WithLibOut/Lib + --build-options + -DLIBRARY_OUTPUT_PATH:PATH=${CMake_BINARY_DIR}/Tests/Jump/WithLibOut/Lib --test-command jumpExecutable ) @@ -1867,7 +1719,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-run-dir "${CMake_BINARY_DIR}/Tests/Jump/NoLibOut/Executable" --build-project Jump ${build_generator_args} - --build-options ${build_options} --test-command jumpExecutable ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Jump") @@ -1879,7 +1730,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project Plugin --build-two-config - --build-options ${build_options} --test-command bin/example) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Plugin") @@ -1895,7 +1745,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/MacRuntimePath" ${build_generator_args} --build-project MacRuntimePath - --build-options ${build_options} + --build-options -DCMake_TEST_NESTED_MAKE_PROGRAM:FILEPATH=${CMake_TEST_EXPLICIT_MAKE_PROGRAM} ) endif() @@ -1913,7 +1763,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/LinkLineOrder" ${build_generator_args} --build-project LinkLineOrder - --build-options ${build_options} --test-command Exec1 ) @@ -1923,7 +1772,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/LinkLineOrder" ${build_generator_args} --build-project LinkLineOrder - --build-options ${build_options} --test-command Exec2 ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/LinkLineOrder") @@ -1943,7 +1791,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/LinkStatic" ${build_generator_args} --build-project LinkStatic - --build-options ${build_options} + --build-options -DMATH_LIBRARY:FILEPATH=/usr/lib/libm.a --test-command LinkStatic ) @@ -1958,7 +1806,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/SubDirSpaces/Executable Sources" ${build_generator_args} --build-project SUBDIR - --build-options ${build_options} --test-command test "${CMake_BINARY_DIR}/Tests/SubDirSpaces/ShouldBeHere" "${CMake_BINARY_DIR}/Tests/SubDirSpaces/testfromsubdir.obj" @@ -1974,7 +1821,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-exe-dir "${CMake_BINARY_DIR}/Tests/SubDir/Executable" ${build_generator_args} --build-project SUBDIR - --build-options ${build_options} --test-command test "${CMake_BINARY_DIR}/Tests/SubDir/ShouldBeHere" "${CMake_BINARY_DIR}/Tests/SubDir/testfromsubdir.obj" @@ -1987,7 +1833,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-exe-dir "${CMake_BINARY_DIR}/Tests/SubDir/Executable" ${build_generator_args} --build-project SUBDIR - --build-options ${build_options} --test-command test "${CMake_BINARY_DIR}/Tests/SubDir/ShouldBeHere" "${CMake_BINARY_DIR}/Tests/SubDir/testfromsubdir.o" @@ -1995,9 +1840,11 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH endif () list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/SubDir") - if(MSVC) - ADD_TEST_MACRO(ForceInclude foo) + if(MSVC OR (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_SIMULATE_ID STREQUAL "MSVC")) ADD_TEST_MACRO(PDBDirectoryAndName myexe) + if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang" OR NOT "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU") + ADD_TEST_MACRO(ForceInclude foo) + endif() if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang") ADD_TEST_MACRO(PrecompiledHeader foo) endif() @@ -2023,7 +1870,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project MakeClean --build-exe-dir "${CMake_BINARY_DIR}/MakeClean" - --build-options ${build_options} --test-command check_clean ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/MakeClean") @@ -2132,7 +1978,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-two-config ${build_generator_args} --build-project mfc_driver - --build-options ${build_options} --test-command ${CMAKE_CTEST_COMMAND} -C \${CTEST_CONFIGURATION_TYPE} -VV) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/MFC") @@ -2162,7 +2007,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-two-config ${build_generator_args} --build-project VSExternalInclude - --build-options ${build_options} --test-command VSExternalInclude) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/VSExternalInclude") @@ -2173,7 +2017,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-two-config ${build_generator_args} --build-project VSMidl - --build-options ${build_options} --test-command VSMidl) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/VSMidl") @@ -2287,11 +2130,11 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH macro(add_test_VSWinCE name generator systemName systemVersion generatorPlatform) # TODO: Fix the tutorial to make it work in cross compile # currently the MakeTable is build for target and can not be used on the host - # This happens in part 5 so we build only part 1-4 of the tutorial - foreach(STP RANGE 1 4) + # This happens in part 5 so we build only through part 4 of the tutorial. + foreach(STP RANGE 2 4) add_test(NAME "TutorialStep${STP}.${name}" COMMAND ${CMAKE_CTEST_COMMAND} --build-and-test - "${CMake_SOURCE_DIR}/Tests/Tutorial/Step${STP}" + "${CMake_SOURCE_DIR}/Help/guide/tutorial/Step${STP}" "${CMake_BINARY_DIR}/Tests/Tutorial/Step${STP}_${name}" --build-generator "${generator}" --build-project Tutorial @@ -2460,7 +2303,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-project BundleTest --build-target install # --build-target package - --build-options ${build_options} + --build-options "-DCMAKE_INSTALL_PREFIX:PATH=${BundleTestInstallDir}" "-DCMake_SOURCE_DIR:PATH=${CMake_SOURCE_DIR}" --test-command @@ -2475,7 +2318,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project CFBundleTest --build-config $<CONFIGURATION> - --build-options ${build_options} --test-command ${CMAKE_CMAKE_COMMAND} -DCTEST_CONFIGURATION_TYPE=$<CONFIGURATION> -Ddir=${CMake_BINARY_DIR}/Tests/CFBundleTest @@ -2496,7 +2338,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project BundleGeneratorTest --build-target package - --build-options ${build_options} + --build-options "-DCMAKE_INSTALL_PREFIX:PATH=${CMake_BINARY_DIR}/Tests/BundleGeneratorTest/InstallDirectory" ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/BundleGeneratorTest") @@ -2509,7 +2351,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-noclean --build-project WarnUnusedUnusedViaSet - --build-options ${build_options} + --build-options "--warn-unused-vars") set_tests_properties(WarnUnusedUnusedViaSet PROPERTIES PASS_REGULAR_EXPRESSION "unused variable \\(changing definition\\) 'UNUSED_VARIABLE'") @@ -2524,7 +2366,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-noclean --build-project WarnUnusedUnusedViaUnset - --build-options ${build_options} + --build-options "--warn-unused-vars") set_tests_properties(WarnUnusedUnusedViaUnset PROPERTIES PASS_REGULAR_EXPRESSION "CMake Warning \\(dev\\) at CMakeLists.txt:7 \\(set\\):") @@ -2538,7 +2380,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/WarnUnusedCliUnused" ${build_generator_args} --build-project WarnUnusedCliUnused - --build-options ${build_options} + --build-options "-DUNUSED_CLI_VARIABLE=Unused") set_tests_properties(WarnUnusedCliUnused PROPERTIES PASS_REGULAR_EXPRESSION "CMake Warning:.*Manually-specified variables were not used by the project:.* UNUSED_CLI_VARIABLE") @@ -2551,7 +2393,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-noclean --build-project WarnUnusedCliUsed - --build-options ${build_options} + --build-options "-DUSED_VARIABLE=Usage proven") set_tests_properties(WarnUnusedCliUsed PROPERTIES PASS_REGULAR_EXPRESSION "Usage proven") @@ -2566,7 +2408,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-noclean --build-project WarnUninitialized - --build-options ${build_options} + --build-options "--warn-uninitialized") set_tests_properties(WarnUninitialized PROPERTIES PASS_REGULAR_EXPRESSION "uninitialized variable 'USED_VARIABLE'") @@ -2581,7 +2423,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-project TestsWorkingDirectoryProj --build-exe-dir "${CMake_BINARY_DIR}/Tests/TestsWorkingDirectory" --force-new-ctest-process - --build-options ${build_options} --test-command ${CMAKE_CTEST_COMMAND} -V -C \${CTEST_CONFIGURATION_TYPE} ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/TestsWorkingDirectory") @@ -3379,7 +3220,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project testf --build-two-config - --build-options ${build_options} --test-command testf) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Fortran") @@ -3390,7 +3230,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/FortranModules" ${build_generator_args} --build-project FortranModules - --build-options ${build_options} + --build-options -DCMake_TEST_NESTED_MAKE_PROGRAM:FILEPATH=${CMake_TEST_EXPLICIT_MAKE_PROGRAM} -DCMake_TEST_Fortran_SUBMODULES:BOOL=${CMake_TEST_Fortran_SUBMODULES} ${CMake_TEST_FortranModules_BUILD_OPTIONS} @@ -3413,7 +3253,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH ${build_generator_args} --build-project FortranC --build-two-config - --build-options ${build_options} --test-command CMakeFiles/FortranCInterface/FortranCInterface) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/FortranC") endif() @@ -3442,7 +3281,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-target hello --build-two-config --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJar/" - --build-options ${build_options} --test-command ${JAVA_RUNTIME} -classpath hello.jar HelloWorld) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJar") add_test(Java.JarSourceList ${CMAKE_CTEST_COMMAND} @@ -3454,7 +3292,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-target hello2 --build-two-config --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJarSourceList/" - --build-options ${build_options} --test-command ${JAVA_RUNTIME} -classpath hello2.jar HelloWorld) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJarSourceList") add_test(Java.JarSourceListAndOutput ${CMAKE_CTEST_COMMAND} @@ -3466,7 +3303,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-target hello3 --build-two-config --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJarSourceListAndOutput/hello3" - --build-options ${build_options} --test-command ${JAVA_RUNTIME} -classpath hello3.jar HelloWorld) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJarSourceListAndOutput") @@ -3492,7 +3328,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-project helloJavah --build-two-config --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJavah/" - --build-options ${build_options} --test-command ${JAVA_RUNTIME} -Djava.library.path=${JAVAH_LIBRARY_PATH} -classpath hello3.jar HelloWorld2) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJavah") endif() @@ -3511,7 +3346,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-project helloJavaNativeHeaders --build-two-config --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/" - --build-options ${build_options} --test-command ${JAVA_RUNTIME} -Djava.library.path=${JAVANATIVEHEADERS_LIBRARY_PATH} -classpath hello4.jar HelloWorld3) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders") endif() @@ -3533,9 +3367,9 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/SimpleCOnly_sdcc" ${build_generator_args} --build-project SimpleC - --build-options ${build_options} - "-DCMAKE_SYSTEM_NAME=Generic" - "-DCMAKE_C_COMPILER=${SDCC_EXECUTABLE}") + --build-options + "-DCMAKE_SYSTEM_NAME=Generic" + "-DCMAKE_C_COMPILER=${SDCC_EXECUTABLE}") list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/SimpleCOnly_sdcc") endif() @@ -3551,11 +3385,11 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/Simple_Mingw_Linux2Win" ${build_generator_args} --build-project Simple - --build-options ${build_options} - "-DCMAKE_SYSTEM_NAME=Windows" - "-DCMAKE_C_COMPILER=${MINGW_CC_LINUX2WIN_EXECUTABLE}" - "-DCMAKE_CXX_COMPILER=${MINGW_CXX_LINUX2WIN_EXECUTABLE}" - "-DCMAKE_RC_COMPILER=${MINGW_RC_LINUX2WIN_EXECUTABLE}" + --build-options + "-DCMAKE_SYSTEM_NAME=Windows" + "-DCMAKE_C_COMPILER=${MINGW_CC_LINUX2WIN_EXECUTABLE}" + "-DCMAKE_CXX_COMPILER=${MINGW_CXX_LINUX2WIN_EXECUTABLE}" + "-DCMAKE_RC_COMPILER=${MINGW_RC_LINUX2WIN_EXECUTABLE}" ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Simple_Mingw_Linux2Win") endif() @@ -3641,7 +3475,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-two-config ${build_generator_args} --build-project IncludeDirectories - --build-options ${build_options} --test-command IncludeDirectories) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/IncludeDirectories") @@ -3655,8 +3488,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH "${CMake_BINARY_DIR}/Tests/IncludeDirectoriesCPATH" --build-two-config ${build_generator_args} - --build-project IncludeDirectoriesCPATH - --build-options ${build_options}) + --build-project IncludeDirectoriesCPATH) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/IncludeDirectoriesCPATH") set_tests_properties(IncludeDirectoriesCPATH PROPERTIES @@ -3670,7 +3502,6 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH --build-two-config ${build_generator_args} --build-project InterfaceLinkLibraries - --build-options ${build_options} --test-command InterfaceLinkLibraries) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/InterfaceLinkLibraries") diff --git a/Tests/CMakeOnly/CMakeLists.txt b/Tests/CMakeOnly/CMakeLists.txt index 1aeab8b..19f3f79 100644 --- a/Tests/CMakeOnly/CMakeLists.txt +++ b/Tests/CMakeOnly/CMakeLists.txt @@ -84,5 +84,5 @@ function(add_major_test module) endfunction() add_major_test(PythonLibs VERSIONS 2 3 VERSION_VAR PYTHONLIBS_VERSION_STRING) -add_major_test(PythonInterp NOLANG VERSIONS 2 3 VERSION_VAR PYTHON_VERSION_STRING) +add_major_test(PythonInterp NOLANG VERSIONS 3 VERSION_VAR PYTHON_VERSION_STRING) add_major_test(Qt VERSIONS 3 4 VERSION_VAR QT_VERSION_STRING) diff --git a/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt b/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt index f058c19..2028a13 100644 --- a/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt +++ b/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt @@ -49,6 +49,15 @@ else () message(STATUS "errno found in <cerrno>") endif () +check_cxx_symbol_exists("std::fopen" "cstdio" CSE_RESULT_FOPEN) +if (NOT CSE_RESULT_FOPEN) + if(NOT ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.10)) + message(SEND_ERROR "CheckCXXSymbolExists did not find std::fopen in <cstdio>") + endif() +else() + message(STATUS "std::fopen found in <cstdio>") +endif() + if (CMAKE_COMPILER_IS_GNUCXX) string(APPEND CMAKE_CXX_FLAGS " -O3") unset(CSE_RESULT_O3 CACHE) @@ -60,3 +69,8 @@ if (CMAKE_COMPILER_IS_GNUCXX) message(SEND_ERROR "CheckCXXSymbolExists reported a nonexistent symbol as existing with optimization -O3") endif () endif () + +check_cxx_symbol_exists("std::non_existent_function_for_symbol_test<int*>" "algorithm" CSE_RESULT_NON_SYMBOL) +if (CSE_RESULT_NON_SYMBOL) + message(SEND_ERROR "CheckCXXSymbolExists reported a nonexistent symbol.") +endif() diff --git a/Tests/CMakeServerLib/testServerBuffering.cpp b/Tests/CMakeServerLib/testServerBuffering.cpp index 7330ead..8b0b89b 100644 --- a/Tests/CMakeServerLib/testServerBuffering.cpp +++ b/Tests/CMakeServerLib/testServerBuffering.cpp @@ -1,6 +1,8 @@ #include "cmConnection.h" #include "cmServerConnection.h" + #include <iostream> +#include <memory> #include <string> #include <vector> diff --git a/Tests/CMakeTests/ELFTest.cmake.in b/Tests/CMakeTests/ELFTest.cmake.in index 4635778..85c2360 100644 --- a/Tests/CMakeTests/ELFTest.cmake.in +++ b/Tests/CMakeTests/ELFTest.cmake.in @@ -25,13 +25,38 @@ foreach(f ${files}) # Change the RPATH. file(RPATH_CHANGE FILE "${f}" OLD_RPATH "/sample/rpath" - NEW_RPATH "/rpath/sample") + NEW_RPATH "/path1:/path2") set(rpath) - file(STRINGS "${f}" rpath REGEX "/rpath/sample" LIMIT_COUNT 1) + file(STRINGS "${f}" rpath REGEX "/path1:/path2" LIMIT_COUNT 1) if(NOT rpath) message(FATAL_ERROR "RPATH not changed in ${f}") endif() + # Change the RPATH without compiler defined rpath removed + file(RPATH_CHANGE FILE "${f}" + OLD_RPATH "/path2" + NEW_RPATH "/path3") + set(rpath) + file(STRINGS "${f}" rpath REGEX "/path1:/path3" LIMIT_COUNT 1) + if(NOT rpath) + message(FATAL_ERROR "RPATH not updated in ${f}") + endif() + + # Change the RPATH with compiler defined rpath removed + file(RPATH_CHANGE FILE "${f}" + OLD_RPATH "/path3" + NEW_RPATH "/rpath/sample" + INSTALL_REMOVE_ENVIRONMENT_RPATH) + set(rpath) + file(STRINGS "${f}" rpath REGEX "/rpath/sample" LIMIT_COUNT 1) + if(NOT rpath) + message(FATAL_ERROR "RPATH not updated in ${f}") + endif() + file(STRINGS "${f}" rpath REGEX "/path1" LIMIT_COUNT 1) + if(rpath) + message(FATAL_ERROR "RPATH not removed in ${f}") + endif() + # Remove the RPATH. file(RPATH_REMOVE FILE "${f}") set(rpath) diff --git a/Tests/CPackComponentsDEB/CMakeLists.txt b/Tests/CPackComponentsDEB/CMakeLists.txt index 9d4b5e9..bc5b6a9 100644 --- a/Tests/CPackComponentsDEB/CMakeLists.txt +++ b/Tests/CPackComponentsDEB/CMakeLists.txt @@ -4,8 +4,8 @@ # application (mylibapp). We create a binary installer (a CPack Generator) # which supports CPack components. -cmake_minimum_required(VERSION 2.8.3.20101130 FATAL_ERROR) -project(CPackComponentsDEB) +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) +project(CPackComponentsDEB VERSION 1.0.3) # Use GNUInstallDirs in order to enforce lib64 if needed include(GNUInstallDirs) @@ -44,10 +44,6 @@ set(CPACK_PACKAGE_NAME "MyLib") set(CPACK_PACKAGE_CONTACT "None") set(CPACK_PACKAGE_VENDOR "CMake.org") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MyLib - CPack Component Installation Example") -set(CPACK_PACKAGE_VERSION "1.0.2") -set(CPACK_PACKAGE_VERSION_MAJOR "1") -set(CPACK_PACKAGE_VERSION_MINOR "0") -set(CPACK_PACKAGE_VERSION_PATCH "2") set(CPACK_PACKAGE_INSTALL_DIRECTORY "CPack Component Example") set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/license.txt) diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend1.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend1.cmake index 73fd0ab..beccc46 100644 --- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend1.cmake +++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend1.cmake @@ -6,7 +6,7 @@ include(${CPackComponentsDEB_SOURCE_DIR}/RunCPackVerifyResult.cmake) # expected results -set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.2_*.deb") +set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.3_*.deb") set(expected_count 3) @@ -36,7 +36,6 @@ endif() # dpkg-deb checks for the dependencies of the packages find_program(DPKGDEB_EXECUTABLE dpkg-deb) if(DPKGDEB_EXECUTABLE) - set(dpkgdeb_output_errors_all "") foreach(_f IN LISTS actual_output) # extracts the metadata from the package @@ -54,32 +53,23 @@ if(DPKGDEB_EXECUTABLE) message(STATUS "package='${dpkg_package_name}', dependencies='${dpkg_depends}'") - if("${dpkg_package_name}" STREQUAL "mylib-applications") - if(NOT "${dpkg_depends}" STREQUAL "depend-application") - set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all} - "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'depend-application'\n") + if(dpkg_package_name STREQUAL "mylib-applications") + if(NOT dpkg_depends STREQUAL "depend-application") + message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'depend-application'\n") endif() - elseif("${dpkg_package_name}" STREQUAL "mylib-headers") - if(NOT "${dpkg_depends}" STREQUAL "mylib-libraries (= 1.0.2), depend-headers") - set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all} - "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'mylib-libraries (= 1.0.2), depend-headers'\n") + elseif(dpkg_package_name STREQUAL "mylib-headers") + if(NOT dpkg_depends STREQUAL "mylib-libraries (= 1.0.3), depend-headers") + message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'mylib-libraries (= 1.0.3), depend-headers'\n") endif() - elseif("${dpkg_package_name}" STREQUAL "mylib-libraries") - if(NOT "${dpkg_depends}" STREQUAL "depend-default") - set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all} - "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'depend-default'\n") + elseif(dpkg_package_name STREQUAL "mylib-libraries") + if(NOT dpkg_depends STREQUAL "depend-default") + message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'depend-default'\n") endif() else() - set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all} - "dpkg-deb: ${_f}: component name not found: ${dpkg_package_name}\n") + message(SEND_ERROR "dpkg-deb: ${_f}: component name not found: ${dpkg_package_name}\n") endif() endforeach() - - - if(NOT "${dpkgdeb_output_errors_all}" STREQUAL "") - message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}") - endif() else() message("dpkg-deb executable not found - skipping dpkg-deb test") endif() diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend2.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend2.cmake index 81dbbc5..88f3248 100644 --- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend2.cmake +++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-depend2.cmake @@ -6,7 +6,7 @@ include(${CPackComponentsDEB_SOURCE_DIR}/RunCPackVerifyResult.cmake) # expected results -set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.2_*.deb") +set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.3_*.deb") set(expected_count 3) set(config_verbose -V) @@ -36,7 +36,6 @@ endif() # dpkg-deb checks for the summary of the packages find_program(DPKGDEB_EXECUTABLE dpkg-deb) if(DPKGDEB_EXECUTABLE) - set(dpkgdeb_output_errors_all "") foreach(_f IN LISTS actual_output) # extracts the metadata from the package @@ -54,13 +53,11 @@ if(DPKGDEB_EXECUTABLE) message(STATUS "package='${dpkg_package_name}', dependencies='${dpkg_depends}'") - if("${dpkg_package_name}" STREQUAL "mylib-applications") + if(dpkg_package_name STREQUAL "mylib-applications") find_program(DPKG_SHLIBDEP_EXECUTABLE dpkg-shlibdeps) if(DPKG_SHLIBDEP_EXECUTABLE) - string(FIND "${dpkg_depends}" "lib" index_libwhatever) - if(NOT index_libwhatever GREATER "-1") - set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}" - "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' does not contain any 'lib'\n") + if(NOT dpkg_depends MATCHES "lib") + message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' does not contain any 'lib'\n") endif() else() message("dpkg-shlibdeps executable not found - skipping dpkg-shlibdeps test") @@ -69,29 +66,20 @@ if(DPKGDEB_EXECUTABLE) # should not contain the default string(FIND "${dpkg_depends}" "depend-default" index_default) if(index_default GREATER "0") - set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}" - "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' does contains 'depend-default'\n") + message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' does contains 'depend-default'\n") endif() - elseif("${dpkg_package_name}" STREQUAL "mylib-headers") - if(NOT "${dpkg_depends}" STREQUAL "mylib-libraries (= 1.0.2), depend-headers") - set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}" - "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'mylib-libraries (= 1.0.2), depend-headers'\n") + elseif(dpkg_package_name STREQUAL "mylib-headers") + if(NOT dpkg_depends STREQUAL "mylib-libraries (= 1.0.3), depend-headers") + message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'mylib-libraries (= 1.0.3), depend-headers'\n") endif() - elseif("${dpkg_package_name}" STREQUAL "mylib-libraries") - if(NOT "${dpkg_depends}" STREQUAL "depend-default") - set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}" - "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'depend-default'\n") + elseif(dpkg_package_name STREQUAL "mylib-libraries") + if(NOT dpkg_depends STREQUAL "depend-default") + message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect dependencies for package ${dpkg_package_name}: '${dpkg_depends}' != 'depend-default'\n") endif() else() - set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}" - "dpkg-deb: ${_f}: component name not found: ${dpkg_package_name}\n") + message(SEND_ERROR "dpkg-deb: ${_f}: component name not found: ${dpkg_package_name}\n") endif() - endforeach() - - if(NOT "${dpkgdeb_output_errors_all}" STREQUAL "") - message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}") - endif() else() message("dpkg-deb executable not found - skipping dpkg-deb test") endif() diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description1.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description1.cmake index ad52f56..f74137c 100644 --- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description1.cmake +++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description1.cmake @@ -6,7 +6,7 @@ include(${CPackComponentsDEB_SOURCE_DIR}/RunCPackVerifyResult.cmake) # expected results -set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.2_*.deb") +set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.3_*.deb") set(expected_count 3) @@ -54,18 +54,18 @@ if(DPKGDEB_EXECUTABLE) message(STATUS "package='${dpkg_package_name}', description='${dpkg_description}'") - if("${dpkg_package_name}" STREQUAL "mylib-applications") + if(dpkg_package_name STREQUAL "mylib-applications") if(NOT "${dpkg_description}" STREQUAL "applications_description") set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all} "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != applications_description") endif() - elseif("${dpkg_package_name}" STREQUAL "mylib-headers") - if(NOT "${dpkg_description}" STREQUAL "headers_description") + elseif(dpkg_package_name STREQUAL "mylib-headers") + if(NOT dpkg_description STREQUAL "headers_description") set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all} "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != headers_description") endif() - elseif("${dpkg_package_name}" STREQUAL "mylib-libraries") - if(NOT "${dpkg_description}" STREQUAL "main description") + elseif(dpkg_package_name STREQUAL "mylib-libraries") + if(NOT dpkg_description STREQUAL "main description") set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all} "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != 'main description'") endif() @@ -77,7 +77,7 @@ if(DPKGDEB_EXECUTABLE) endforeach() - if(NOT "${dpkgdeb_output_errors_all}" STREQUAL "") + if(NOT dpkgdeb_output_errors_all STREQUAL "") message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}") endif() else() diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description2.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description2.cmake index af27c51..241dda5 100644 --- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description2.cmake +++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-description2.cmake @@ -7,7 +7,7 @@ include(${CPackComponentsDEB_SOURCE_DIR}/RunCPackVerifyResult.cmake) # expected results -set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.2_*.deb") +set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.3_*.deb") set(expected_count 3) @@ -54,18 +54,18 @@ if(DPKGDEB_EXECUTABLE) message(STATUS "package='${dpkg_package_name}', description='${dpkg_description}'") - if("${dpkg_package_name}" STREQUAL "mylib-applications") - if(NOT "${dpkg_description}" STREQUAL "main description 2") + if(dpkg_package_name STREQUAL "mylib-applications") + if(NOT dpkg_description STREQUAL "main description 2") set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all} "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != applications_description") endif() - elseif("${dpkg_package_name}" STREQUAL "mylib-headers") - if(NOT "${dpkg_description}" STREQUAL "main description 2") + elseif(dpkg_package_name STREQUAL "mylib-headers") + if(NOT dpkg_description STREQUAL "main description 2") set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all} "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != headers_description") endif() - elseif("${dpkg_package_name}" STREQUAL "mylib-libraries") - if(NOT "${dpkg_description}" STREQUAL "library description") + elseif(dpkg_package_name STREQUAL "mylib-libraries") + if(NOT dpkg_description STREQUAL "library description") set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all} "dpkg-deb: ${_f}: Incorrect description for package ${dpkg_package_name}: ${dpkg_description} != 'main description'") endif() @@ -77,7 +77,7 @@ if(DPKGDEB_EXECUTABLE) endforeach() - if(NOT "${dpkgdeb_output_errors_all}" STREQUAL "") + if(NOT dpkgdeb_output_errors_all STREQUAL "") message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}") endif() else() diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-lintian-dpkgdeb-checks.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-lintian-dpkgdeb-checks.cmake index ec75d61..7cfbb16 100644 --- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-lintian-dpkgdeb-checks.cmake +++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-lintian-dpkgdeb-checks.cmake @@ -5,7 +5,7 @@ endif() include(${CPackComponentsDEB_SOURCE_DIR}/RunCPackVerifyResult.cmake) # TODO: currently debian doesn't produce lower cased names -set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.2_*.deb") +set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.3_*.deb") set(expected_count 3) @@ -44,7 +44,7 @@ if(LINTIAN_EXECUTABLE) string(APPEND lintian_output_errors_all "${lintian_output_errors}") endforeach() - if(NOT "${lintian_output_errors_all}" STREQUAL "") + if(NOT lintian_output_errors_all STREQUAL "") message(FATAL_ERROR "Lintian checks failed:\n${lintian_output_errors_all}") endif() else() @@ -64,13 +64,13 @@ if(DPKGDEB_EXECUTABLE) DPKGDEB_OUTPUT "${dpkg_output}" METAENTRY "Maintainer:") - if(NOT "${dpkgentry}" STREQUAL "None") + if(NOT dpkgentry STREQUAL "None") set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}" "dpkg-deb: ${_f}: Incorrect value for Maintainer: ${dpkgentry} != None\n") endif() endforeach() - if(NOT "${dpkgdeb_output_errors_all}" STREQUAL "") + if(NOT dpkgdeb_output_errors_all STREQUAL "") message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}") endif() else() diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-shlibdeps1.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-shlibdeps1.cmake index e57488c..6eff3db 100644 --- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-shlibdeps1.cmake +++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-shlibdeps1.cmake @@ -9,7 +9,7 @@ include(${CPackComponentsDEB_SOURCE_DIR}/RunCPackVerifyResult.cmake) # requirements # debian now produces lower case names -set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.2_*.deb") +set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.3_*.deb") set(expected_count 3) @@ -39,7 +39,7 @@ endif() # dpkg-deb checks for the summary of the packages find_program(DPKGDEB_EXECUTABLE dpkg-deb) if(DPKGDEB_EXECUTABLE) - set(dpkgdeb_output_errors_all) + set(dpkgdeb_output_errors_all "") foreach(_f IN LISTS actual_output) # extracts the metadata from the package @@ -53,11 +53,11 @@ if(DPKGDEB_EXECUTABLE) message(STATUS "package='${dpkg_package_name}'") - if("${dpkg_package_name}" STREQUAL "mylib-applications") + if(dpkg_package_name STREQUAL "mylib-applications") # pass - elseif("${dpkg_package_name}" STREQUAL "mylib-headers") + elseif(dpkg_package_name STREQUAL "mylib-headers") # pass - elseif("${dpkg_package_name}" STREQUAL "mylib-libraries") + elseif(dpkg_package_name STREQUAL "mylib-libraries") # pass else() set(dpkgdeb_output_errors_all ${dpkgdeb_output_errors_all} @@ -67,7 +67,7 @@ if(DPKGDEB_EXECUTABLE) endforeach() - if(NOT "${dpkgdeb_output_errors_all}" STREQUAL "") + if(NOT dpkgdeb_output_errors_all STREQUAL "") message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}") endif() else() diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-source.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-source.cmake index 5ee057a..3454dca 100644 --- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-source.cmake +++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-components-source.cmake @@ -6,7 +6,7 @@ include(${CPackComponentsDEB_SOURCE_DIR}/RunCPackVerifyResult.cmake) # expected results -set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.2_*.deb") +set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib-*_1.0.3_*.deb") set(expected_count 3) set(config_verbose -V) @@ -36,7 +36,6 @@ endif() # dpkg-deb checks for the summary of the packages find_program(DPKGDEB_EXECUTABLE dpkg-deb) if(DPKGDEB_EXECUTABLE) - set(dpkgdeb_output_errors_all "") foreach(_f IN LISTS actual_output) # extracts the metadata from the package @@ -54,22 +53,16 @@ if(DPKGDEB_EXECUTABLE) message(STATUS "package='${_f}', source='${dpkg_package_source}'") - if(NOT ("${dpkg_package_name}" STREQUAL "mylib-applications")) - if(NOT ("${dpkg_package_source}" STREQUAL "test-source")) - set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}" - "dpkg-deb: ${_f}: Incorrect source for package '${dpkg_package_name}': '${dpkg_package_source}' instead of 'test-source'\n") + if(NOT dpkg_package_name STREQUAL "mylib-applications") + if(NOT dpkg_package_source STREQUAL "test-source") + message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect source for package '${dpkg_package_name}': '${dpkg_package_source}' instead of 'test-source'\n") endif() else() - if(NOT ("${dpkg_package_source}" STREQUAL "test-other-source")) - set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}" - "dpkg-deb: ${_f}: Incorrect source for package '${dpkg_package_name}': '${dpkg_package_source}' instead of 'test-other-source'\n") + if(NOT dpkg_package_source STREQUAL "test-other-source") + message(SEND_ERROR "dpkg-deb: ${_f}: Incorrect source for package '${dpkg_package_name}': '${dpkg_package_source}' instead of 'test-other-source'\n") endif() endif() endforeach() - - if(NOT "${dpkgdeb_output_errors_all}" STREQUAL "") - message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}") - endif() else() message("dpkg-deb executable not found - skipping dpkg-deb test") endif() diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult-compression.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult-compression.cmake index 8c0bc4b..764fe9d 100644 --- a/Tests/CPackComponentsDEB/RunCPackVerifyResult-compression.cmake +++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult-compression.cmake @@ -5,7 +5,7 @@ endif() include(${CPackComponentsDEB_SOURCE_DIR}/RunCPackVerifyResult.cmake) # TODO: currently debian doesn't produce lower cased names -set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib_1.0.2_*.deb") +set(expected_file_mask "${CPackComponentsDEB_BINARY_DIR}/mylib_1.0.3_*.deb") set(expected_count 1) set(actual_output) @@ -33,22 +33,16 @@ endif() # dpkg-deb checks find_program(DPKGDEB_EXECUTABLE dpkg-deb) if(DPKGDEB_EXECUTABLE) - set(dpkgdeb_output_errors_all "") foreach(_f IN LISTS actual_output) run_dpkgdeb(dpkg_output FILENAME "${_f}" ) # message(FATAL_ERROR "output = '${dpkg_output}'") - if("${dpkg_output}" STREQUAL "") - set(dpkgdeb_output_errors_all "${dpkgdeb_output_errors_all}" - "dpkg-deb: ${_f}: empty content returned by dpkg-deb") + if(dpkg_output STREQUAL "") + message(SEND_ERROR "dpkg-deb: ${_f}: empty content returned by dpkg-deb") endif() endforeach() - - if(NOT "${dpkgdeb_output_errors_all}" STREQUAL "") - message(FATAL_ERROR "dpkg-deb checks failed:\n${dpkgdeb_output_errors_all}") - endif() else() message("dpkg-deb executable not found - skipping dpkg-deb test") endif() diff --git a/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake b/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake index 2f9e2fc..2093e7e 100644 --- a/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake +++ b/Tests/CPackComponentsDEB/RunCPackVerifyResult.cmake @@ -119,13 +119,13 @@ function(lintian_check_specific_errors output_errors) # regex to avoid foreach(_s IN LISTS lintian_check_specific_errors_deb_ERROR_REGEX_STRINGS) - if("${_s}" STREQUAL "") + if(_s STREQUAL "") continue() endif() string(REGEX MATCHALL "${_s}" "_TMP_CHECK_ERROR" "${lintian_output}") - if(NOT "${_TMP_CHECK_ERROR}" STREQUAL "") + if(NOT _TMP_CHECK_ERROR STREQUAL "") string(APPEND ERROR_ACC "\nlintian: ${_f}: output contains an undesirable regex:\n\t${_TMP_CHECK_ERROR}") endif() endforeach() @@ -167,7 +167,7 @@ function(run_dpkgdeb dpkg_deb_output) ERROR_VARIABLE DPKGDEB_ERROR OUTPUT_STRIP_TRAILING_WHITESPACE ) - if(NOT ("${DPKGDEB_RESULT}" EQUAL "0")) + if(NOT DPKGDEB_RESULT EQUAL "0") message(FATAL_ERROR "Error '${DPKGDEB_RESULT}' returned by dpkg-deb: '${DPKGDEB_ERROR}'") endif() diff --git a/Tests/CudaOnly/DontResolveDeviceSymbols/CMakeLists.txt b/Tests/CudaOnly/DontResolveDeviceSymbols/CMakeLists.txt index 6190089..6e3697f 100644 --- a/Tests/CudaOnly/DontResolveDeviceSymbols/CMakeLists.txt +++ b/Tests/CudaOnly/DontResolveDeviceSymbols/CMakeLists.txt @@ -27,12 +27,12 @@ endif() string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=[compute_30] -gencode arch=compute_50,code=\\\"compute_50\\\"") set(CMAKE_CXX_STANDARD 11) set(CMAKE_CUDA_STANDARD 11) +set(CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS OFF) add_library(CUDANoDeviceResolve SHARED file1.cu) set_target_properties(CUDANoDeviceResolve PROPERTIES CUDA_SEPARABLE_COMPILATION ON - CUDA_RESOLVE_DEVICE_SYMBOLS OFF POSITION_INDEPENDENT_CODE ON) if(MSVC) target_link_options(CUDANoDeviceResolve PRIVATE "/FORCE:UNRESOLVED") diff --git a/Tests/ExternalProject/CMakeLists.txt b/Tests/ExternalProject/CMakeLists.txt index 5adcbd9..093391e 100644 --- a/Tests/ExternalProject/CMakeLists.txt +++ b/Tests/ExternalProject/CMakeLists.txt @@ -421,7 +421,7 @@ if(do_git_tests) set(local_git_repo "../../LocalRepositories/GIT-with-submodules") - set(proj TS1-GIT-no-GIT_SUBMODULES) + set(proj TS1-GIT-all-GIT_SUBMODULES) ExternalProject_Add(${proj} GIT_REPOSITORY "${local_git_repo}" CMAKE_GENERATOR "${CMAKE_GENERATOR}" @@ -435,7 +435,8 @@ if(do_git_tests) ) set_property(TARGET ${proj} PROPERTY FOLDER "GIT") - set(proj TS1-GIT-empty-GIT_SUBMODULES) + set(proj TS1-GIT-all-GIT_SUBMODULES-via-CMP0097-OLD) + cmake_policy(SET CMP0097 OLD) ExternalProject_Add(${proj} GIT_REPOSITORY "${local_git_repo}" GIT_SUBMODULES "" @@ -450,6 +451,22 @@ if(do_git_tests) ) set_property(TARGET ${proj} PROPERTY FOLDER "GIT") + set(proj TS1-GIT-no-GIT_SUBMODULES) + cmake_policy(SET CMP0097 NEW) + ExternalProject_Add(${proj} + GIT_REPOSITORY "${local_git_repo}" + GIT_SUBMODULES "" + CMAKE_GENERATOR "${CMAKE_GENERATOR}" + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> + -DWITH_m1:BOOL=OFF + -DWITH_m2:BOOL=OFF + BUILD_COMMAND "" + INSTALL_COMMAND "" + DEPENDS "SetupLocalGITRepository" + "SetupLocalGITRepositoryWithSubmodules" + ) + set_property(TARGET ${proj} PROPERTY FOLDER "GIT") + set(proj TS1-GIT-some-GIT_SUBMODULES) ExternalProject_Add(${proj} GIT_REPOSITORY "${local_git_repo}" diff --git a/Tests/FindMatlab/basic_checks/CMakeLists.txt b/Tests/FindMatlab/basic_checks/CMakeLists.txt index c5be1ea..c0c752a 100644 --- a/Tests/FindMatlab/basic_checks/CMakeLists.txt +++ b/Tests/FindMatlab/basic_checks/CMakeLists.txt @@ -71,3 +71,15 @@ if(RUN_UNIT_TESTS) ) set_tests_properties(${PROJECT_NAME}_matlabtest-4 PROPERTIES WILL_FAIL TRUE) endif() + + +# checking correct flags passed +# EXCLUDE_FROM_ALL appears after a multiargs (like SRC) +matlab_add_mex( + # target name + NAME cmake_matlab_test_exclude_from_all + # output name + OUTPUT_NAME cmake_matlab_mex_dummy + SRC ${CMAKE_CURRENT_SOURCE_DIR}/../matlab_wrapper_failure.cpp + EXCLUDE_FROM_ALL + ) diff --git a/Tests/FindMatlab/matlab_wrapper_failure.cpp b/Tests/FindMatlab/matlab_wrapper_failure.cpp new file mode 100644 index 0000000..3fe437b --- /dev/null +++ b/Tests/FindMatlab/matlab_wrapper_failure.cpp @@ -0,0 +1,13 @@ +// This should not link, as the mex function is missing. +// This is mostly for checking we are passing the right arguments to the +// add_library + +#include <algorithm> + +#include "mex.h" + +void mexFunctionXX(const int nlhs, mxArray* plhs[], const int nrhs, + const mxArray* prhs[]) +{ + mexErrMsgTxt("Should not be running"); +} diff --git a/Tests/FindOpenACC/CMakeLists.txt b/Tests/FindOpenACC/CMakeLists.txt new file mode 100644 index 0000000..ef7de65 --- /dev/null +++ b/Tests/FindOpenACC/CMakeLists.txt @@ -0,0 +1,20 @@ + +set(langs C CXX) +if(NOT CMAKE_GENERATOR STREQUAL "Ninja") + list(APPEND langs Fortran) +endif() + +foreach(lang IN LISTS langs) + if(CMAKE_${lang}_COMPILER) + add_test(NAME FindOpenACC.Test${lang} COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindOpenACC/${lang}Test" + "${CMake_BINARY_DIR}/Tests/FindOpenACC/${lang}Test" + ${build_generator_args} + --build-project TestFindOpenACC + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) + endif() +endforeach() diff --git a/Tests/FindOpenACC/CTest/CMakeLists.txt b/Tests/FindOpenACC/CTest/CMakeLists.txt new file mode 100644 index 0000000..c8d0968 --- /dev/null +++ b/Tests/FindOpenACC/CTest/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.14) +project(VerifyFindOpenAcc C) + +set(CMAKE_C_STANDARD 11) + +find_package(OpenACC REQUIRED) + +add_executable(UsesOpenACC main.c) +target_link_libraries(UsesOpenACC PRIVATE OpenACC::OpenACC_C) + +add_executable(UsesOpenACCVars main.c) +target_link_options(UsesOpenACCVars PRIVATE ${OpenACC_C_OPTIONS}) +target_compile_options(UsesOpenACCVars PRIVATE ${OpenACC_C_OPTIONS}) diff --git a/Tests/FindOpenACC/CTest/main.c b/Tests/FindOpenACC/CTest/main.c new file mode 100644 index 0000000..53b6cae --- /dev/null +++ b/Tests/FindOpenACC/CTest/main.c @@ -0,0 +1,44 @@ +#include <stdio.h> +#include <stdlib.h> + +void vecaddgpu(float* r, float* a, float* b, int n) +{ +#pragma acc kernels loop present(r, a, b) + for (int i = 0; i < n; ++i) + r[i] = a[i] + b[i]; +} + +int main() +{ + int n = 100000; /* vector length */ + float* a; /* input vector 1 */ + float* b; /* input vector 2 */ + float* r; /* output vector */ + float* e; /* expected output values */ + int i, errs; + + a = (float*)malloc(n * sizeof(float)); + b = (float*)malloc(n * sizeof(float)); + r = (float*)malloc(n * sizeof(float)); + e = (float*)malloc(n * sizeof(float)); + for (i = 0; i < n; ++i) { + a[i] = (float)(i + 1); + b[i] = (float)(1000 * i); + } +/* compute on the GPU */ +#pragma acc data copyin(a [0:n], b [0:n]) copyout(r [0:n]) + { + vecaddgpu(r, a, b, n); + } + /* compute on the host to compare */ + for (i = 0; i < n; ++i) + e[i] = a[i] + b[i]; + /* compare results */ + errs = 0; + for (i = 0; i < n; ++i) { + if (r[i] != e[i]) { + ++errs; + } + } + return errs; +} diff --git a/Tests/FindOpenACC/CXXTest/CMakeLists.txt b/Tests/FindOpenACC/CXXTest/CMakeLists.txt new file mode 100644 index 0000000..a6caf7b --- /dev/null +++ b/Tests/FindOpenACC/CXXTest/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.14) +project(VerifyFindOpenAcc CXX) + +set(CMAKE_CXX_STANDARD 11) + +find_package(OpenACC REQUIRED) + +add_executable(UsesOpenACC main.cxx) +target_link_libraries(UsesOpenACC PRIVATE OpenACC::OpenACC_CXX) + +add_executable(UsesOpenACCVars main.cxx) +target_link_options(UsesOpenACCVars PRIVATE ${OpenACC_CXX_OPTIONS}) +target_compile_options(UsesOpenACCVars PRIVATE ${OpenACC_CXX_OPTIONS}) diff --git a/Tests/FindOpenACC/CXXTest/main.cxx b/Tests/FindOpenACC/CXXTest/main.cxx new file mode 100644 index 0000000..7369045 --- /dev/null +++ b/Tests/FindOpenACC/CXXTest/main.cxx @@ -0,0 +1,43 @@ + +#include <vector> + +void vecaddgpu(float* r, float* a, float* b, std::size_t n) +{ +#pragma acc kernels loop present(r, a, b) + for (std::size_t i = 0; i < n; ++i) + r[i] = a[i] + b[i]; +} + +int main(int, char* []) +{ + const std::size_t n = 100000; /* vector length */ + std::vector<float> a(n); /* input vector 1 */ + std::vector<float> b(n); /* input vector 2 */ + std::vector<float> r(n); /* output vector */ + std::vector<float> e(n); /* expected output values */ + + for (std::size_t i = 0; i < n; ++i) { + a[i] = static_cast<float>(i + 1); + b[i] = static_cast<float>(1000 * i); + } + + /* compute on the GPU */ + auto a_ptr = a.data(); + auto b_ptr = b.data(); + auto r_ptr = r.data(); +#pragma acc data copyin(a_ptr [0:n], b_ptr [0:n]) copyout(r_ptr [0:n]) + { + vecaddgpu(r_ptr, a_ptr, b_ptr, n); + } + /* compute on the host to compare */ + for (std::size_t i = 0; i < n; ++i) + e[i] = a[i] + b[i]; + /* compare results */ + int errs = 0; + for (std::size_t i = 0; i < n; ++i) { + if (r[i] != e[i]) { + ++errs; + } + } + return errs; +} diff --git a/Tests/FindOpenACC/FortranTest/CMakeLists.txt b/Tests/FindOpenACC/FortranTest/CMakeLists.txt new file mode 100644 index 0000000..12e3503 --- /dev/null +++ b/Tests/FindOpenACC/FortranTest/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.14) +project(VerifyFindOpenAcc Fortran) + +find_package(OpenACC REQUIRED) + +add_executable(UsesOpenACC main.f90) +target_link_libraries(UsesOpenACC PRIVATE OpenACC::OpenACC_Fortran) + +add_executable(UsesOpenACCVars main.f90) +target_link_options(UsesOpenACCVars PRIVATE ${OpenACC_Fortran_OPTIONS}) +target_compile_options(UsesOpenACCVars PRIVATE ${OpenACC_Fortran_OPTIONS}) diff --git a/Tests/FindOpenACC/FortranTest/main.f90 b/Tests/FindOpenACC/FortranTest/main.f90 new file mode 100644 index 0000000..2ff1ba0 --- /dev/null +++ b/Tests/FindOpenACC/FortranTest/main.f90 @@ -0,0 +1,9 @@ +program t +integer(4) a(10000) +a = [ (1+i,i=1,10000) ] +!$acc kernels +do i = 1, 10000 + if (a(i)/3000*3000.eq.a(i)) print *," located ",i,a(i),i.gt.5000,a(i)/5.0 +end do +!$acc end kernels +end diff --git a/Tests/FindPackageTest/CMakeLists.txt b/Tests/FindPackageTest/CMakeLists.txt index 1b9c973..7217f43 100644 --- a/Tests/FindPackageTest/CMakeLists.txt +++ b/Tests/FindPackageTest/CMakeLists.txt @@ -391,16 +391,44 @@ try_compile(EXPORTER_COMPILED message(STATUS "Searching for export(PACKAGE) test project") set(CMakeTestExportPackage_DIR "" CACHE FILEPATH "Wipe out find results for testing." FORCE) + +message(STATUS "Searching for export(PACKAGE) with CMAKE_FIND_USE_PACKAGE_REGISTRY=TRUE") +set(CMAKE_FIND_USE_PACKAGE_REGISTRY TRUE) +find_package(CMakeTestExportPackage 1.${version} EXACT REQUIRED) +if(NOT CMakeTestExportPackage_FOUND) + message(SEND_ERROR "CMakeTestExportPackage should be FOUND!") +endif() +unset(CMAKE_FIND_USE_PACKAGE_REGISTRY) + +message(STATUS "Searching for export(PACKAGE) with CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=FALSE") +set(CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY FALSE) find_package(CMakeTestExportPackage 1.${version} EXACT REQUIRED) +if(NOT CMakeTestExportPackage_FOUND) + message(SEND_ERROR "CMakeTestExportPackage should be FOUND!") +endif() +unset(CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY) -message(STATUS "Searching for export(PACKAGE) test project with CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=TRUE") +message(STATUS "Searching for export(PACKAGE) with CMAKE_FIND_USE_PACKAGE_REGISTRY=TRUE and CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=TRUE") +set(CMAKE_FIND_USE_PACKAGE_REGISTRY TRUE) set(CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY TRUE) +set(CMakeTestExportPackage_DIR FALSE) +find_package(CMakeTestExportPackage 1.${version} EXACT REQUIRED) +if(NOT CMakeTestExportPackage_FOUND) + message(SEND_ERROR "CMakeTestExportPackage should be FOUND!") +endif() +unset(CMAKE_FIND_USE_PACKAGE_REGISTRY) +unset(CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY) + +message(STATUS "Searching for export(PACKAGE) with CMAKE_FIND_USE_PACKAGE_REGISTRY=FALSE and CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY=FALSE") +set(CMAKE_FIND_USE_PACKAGE_REGISTRY FALSE) +set(CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY FALSE) set(CMakeTestExportPackage_DIR "" CACHE FILEPATH "Wipe out find results for testing." FORCE) -find_package(CMakeTestExportPackage 1.${version} EXACT QUIET) +find_package(CMakeTestExportPackage 1.${version} EXACT QUIET) if(CMakeTestExportPackage_FOUND) - message(SEND_ERROR "CMakeTestExportPackage should not be FOUND!") + message(SEND_ERROR "CMakeTestExportPackage should be not FOUND!") endif() +unset(CMAKE_FIND_USE_PACKAGE_REGISTRY) unset(CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY) message(STATUS "Remove export(PACKAGE) test project") diff --git a/Tests/FindProtobuf/Test/CMakeLists.txt b/Tests/FindProtobuf/Test/CMakeLists.txt index bc89190..fc6b37e 100644 --- a/Tests/FindProtobuf/Test/CMakeLists.txt +++ b/Tests/FindProtobuf/Test/CMakeLists.txt @@ -29,6 +29,7 @@ add_test(NAME test_tgt_protoc COMMAND test_tgt_protoc) add_executable(test_var_protoc main-protoc.cxx) target_include_directories(test_var_protoc PRIVATE ${Protobuf_INCLUDE_DIRS}) target_link_libraries(test_var_protoc PRIVATE ${Protobuf_PROTOC_LIBRARIES}) +target_compile_features(test_var_protoc PRIVATE cxx_std_11) add_test(NAME test_var_protoc COMMAND test_var_protoc) add_test(NAME test_tgt_protoc_version COMMAND protobuf::protoc --version) @@ -37,14 +38,17 @@ set(Protobuf_IMPORT_DIRS ${Protobuf_INCLUDE_DIRS}) PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_HEADER msgs/example.proto) PROTOBUF_GENERATE_CPP(DESC_PROTO_SRC DESC_PROTO_HEADER DESCRIPTORS DESC_PROTO_DESC msgs/example_desc.proto) add_library(msgs ${PROTO_SRC} ${PROTO_HEADER}) +target_compile_features(msgs PRIVATE cxx_std_11) add_executable(test_generate main-generate.cxx ${PROTO_SRC}) target_include_directories(test_generate PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(test_generate msgs ${Protobuf_LIBRARIES}) +target_compile_features(test_generate PRIVATE cxx_std_11) add_test(NAME test_generate COMMAND test_generate) add_executable(test_desc main-desc.cxx ${DESC_PROTO_SRC}) target_compile_features(test_desc PRIVATE cxx_std_11) target_include_directories(test_desc PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(test_desc msgs ${Protobuf_LIBRARIES}) +target_compile_features(test_desc PRIVATE cxx_std_11) add_test(NAME test_desc COMMAND test_desc ${DESC_PROTO_DESC}) diff --git a/Tests/FindPython/FindPythonScript.cmake b/Tests/FindPython/FindPythonScript.cmake index 9450092..bc7e0d1 100644 --- a/Tests/FindPython/FindPythonScript.cmake +++ b/Tests/FindPython/FindPythonScript.cmake @@ -1 +1,9 @@ -find_package(${PYTHON_PACKAGE_NAME} REQUIRED QUIET) + +if (PYTHON_MUST_NOT_BE_FOUND) + find_package(${PYTHON_PACKAGE_NAME} QUIET) + if (${PYTHON_PACKAGE_NAME}_FOUND) + message(FATAL_ERROR "${PYTHON_PACKAGE_NAME}: unexpectedly founded.") + endif() +else() + find_package(${PYTHON_PACKAGE_NAME} REQUIRED QUIET) +endif() diff --git a/Tests/FindPython/Python2/CMakeLists.txt b/Tests/FindPython/Python2/CMakeLists.txt index 274745a..cf77ca2 100644 --- a/Tests/FindPython/Python2/CMakeLists.txt +++ b/Tests/FindPython/Python2/CMakeLists.txt @@ -34,4 +34,5 @@ add_test (NAME python2_spam2 add_test(NAME findpython2_script COMMAND "${CMAKE_COMMAND}" -DPYTHON_PACKAGE_NAME=Python2 + -DPython2_FIND_STRATEGY=${Python2_FIND_STRATEGY} -P "${CMAKE_CURRENT_LIST_DIR}/../FindPythonScript.cmake") diff --git a/Tests/FindPython/Python3/CMakeLists.txt b/Tests/FindPython/Python3/CMakeLists.txt index b21a15b..6691a48 100644 --- a/Tests/FindPython/Python3/CMakeLists.txt +++ b/Tests/FindPython/Python3/CMakeLists.txt @@ -34,4 +34,57 @@ add_test (NAME python3_spam3 add_test(NAME findpython3_script COMMAND "${CMAKE_COMMAND}" -DPYTHON_PACKAGE_NAME=Python3 + -DPython3_FIND_STRATEGY=${Python3_FIND_STRATEGY} + -P "${CMAKE_CURRENT_LIST_DIR}/../FindPythonScript.cmake") + + +## Try a new search specifying only expected ABI +# retrieve ABI of python interpreter +execute_process (COMMAND "${Python3_EXECUTABLE}" -c + "import sys; sys.stdout.write(sys.abiflags)" + RESULT_VARIABLE result + OUTPUT_VARIABLE abi + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +if (result) + # assume ABI is not supported + set (abi "") +endif() + +# define FIND_ABI variable +if (abi MATCHES "d") + set (Python3_VALID_ABI "ON") +else() + set (Python3_VALID_ABI "OFF") +endif() +if (abi MATCHES "m") + list (APPEND Python3_VALID_ABI "ON") +else() + list (APPEND Python3_VALID_ABI "OFF") +endif() +if (abi MATCHES "u") + list (APPEND Python3_VALID_ABI "ON") +else() + list (APPEND Python3_VALID_ABI "OFF") +endif() +# build an invalid pattern for ABI +set (Python3_INVALID_ABI) +foreach (abi IN LISTS Python3_VALID_ABI) + if (abi) + list (APPEND Python3_INVALID_ABI "OFF") + else() + list (APPEND Python3_INVALID_ABI "ON") + endif() +endforeach() + +add_test(NAME python3_find_valid_abi + COMMAND "${CMAKE_COMMAND}" -DPYTHON_PACKAGE_NAME=Python3 + -DPython3_FIND_STRATEGY=${Python3_FIND_STRATEGY} + "-DPython3_FIND_ABI=${Python3_VALID_ABI}" + -P "${CMAKE_CURRENT_LIST_DIR}/../FindPythonScript.cmake") +add_test(NAME python3_find_invalid_abi + COMMAND "${CMAKE_COMMAND}" -DPYTHON_PACKAGE_NAME=Python3 + -DPYTHON_MUST_NOT_BE_FOUND=ON + -DPython3_FIND_STRATEGY=${Python3_FIND_STRATEGY} + "-DPython3_FIND_ABI=${Python3_INVALID_ABI}" -P "${CMAKE_CURRENT_LIST_DIR}/../FindPythonScript.cmake") diff --git a/Tests/MSVCRuntimeLibrary/Fortran/CMakeLists.txt b/Tests/MSVCRuntimeLibrary/Fortran/CMakeLists.txt index 169ba07..27838a4 100644 --- a/Tests/MSVCRuntimeLibrary/Fortran/CMakeLists.txt +++ b/Tests/MSVCRuntimeLibrary/Fortran/CMakeLists.txt @@ -6,9 +6,17 @@ foreach(t MultiThreaded SingleThreaded) foreach(dbg "" Debug) foreach(dll "" DLL) set(var "CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_${t}${dbg}${dll}") - # ifort does not actually define these, so inject them - string(REPLACE "-threads" "-threads;-D_MT" "${var}" "${${var}}") - string(REPLACE "-dbglibs" "-dbglibs;-D_DEBUG" "${var}" "${${var}}") + if(CMAKE_Fortran_COMPILER_ID STREQUAL "Intel") + # ifort does not actually define these, so inject them + string(REPLACE "-threads" "-threads;-D_MT" "${var}" "${${var}}") + string(REPLACE "-dbglibs" "-dbglibs;-D_DEBUG" "${var}" "${${var}}") + elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "Flang") + # flang does not actually define these, so inject them + string(REPLACE ";--dependent-lib=libcmt;" ";--dependent-lib=libcmt;-D_MT;" "${var}" ";${${var}};") + string(REPLACE ";--dependent-lib=msvcrt;" ";--dependent-lib=msvcrt;-D_MT;-D_DLL;" "${var}" ";${${var}};") + string(REPLACE ";--dependent-lib=libcmtd;" ";--dependent-lib=libcmtd;-D_MT;-D_DEBUG;" "${var}" ";${${var}};") + string(REPLACE ";--dependent-lib=msvcrtd;" ";--dependent-lib=msvcrtd;-D_MT;-D_DEBUG;-D_DLL;" "${var}" ";${${var}};") + endif() endforeach() endforeach() endforeach() @@ -45,6 +53,6 @@ endfunction() verify(Fortran verify.F90) # Intel Fortran for Windows supports single-threaded RTL but it is # not implemented by the Visual Studio integration. -if(NOT CMAKE_GENERATOR MATCHES "Visual Studio") +if(CMAKE_Fortran_COMPILER_ID STREQUAL "Intel" AND NOT CMAKE_GENERATOR MATCHES "Visual Studio") verify_combinations(SingleThreaded Fortran verify.F90) endif() diff --git a/Tests/MakeClean/ToClean/CMakeLists.txt b/Tests/MakeClean/ToClean/CMakeLists.txt index 6f16d12..a05c38b 100644 --- a/Tests/MakeClean/ToClean/CMakeLists.txt +++ b/Tests/MakeClean/ToClean/CMakeLists.txt @@ -15,42 +15,45 @@ function(writeCleanFile FILENAME) file(WRITE "${FILENAME}" ${CLEAN_FILE_CONTENT}) endfunction() +set(DUMMY_CONTENT_FILE ${CSD}/toclean.cxx) + # Build a simple project whose compiled objects should be cleaned. add_executable(toclean toclean.cxx) -addCleanFile("${CBD}${CMAKE_FILES_DIRECTORY}/toclean.dir/toclean.cxx${CMAKE_CXX_OUTPUT_EXTENSION}") +addCleanFile( + "${CBD}${CMAKE_FILES_DIRECTORY}/toclean.dir/toclean.cxx${CMAKE_CXX_OUTPUT_EXTENSION}") -# Create a post build custom command that copies the toclean output executable +# Create a post build custom command that copies a dummy file # to a custom location -function(addToCleanPostBuildCopy FILENAME) - add_custom_command(TARGET toclean POST_BUILD +function(addPostBuildFile TARGET FILENAME) + add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} - ARGS -E copy $<TARGET_FILE:toclean> ${FILENAME}) + ARGS -E copy ${DUMMY_CONTENT_FILE} ${FILENAME}) endfunction() # Create a custom command whose output should be cleaned. set(CustomCommandFile "${CBD}/CustomCommandFile.txt") add_custom_command(OUTPUT ${CustomCommandFile} - DEPENDS ${CSD}/toclean.cxx + DEPENDS ${DUMMY_CONTENT_FILE} COMMAND ${CMAKE_COMMAND} - ARGS -E copy ${CSD}/toclean.cxx ${CustomCommandFile}) -add_custom_target(generate ALL DEPENDS ${CustomCommandFile}) + ARGS -E copy ${DUMMY_CONTENT_FILE} ${CustomCommandFile}) +add_custom_target(customTarget ALL DEPENDS ${CustomCommandFile}) addCleanFile(${CustomCommandFile}) ### Tests ADDITIONAL_MAKE_CLEAN_FILES directory property if("${CMAKE_GENERATOR}" MATCHES "Makefile") # Create a file that must be registered for cleaning. - set(MakeDirPropFile "${CBD}/MakeDirPropFile.txt") - writeCleanFile("${MakeDirPropFile}") - set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${MakeDirPropFile}") - addCleanFile(${MakeDirPropFile}) + set(MakeDirPropFileAbs "${CBD}/MakeDirPropFile.txt") + writeCleanFile("${MakeDirPropFileAbs}") + set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${MakeDirPropFileAbs}") + addCleanFile(${MakeDirPropFileAbs}) # Create a custom command whose output should be cleaned, but whose name # is not known until generate-time set(MakeDirPropExpFileRel "MakeDirProp_copy${CMAKE_EXECUTABLE_SUFFIX}") - set(MakeDirPropExpFile "$<TARGET_FILE_DIR:toclean>/${MakeDirPropExpFileRel}") - addToCleanPostBuildCopy("${MakeDirPropExpFile}") - set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${MakeDirPropExpFile}) + set(MakeDirPropExpFileAbs "$<TARGET_FILE_DIR:toclean>/${MakeDirPropExpFileRel}") + addPostBuildFile(toclean "${MakeDirPropExpFileAbs}") + set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${MakeDirPropExpFileAbs}) addCleanFile("${CBD}/${MakeDirPropExpFileRel}") endif() @@ -72,34 +75,43 @@ addCleanFile("${DirPropFileAbs}") # Create a custom command whose output should be cleaned, but whose name # is not known until generate-time set(DirPropExpFileRel "DirProp_copy${CMAKE_EXECUTABLE_SUFFIX}") -set(DirPropExpFile "$<TARGET_FILE_DIR:toclean>/${DirPropExpFileRel}") -addToCleanPostBuildCopy("${DirPropExpFile}") -set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_CLEAN_FILES ${DirPropExpFile}) +set(DirPropExpFileAbs "$<TARGET_FILE_DIR:toclean>/${DirPropExpFileRel}") +addPostBuildFile(toclean "${DirPropExpFileAbs}") +set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_CLEAN_FILES ${DirPropExpFileAbs}) addCleanFile("${CBD}/${DirPropExpFileRel}") ### Tests ADDITIONAL_CLEAN_FILES target property -# Register a file path relative to the build directory -set(TgtPropFileRel "TargetPropFileRel.txt") -writeCleanFile("${CBD}/${TgtPropFileRel}") -set_target_properties(toclean PROPERTIES ADDITIONAL_CLEAN_FILES ${TgtPropFileRel}) -addCleanFile("${CBD}/${TgtPropFileRel}") - -# Register an absolute file path -set(TgtPropFileAbs "${CBD}/TargetPropFileAbs.txt") -writeCleanFile("${TgtPropFileAbs}") -set_property(TARGET toclean APPEND PROPERTY ADDITIONAL_CLEAN_FILES ${TgtPropFileAbs}) -addCleanFile("${TgtPropFileAbs}") - -# Create a custom command whose output should be cleaned, but whose name -# is not known until generate-time -set(TgtPropExpFileRel "TgtProp_copy${CMAKE_EXECUTABLE_SUFFIX}") -set(TgtPropExpFile "$<TARGET_FILE_DIR:toclean>/${TgtPropExpFileRel}") -addToCleanPostBuildCopy("${TgtPropExpFile}") -set_property(TARGET toclean APPEND PROPERTY ADDITIONAL_CLEAN_FILES ${TgtPropExpFile}) -addCleanFile("${CBD}/${TgtPropExpFileRel}") +function(test_target_property TARGET) + # Register a file path relative to the build directory + set(TgtPropFileRel "${TARGET}_TargetPropFileRel.txt") + writeCleanFile("${CBD}/${TgtPropFileRel}") + set_target_properties(${TARGET} PROPERTIES ADDITIONAL_CLEAN_FILES ${TgtPropFileRel}) + addCleanFile("${CBD}/${TgtPropFileRel}") + + # Register an absolute file path + set(TgtPropFileAbs "${CBD}/${TARGET}_TargetPropFileAbs.txt") + writeCleanFile("${TgtPropFileAbs}") + set_property(TARGET ${TARGET} APPEND PROPERTY ADDITIONAL_CLEAN_FILES ${TgtPropFileAbs}) + addCleanFile("${TgtPropFileAbs}") + + # Create a custom command whose output should be cleaned, but whose name + # is not known until generate-time + set(TgtPropExpFileRel "${TARGET}_TargetPropGenExp.txt") + set(TgtPropExpFileAbs "$<TARGET_FILE_DIR:toclean>/${TgtPropExpFileRel}") + addPostBuildFile(${TARGET} "${TgtPropExpFileAbs}") + set_property(TARGET ${TARGET} APPEND PROPERTY ADDITIONAL_CLEAN_FILES ${TgtPropExpFileAbs}) + addCleanFile("${CBD}/${TgtPropExpFileRel}") +endfunction() +# Test target property for various target types +add_executable(acf_exec toclean.cxx) +test_target_property(acf_exec) +add_library(acf_lib toclean.cxx) +test_target_property(acf_lib) +add_custom_target(acf_custom ALL DEPENDS ${CustomCommandFile}) +test_target_property(acf_custom) # Process subdirectory without targets add_subdirectory(EmptySubDir) diff --git a/Tests/MathTest/CMakeLists.txt b/Tests/MathTest/CMakeLists.txt index 5403d29..396f633 100644 --- a/Tests/MathTest/CMakeLists.txt +++ b/Tests/MathTest/CMakeLists.txt @@ -16,6 +16,8 @@ set(expressions "1000 -12*5" "1000 +12*-5" "1000 -12*-5" + "~~1" + "1000 & ~0" ) set(FILE_EXPRESSIONS "extern void test_expression(int x, int y, const char * text);\n") diff --git a/Tests/PDBDirectoryAndName/CMakeLists.txt b/Tests/PDBDirectoryAndName/CMakeLists.txt index 6d8d6cc..44194ca 100644 --- a/Tests/PDBDirectoryAndName/CMakeLists.txt +++ b/Tests/PDBDirectoryAndName/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_policy(SET CMP0054 NEW) project(PDBDirectoryAndName C) # Make sure the proper compiler is in use. -if(NOT MSVC AND NOT CMAKE_C_COMPILER_ID STREQUAL "Intel") - message(FATAL_ERROR "The PDBDirectoryAndName test works only with MSVC or Intel") +if(NOT MSVC AND NOT CMAKE_C_COMPILER_ID STREQUAL "Intel" AND NOT CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "The PDBDirectoryAndName test works only with MSVC, Clang or Intel") endif() # Intel 11.1 does not support /Fd but Intel 14.0 does. diff --git a/Tests/Preprocess/CMakeLists.txt b/Tests/Preprocess/CMakeLists.txt index 588af03..bce1b3f 100644 --- a/Tests/Preprocess/CMakeLists.txt +++ b/Tests/Preprocess/CMakeLists.txt @@ -29,7 +29,10 @@ if("${CMAKE_GENERATOR}" MATCHES "Visual Studio") set(PP_VS 1) endif() if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND - "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC" AND + "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") + set(CLANG_MSVC_WINDOWS 1) +endif() +if(CLANG_MSVC_WINDOWS AND "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU") set(CLANG_GNULIKE_WINDOWS 1) endif() @@ -106,7 +109,7 @@ endif() set(EXPR_OP1 "/") if((NOT MSVC OR PP_NMAKE) AND NOT CMAKE_C_COMPILER_ID STREQUAL "Intel" AND - NOT CLANG_GNULIKE_WINDOWS) + NOT CLANG_MSVC_WINDOWS) # MSVC cl, Intel icl: % # When the cl compiler is invoked from the command line then % must # be written %% (to distinguish from %ENV% syntax). However cl does diff --git a/Tests/QtAutogen/SameName/CMakeLists.txt b/Tests/QtAutogen/SameName/CMakeLists.txt index 0a80d5e..1919cc7 100644 --- a/Tests/QtAutogen/SameName/CMakeLists.txt +++ b/Tests/QtAutogen/SameName/CMakeLists.txt @@ -18,9 +18,11 @@ add_executable(sameName ccc/data.qrc item.cpp object.h + object.hh object.h++ object.hpp object.hxx + object_upper_ext.H data.qrc main.cpp ) diff --git a/Tests/QtAutogen/SameName/main.cpp b/Tests/QtAutogen/SameName/main.cpp index 92f15cd..725f4cd 100644 --- a/Tests/QtAutogen/SameName/main.cpp +++ b/Tests/QtAutogen/SameName/main.cpp @@ -6,8 +6,10 @@ #include "item.hpp" #include "object.h" #include "object.h++" +#include "object.hh" #include "object.hpp" #include "object.hxx" +#include "object_upper_ext.H" int main(int argv, char** args) { @@ -20,8 +22,10 @@ int main(int argv, char** args) ::ccc::Item ccc_item; // Object instances ::Object_h obj_h; + ::Object_hh obj_hh; ::Object_hplpl obj_hplpl; ::Object_hpp obj_hpp; ::Object_hxx obj_hxx; + ::Object_Upper_Ext_H obj_upper_ext_h; return 0; } diff --git a/Tests/QtAutogen/SameName/object.hh b/Tests/QtAutogen/SameName/object.hh new file mode 100644 index 0000000..3e16f83 --- /dev/null +++ b/Tests/QtAutogen/SameName/object.hh @@ -0,0 +1,13 @@ +#ifndef OBJECT_HH +#define OBJECT_HH + +#include <QObject> + +class Object_hh : public QObject +{ + Q_OBJECT + Q_SLOT + void go(){}; +}; + +#endif diff --git a/Tests/QtAutogen/SameName/object_upper_ext.H b/Tests/QtAutogen/SameName/object_upper_ext.H new file mode 100644 index 0000000..3266087 --- /dev/null +++ b/Tests/QtAutogen/SameName/object_upper_ext.H @@ -0,0 +1,13 @@ +#ifndef OBJECT_UPPER_EXT_H +#define OBJECT_UPPER_EXT_H + +#include <QObject> + +class Object_Upper_Ext_H : public QObject +{ + Q_OBJECT + Q_SLOT + void go(){}; +}; + +#endif diff --git a/Tests/RunCMake/Android/common.cmake b/Tests/RunCMake/Android/common.cmake index aaa7c89..d96ab86 100644 --- a/Tests/RunCMake/Android/common.cmake +++ b/Tests/RunCMake/Android/common.cmake @@ -6,8 +6,6 @@ if(NOT ANDROID) endif() foreach(f - "${CMAKE_C_ANDROID_TOOLCHAIN_PREFIX}gcc${CMAKE_C_ANDROID_TOOLCHAIN_SUFFIX}" - "${CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX}g++${CMAKE_CXX_ANDROID_TOOLCHAIN_SUFFIX}" "${CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX}ar${CMAKE_CXX_ANDROID_TOOLCHAIN_SUFFIX}" "${CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX}ld${CMAKE_CXX_ANDROID_TOOLCHAIN_SUFFIX}" ) @@ -51,23 +49,26 @@ elseif(CMAKE_ANDROID_STANDALONE_TOOLCHAIN) endif() endif() -execute_process( - COMMAND "${CMAKE_C_ANDROID_TOOLCHAIN_PREFIX}gcc${CMAKE_C_ANDROID_TOOLCHAIN_SUFFIX}" -dumpmachine - OUTPUT_VARIABLE _out OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_VARIABLE _err - RESULT_VARIABLE _res - ) -if(NOT _res EQUAL 0) - message(SEND_ERROR "Failed to run 'gcc -dumpmachine':\n ${_res}") -endif() -string(REPLACE "--" "-" _out_check "${_out}") -if(NOT _out_check STREQUAL "${CMAKE_C_ANDROID_TOOLCHAIN_MACHINE}" - AND NOT (_out STREQUAL "arm--linux-android" AND CMAKE_C_ANDROID_TOOLCHAIN_MACHINE STREQUAL "arm-linux-androideabi")) - message(SEND_ERROR "'gcc -dumpmachine' produced:\n" - " ${_out}\n" - "which does not match CMAKE_C_ANDROID_TOOLCHAIN_MACHINE:\n" - " ${CMAKE_C_ANDROID_TOOLCHAIN_MACHINE}" +set(gcc ${CMAKE_C_ANDROID_TOOLCHAIN_PREFIX}gcc${CMAKE_C_ANDROID_TOOLCHAIN_SUFFIX}) +if(EXISTS "${gcc}") + execute_process( + COMMAND "${CMAKE_C_ANDROID_TOOLCHAIN_PREFIX}gcc${CMAKE_C_ANDROID_TOOLCHAIN_SUFFIX}" -dumpmachine + OUTPUT_VARIABLE _out OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE _err + RESULT_VARIABLE _res ) + if(NOT _res EQUAL 0) + message(SEND_ERROR "Failed to run 'gcc -dumpmachine':\n ${_res}") + endif() + string(REPLACE "--" "-" _out_check "${_out}") + if(NOT _out_check STREQUAL "${CMAKE_C_ANDROID_TOOLCHAIN_MACHINE}" + AND NOT (_out STREQUAL "arm--linux-android" AND CMAKE_C_ANDROID_TOOLCHAIN_MACHINE STREQUAL "arm-linux-androideabi")) + message(SEND_ERROR "'gcc -dumpmachine' produced:\n" + " ${_out}\n" + "which does not match CMAKE_C_ANDROID_TOOLCHAIN_MACHINE:\n" + " ${CMAKE_C_ANDROID_TOOLCHAIN_MACHINE}" + ) + endif() endif() if(CMAKE_ANDROID_STL_TYPE STREQUAL "none") diff --git a/Tests/RunCMake/Android/ndk-arm64-v8a-stdout.txt b/Tests/RunCMake/Android/ndk-arm64-v8a-stdout.txt index 8d0bdc2..a228ccc 100644 --- a/Tests/RunCMake/Android/ndk-arm64-v8a-stdout.txt +++ b/Tests/RunCMake/Android/ndk-arm64-v8a-stdout.txt @@ -1,2 +1,2 @@ -- Android: Targeting API '[0-9]+' with architecture 'arm64', ABI 'arm64-v8a', and processor 'aarch64' --- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+' +-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+') diff --git a/Tests/RunCMake/Android/ndk-armeabi-arm-stdout.txt b/Tests/RunCMake/Android/ndk-armeabi-arm-stdout.txt index 3741da3..72ec00e 100644 --- a/Tests/RunCMake/Android/ndk-armeabi-arm-stdout.txt +++ b/Tests/RunCMake/Android/ndk-armeabi-arm-stdout.txt @@ -1,3 +1,3 @@ -- Android: Targeting API '[0-9]+' with architecture 'arm', ABI 'armeabi', and processor 'armv5te' --- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+' +-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+') .*-- CMAKE_ANDROID_ARM_MODE=1 diff --git a/Tests/RunCMake/Android/ndk-armeabi-v7a-neon-stdout.txt b/Tests/RunCMake/Android/ndk-armeabi-v7a-neon-stdout.txt index ac2bfd5..8bd87fa 100644 --- a/Tests/RunCMake/Android/ndk-armeabi-v7a-neon-stdout.txt +++ b/Tests/RunCMake/Android/ndk-armeabi-v7a-neon-stdout.txt @@ -1,3 +1,3 @@ -- Android: Targeting API '[0-9]+' with architecture 'arm', ABI 'armeabi-v7a', and processor 'armv7-a' --- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+' +-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+') .*-- CMAKE_ANDROID_ARM_NEON=1 diff --git a/Tests/RunCMake/Android/ndk-armeabi-v7a-stdout.txt b/Tests/RunCMake/Android/ndk-armeabi-v7a-stdout.txt index 0edb4f7..554548e 100644 --- a/Tests/RunCMake/Android/ndk-armeabi-v7a-stdout.txt +++ b/Tests/RunCMake/Android/ndk-armeabi-v7a-stdout.txt @@ -1,3 +1,3 @@ -- Android: Targeting API '[0-9]+' with architecture 'arm', ABI 'armeabi-v7a', and processor 'armv7-a' --- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+' +-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+') .*-- CMAKE_ANDROID_ARM_NEON=0 diff --git a/Tests/RunCMake/Android/ndk-badver-stderr.txt b/Tests/RunCMake/Android/ndk-badver-stderr.txt index df2c5e6..ce6bc4e 100644 --- a/Tests/RunCMake/Android/ndk-badver-stderr.txt +++ b/Tests/RunCMake/Android/ndk-badver-stderr.txt @@ -1,11 +1,12 @@ ^CMake Error at .*/Modules/Platform/Android/Determine-Compiler-NDK.cmake:[0-9]+ \(message\): - Android: The CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION value 'badver' is not one + Android: The CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION value 'badver' is not( + supported by this NDK. It must be 'clang' or not set at all\.| one of the allowed forms: <major>.<minor> = GCC of specified version clang<major>.<minor> = Clang of specified version clang = Clang of most recent available version - +) Call Stack \(most recent call first\): .* ndk-badver.cmake:1 \(enable_language\) diff --git a/Tests/RunCMake/Android/ndk-badvernum-stderr.txt b/Tests/RunCMake/Android/ndk-badvernum-stderr.txt index adacaf1..aec91d9 100644 --- a/Tests/RunCMake/Android/ndk-badvernum-stderr.txt +++ b/Tests/RunCMake/Android/ndk-badvernum-stderr.txt @@ -1,4 +1,6 @@ -^CMake Error at .*/Modules/Platform/Android/Determine-Compiler-NDK.cmake:[0-9]+ \(message\): +^CMake Error at .*/Modules/Platform/Android/Determine-Compiler-NDK.cmake:[0-9]+ \(message\):( + Android: The CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION value '1.0' is not + supported by this NDK. It must be 'clang' or not set at all.| Android: No toolchain for ABI 'armeabi(-v7a)?' found in the NDK: .* @@ -6,7 +8,7 @@ of the version specified by CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION: 1\.0 - +) Call Stack \(most recent call first\): .* ndk-badvernum.cmake:1 \(enable_language\) diff --git a/Tests/RunCMake/Android/ndk-mips-stdout.txt b/Tests/RunCMake/Android/ndk-mips-stdout.txt index c744683..8ce544d 100644 --- a/Tests/RunCMake/Android/ndk-mips-stdout.txt +++ b/Tests/RunCMake/Android/ndk-mips-stdout.txt @@ -1,2 +1,2 @@ -- Android: Targeting API '[0-9]+' with architecture 'mips', ABI 'mips', and processor 'mips' --- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+' +-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+') diff --git a/Tests/RunCMake/Android/ndk-mips64-stdout.txt b/Tests/RunCMake/Android/ndk-mips64-stdout.txt index 839ddfd..1d7edea 100644 --- a/Tests/RunCMake/Android/ndk-mips64-stdout.txt +++ b/Tests/RunCMake/Android/ndk-mips64-stdout.txt @@ -1,2 +1,2 @@ -- Android: Targeting API '[0-9]+' with architecture 'mips64', ABI 'mips64', and processor 'mips64' --- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+' +-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+') diff --git a/Tests/RunCMake/Android/ndk-x86-stdout.txt b/Tests/RunCMake/Android/ndk-x86-stdout.txt index 2dbb2f0..8d710fe 100644 --- a/Tests/RunCMake/Android/ndk-x86-stdout.txt +++ b/Tests/RunCMake/Android/ndk-x86-stdout.txt @@ -1,2 +1,2 @@ -- Android: Targeting API '[0-9]+' with architecture 'x86', ABI 'x86', and processor 'i686' --- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+' +-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+') diff --git a/Tests/RunCMake/Android/ndk-x86_64-stdout.txt b/Tests/RunCMake/Android/ndk-x86_64-stdout.txt index a7ae91d..695a088 100644 --- a/Tests/RunCMake/Android/ndk-x86_64-stdout.txt +++ b/Tests/RunCMake/Android/ndk-x86_64-stdout.txt @@ -1,2 +1,2 @@ -- Android: Targeting API '[0-9]+' with architecture 'x86_64', ABI 'x86_64', and processor 'x86_64' --- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+' +-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+') diff --git a/Tests/RunCMake/CMP0065/RunCMakeTest.cmake b/Tests/RunCMake/CMP0065/RunCMakeTest.cmake index 254a4ec..e86b50e 100644 --- a/Tests/RunCMake/CMP0065/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMP0065/RunCMakeTest.cmake @@ -1,8 +1,11 @@ include(RunCMake) run_cmake(OLDBad1) -run_cmake(OLDBad2) -run_cmake(NEWBad) +if(NOT CMAKE_SYSTEM_NAME STREQUAL "AIX") + # Tests with ENABLE_EXPORTS ON. For AIX we do not use the flags at all. + run_cmake(OLDBad2) + run_cmake(NEWBad) +endif() run_cmake(NEWGood) run_cmake(WARN-OFF) run_cmake(WARN-ON) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 69f8162..0e93cf8 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -120,7 +120,7 @@ add_RunCMake_test(CMP0081) # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode # generators ignore. The policy will have no effect on those generators. if(NOT CMAKE_GENERATOR MATCHES "Visual Studio|Xcode") - add_RunCMake_test(CMP0065) + add_RunCMake_test(CMP0065 -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}) endif() if(CMAKE_GENERATOR MATCHES "Make") add_RunCMake_test(Make -DMAKE_IS_GNU=${MAKE_IS_GNU}) @@ -248,7 +248,8 @@ add_RunCMake_test(export) add_RunCMake_test(cmake_minimum_required) add_RunCMake_test(cmake_parse_arguments) add_RunCMake_test(continue) -add_RunCMake_test(ctest_build) +add_executable(color_warning color_warning.c) +add_RunCMake_test(ctest_build -DCOLOR_WARNING=$<TARGET_FILE:color_warning>) add_RunCMake_test(ctest_cmake_error) add_RunCMake_test(ctest_configure) if(COVERAGE_COMMAND) @@ -408,7 +409,12 @@ else() set(NO_NAMELINK 0) endif() -add_RunCMake_test(install -DNO_NAMELINK=${NO_NAMELINK} -DCYGWIN=${CYGWIN}) +add_RunCMake_test(install -DNO_NAMELINK=${NO_NAMELINK} -DCYGWIN=${CYGWIN} -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID} + -DCMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN=${CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN} + -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} + -DCMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG=${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG} + -DCMAKE_EXECUTABLE_FORMAT=${CMAKE_EXECUTABLE_FORMAT}) + add_RunCMake_test(CPackCommandLine) add_RunCMake_test(CPackConfig) add_RunCMake_test(CPackInstallProperties) @@ -565,3 +571,5 @@ if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|9[0-9])") add_RunCMake_test(CSharpCustomCommand) add_RunCMake_test(CSharpReferenceImport) endif() + +add_RunCMake_test("CTestCommandExpandLists") 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/CTestCommandExpandLists/CMakeLists.txt b/Tests/RunCMake/CTestCommandExpandLists/CMakeLists.txt new file mode 100644 index 0000000..3e470a2 --- /dev/null +++ b/Tests/RunCMake/CTestCommandExpandLists/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.14) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CTestCommandExpandLists/CMakeLists.txt.in b/Tests/RunCMake/CTestCommandExpandLists/CMakeLists.txt.in new file mode 100644 index 0000000..7d56c90 --- /dev/null +++ b/Tests/RunCMake/CTestCommandExpandLists/CMakeLists.txt.in @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.14) +project(@CASE_NAME@ NONE) +include("@RunCMake_SOURCE_DIR@/@CASE_NAME@.cmake") diff --git a/Tests/RunCMake/CTestCommandExpandLists/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandExpandLists/RunCMakeTest.cmake new file mode 100644 index 0000000..7c3779e --- /dev/null +++ b/Tests/RunCMake/CTestCommandExpandLists/RunCMakeTest.cmake @@ -0,0 +1,5 @@ +include(RunCTest) + +run_ctest(expandGeneratorExpressionResult) +run_ctest(expandEmptyCommand) +run_cmake(multipleExpandOptions) diff --git a/Tests/RunCMake/CTestCommandExpandLists/compare_options.cmake b/Tests/RunCMake/CTestCommandExpandLists/compare_options.cmake new file mode 100644 index 0000000..a32e579 --- /dev/null +++ b/Tests/RunCMake/CTestCommandExpandLists/compare_options.cmake @@ -0,0 +1,14 @@ +set(range 1 2 3 4 5 6 7 8 9 10) +set(aargs "") +set(bargs "") +foreach(n IN LISTS range) + set(aval "${A${n}ARG}") + set(bval "${B${n}ARG}") + if(aval OR bval) + list(APPEND aargs "\"${aval}\"") + list(APPEND bargs "\"${bval}\"") + endif() +endforeach() +if(NOT "${aargs}" STREQUAL "${bargs}") + message(FATAL_ERROR "COMPARE_OPTIONS: \n\t${aargs} != \n\t${bargs}") +endif() diff --git a/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-result.txt b/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-result.txt new file mode 100644 index 0000000..b57e2de --- /dev/null +++ b/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-stderr.txt b/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-stderr.txt new file mode 100644 index 0000000..c656b4c --- /dev/null +++ b/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-stderr.txt @@ -0,0 +1 @@ +Unable to find executable: diff --git a/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-stdout.txt b/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-stdout.txt new file mode 100644 index 0000000..0752580 --- /dev/null +++ b/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-stdout.txt @@ -0,0 +1,13 @@ +Test project .*/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand-build +.* +Start 1: CommandExpandEmptyList +Could not find executable + +Looked in the following places: +.* +1/1 Test #1: CommandExpandEmptyList +\.+\*\*\*Not Run +[0-9.]+ sec ++ +0% tests passed, 1 tests failed out of 1 ++ +Total Test time \(real\) = +[0-9.]+ sec ++ +The following tests FAILED: +.* +1 - CommandExpandEmptyList \(Not Run\)$ diff --git a/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand.cmake b/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand.cmake new file mode 100644 index 0000000..b75828e --- /dev/null +++ b/Tests/RunCMake/CTestCommandExpandLists/expandEmptyCommand.cmake @@ -0,0 +1,10 @@ +include(CTest) + +set(argv /bin/true) +list(POP_BACK argv) + +add_test( + NAME CommandExpandEmptyList + COMMAND "$<JOIN:${argv},;>" + COMMAND_EXPAND_LISTS +) diff --git a/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-result.txt b/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-stdout.txt b/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-stdout.txt new file mode 100644 index 0000000..2f21592 --- /dev/null +++ b/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-stdout.txt @@ -0,0 +1,7 @@ +Test project .*/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult-build +.* +Start 1: CommandExpandList +1/1 Test #1: CommandExpandList +\.+ +Passed +[0-9.]+ sec ++ +100% tests passed, 0 tests failed out of 1 ++ +Total Test time \(real\) = +[0-9.]+ sec diff --git a/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult.cmake b/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult.cmake new file mode 100644 index 0000000..20608ae --- /dev/null +++ b/Tests/RunCMake/CTestCommandExpandLists/expandGeneratorExpressionResult.cmake @@ -0,0 +1,19 @@ +include(CTest) + + +set(cmp_args "1ARG=COMMAND_EXPAND_LISTS" "2ARG=test" "3ARG=outfile" + "4ARG=content") +set(AARGS "") +foreach(arg IN LISTS cmp_args) + list(APPEND AARGS "-DA${arg}") +endforeach() + + + +add_test( + NAME CommandExpandList + COMMAND ${CMAKE_COMMAND} ${AARGS} -V + "-DB$<JOIN:${cmp_args},;-DB>" + "-P" "${CMAKE_CURRENT_LIST_DIR}/compare_options.cmake" + COMMAND_EXPAND_LISTS +) diff --git a/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-result.txt b/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-stderr.txt b/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-stderr.txt new file mode 100644 index 0000000..e48513f --- /dev/null +++ b/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-stderr.txt @@ -0,0 +1,2 @@ +CMake Error at multipleExpandOptions\.cmake:3 \(add_test\): + +add_test may be given at most one COMMAND_EXPAND_LISTS\. diff --git a/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-stdout.txt b/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-stdout.txt new file mode 100644 index 0000000..55bb894 --- /dev/null +++ b/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-stdout.txt @@ -0,0 +1,2 @@ +-- Configuring incomplete, errors occurred! +See also ".*/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions-build/CMakeFiles/CMakeOutput\.log". diff --git a/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions.cmake b/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions.cmake new file mode 100644 index 0000000..dcf2dc4 --- /dev/null +++ b/Tests/RunCMake/CTestCommandExpandLists/multipleExpandOptions.cmake @@ -0,0 +1,8 @@ +include(CTest) + +add_test( + NAME MultipleExpandOptions + COMMAND /bin/true + COMMAND_EXPAND_LISTS + COMMAND_EXPAND_LISTS +) diff --git a/Tests/RunCMake/CTestCommandExpandLists/test.cmake.in b/Tests/RunCMake/CTestCommandExpandLists/test.cmake.in new file mode 100644 index 0000000..d9a8ccb --- /dev/null +++ b/Tests/RunCMake/CTestCommandExpandLists/test.cmake.in @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.14) + +set(CTEST_SITE "test-site") +set(CTEST_BUILD_NAME "test-build-name") +set(CTEST_SOURCE_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@") +set(CTEST_BINARY_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@-build") +set(CTEST_CMAKE_GENERATOR "@RunCMake_GENERATOR@") +set(CTEST_CMAKE_GENERATOR_PLATFORM "@RunCMake_GENERATOR_PLATFORM@") +set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@") +set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") + +ctest_start(Experimental) +ctest_configure() +ctest_build() +ctest_test() diff --git a/Tests/RunCMake/CTestCommandLine/FailRegexFound-check.cmake b/Tests/RunCMake/CTestCommandLine/FailRegexFound-check.cmake new file mode 100644 index 0000000..1097788 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/FailRegexFound-check.cmake @@ -0,0 +1,13 @@ +set(last_test_log "${RunCMake_TEST_BINARY_DIR}/Testing/Temporary/LastTest.log") +if(EXISTS "${last_test_log}") + file(READ "${last_test_log}" last_test_log_content) + string(REGEX REPLACE "\n+$" "" last_test_log_content "${last_test_log_content}") + if(NOT last_test_log_content MATCHES " +Test Pass Reason: +Error regular expression found in output. Regex=[[]test1]") + string(REPLACE "\n" "\n " last_test_log_content " ${last_test_log_content}") + set(RunCMake_TEST_FAILED "LastTest.log does not have expected content:\n${last_test_log_content}") + endif() +else() + set(RunCMake_TEST_FAILED "LastTest.log missing:\n ${last_test_log}") +endif() diff --git a/Tests/RunCMake/CTestCommandLine/RequiredRegexFound-check.cmake b/Tests/RunCMake/CTestCommandLine/RequiredRegexFound-check.cmake new file mode 100644 index 0000000..bde60d1 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/RequiredRegexFound-check.cmake @@ -0,0 +1,13 @@ +set(last_test_log "${RunCMake_TEST_BINARY_DIR}/Testing/Temporary/LastTest.log") +if(EXISTS "${last_test_log}") + file(READ "${last_test_log}" last_test_log_content) + string(REGEX REPLACE "\n+$" "" last_test_log_content "${last_test_log_content}") + if(NOT last_test_log_content MATCHES " +Test Pass Reason: +Required regular expression found. Regex=[[]test1]") + string(REPLACE "\n" "\n " last_test_log_content " ${last_test_log_content}") + set(RunCMake_TEST_FAILED "LastTest.log does not have expected content:\n${last_test_log_content}") + endif() +else() + set(RunCMake_TEST_FAILED "LastTest.log missing:\n ${last_test_log}") +endif() diff --git a/Tests/RunCMake/CTestCommandLine/RequiredRegexNotFound-check.cmake b/Tests/RunCMake/CTestCommandLine/RequiredRegexNotFound-check.cmake new file mode 100644 index 0000000..6d420f3 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/RequiredRegexNotFound-check.cmake @@ -0,0 +1,16 @@ +set(last_test_log "${RunCMake_TEST_BINARY_DIR}/Testing/Temporary/LastTest.log") +if(EXISTS "${last_test_log}") + file(READ "${last_test_log}" last_test_log_content) + string(REGEX REPLACE "\n+$" "" last_test_log_content "${last_test_log_content}") + if(NOT last_test_log_content MATCHES " +Test Pass Reason: +Required regular expression not found. Regex=[[]foo +toast1 +bar +]") + string(REPLACE "\n" "\n " last_test_log_content " ${last_test_log_content}") + set(RunCMake_TEST_FAILED "LastTest.log does not have expected content:\n${last_test_log_content}") + endif() +else() + set(RunCMake_TEST_FAILED "LastTest.log missing:\n ${last_test_log}") +endif() diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake index d524f41..ca2975a 100644 --- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake @@ -78,6 +78,62 @@ endfunction() run_LabelCount() +function(run_RequiredRegexFoundTest) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/RequiredRegexFound) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" " +add_test(test1 \"${CMAKE_COMMAND}\" -E echo \"test1\") +set_tests_properties(test1 PROPERTIES PASS_REGULAR_EXPRESSION \"foo;test1;bar\") +") + + run_cmake_command(RequiredRegexFound ${CMAKE_CTEST_COMMAND} -V) +endfunction() +run_RequiredRegexFoundTest() + +function(run_RequiredRegexNotFoundTest) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/RequiredRegexNotFound) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" " +add_test(test1 \"${CMAKE_COMMAND}\" -E echo \"test1\") +set_tests_properties(test1 PROPERTIES PASS_REGULAR_EXPRESSION \"foo;toast1;bar\" WILL_FAIL True) +") + + run_cmake_command(RequiredRegexNotFound ${CMAKE_CTEST_COMMAND} -V) +endfunction() +run_RequiredRegexNotFoundTest() + +function(run_FailRegexFoundTest) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/FailRegexFound) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" " +add_test(test1 \"${CMAKE_COMMAND}\" -E echo \"test1\") +set_tests_properties(test1 PROPERTIES FAIL_REGULAR_EXPRESSION \"foo;test1;bar\" WILL_FAIL True) +") + + run_cmake_command(FailRegexFound ${CMAKE_CTEST_COMMAND} -V) +endfunction() +run_FailRegexFoundTest() + +function(run_SkipRegexFoundTest) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SkipRegexFound) + set(RunCMake_TEST_NO_CLEAN 1) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" " +add_test(test1 \"${CMAKE_COMMAND}\" -E echo \"test1\") +set_tests_properties(test1 PROPERTIES SKIP_REGULAR_EXPRESSION \"test1\") +") + + run_cmake_command(SkipRegexFound ${CMAKE_CTEST_COMMAND} -V) +endfunction() +run_SkipRegexFoundTest() + function(run_SerialFailed) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SerialFailed) set(RunCMake_TEST_NO_CLEAN 1) @@ -200,7 +256,11 @@ function(run_ShowOnly) file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" " add_test(ShowOnly \"${CMAKE_COMMAND}\" -E echo) - set_tests_properties(ShowOnly PROPERTIES WILL_FAIL true _BACKTRACE_TRIPLES \"file1;1;add_test;file0;;\") + set_tests_properties(ShowOnly PROPERTIES + WILL_FAIL true + REQUIRED_FILES RequiredFileDoesNotExist + _BACKTRACE_TRIPLES \"file1;1;add_test;file0;;\" + ) add_test(ShowOnlyNotAvailable NOT_AVAILABLE) ") run_cmake_command(show-only_human ${CMAKE_CTEST_COMMAND} --show-only=human) diff --git a/Tests/RunCMake/CTestCommandLine/SkipRegexFound-check.cmake b/Tests/RunCMake/CTestCommandLine/SkipRegexFound-check.cmake new file mode 100644 index 0000000..1a2dfa3 --- /dev/null +++ b/Tests/RunCMake/CTestCommandLine/SkipRegexFound-check.cmake @@ -0,0 +1,13 @@ +set(last_test_log "${RunCMake_TEST_BINARY_DIR}/Testing/Temporary/LastTest.log") +if(EXISTS "${last_test_log}") + file(READ "${last_test_log}" last_test_log_content) + string(REGEX REPLACE "\n+$" "" last_test_log_content "${last_test_log_content}") + if(NOT last_test_log_content MATCHES " +Test Pass Reason: +Skip regular expression found in output. Regex=[[]test1]") + string(REPLACE "\n" "\n " last_test_log_content " ${last_test_log_content}") + set(RunCMake_TEST_FAILED "LastTest.log does not have expected content:\n${last_test_log_content}") + endif() +else() + set(RunCMake_TEST_FAILED "LastTest.log missing:\n ${last_test_log}") +endif() diff --git a/Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py b/Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py index 4dff90c..3ad5768 100644 --- a/Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py +++ b/Tests/RunCMake/CTestCommandLine/show-only_json-v1_check.py @@ -63,6 +63,15 @@ def check_command(c): assert is_string(c[2]) assert c[2] == "echo" +def check_reqfiles_property(p): + assert is_dict(p) + assert sorted(p.keys()) == ["name", "value"] + assert is_string(p["name"]) + assert is_list(p["value"]) + assert p["name"] == "REQUIRED_FILES" + assert len(p["value"]) == 1 + assert p["value"][0] == "RequiredFileDoesNotExist" + def check_willfail_property(p): assert is_dict(p) assert sorted(p.keys()) == ["name", "value"] @@ -81,9 +90,10 @@ def check_workingdir_property(p): def check_properties(p): assert is_list(p) - assert len(p) == 2 - check_willfail_property(p[0]) - check_workingdir_property(p[1]) + assert len(p) == 3 + check_reqfiles_property(p[0]) + check_willfail_property(p[1]) + check_workingdir_property(p[2]) def check_tests(t): assert is_list(t) diff --git a/Tests/RunCMake/CommandLine/E_false-extraargs-result.txt b/Tests/RunCMake/CommandLine/E_false-extraargs-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_false-extraargs-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_false-result.txt b/Tests/RunCMake/CommandLine/E_false-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_false-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index c9d3a4d..dd49423 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -26,6 +26,10 @@ run_cmake_command(E_echo_append ${CMAKE_COMMAND} -E echo_append) run_cmake_command(E_rename-no-arg ${CMAKE_COMMAND} -E rename) run_cmake_command(E_server-arg ${CMAKE_COMMAND} -E server --extra-arg) run_cmake_command(E_server-pipe ${CMAKE_COMMAND} -E server --pipe=) +run_cmake_command(E_true ${CMAKE_COMMAND} -E true) +run_cmake_command(E_true-extraargs ${CMAKE_COMMAND} -E true ignored) +run_cmake_command(E_false ${CMAKE_COMMAND} -E false) +run_cmake_command(E_false-extraargs ${CMAKE_COMMAND} -E false ignored) run_cmake_command(E_touch_nocreate-no-arg ${CMAKE_COMMAND} -E touch_nocreate) run_cmake_command(E_touch-nonexistent-dir ${CMAKE_COMMAND} -E touch "${RunCMake_BINARY_DIR}/touch-nonexistent-dir/foo") @@ -480,6 +484,14 @@ set(RunCMake_TEST_OPTIONS --trace-expand --warn-uninitialized) run_cmake(trace-expand-warn-uninitialized) unset(RunCMake_TEST_OPTIONS) +set(RunCMake_TEST_OPTIONS --trace-redirect=${RunCMake_BINARY_DIR}/redirected.trace) +run_cmake(trace-redirect) +unset(RunCMake_TEST_OPTIONS) + +set(RunCMake_TEST_OPTIONS --trace-redirect=/no/such/file.txt) +run_cmake(trace-redirect-nofile) +unset(RunCMake_TEST_OPTIONS) + set(RunCMake_TEST_OPTIONS -Wno-deprecated --warn-uninitialized) run_cmake(warn-uninitialized) unset(RunCMake_TEST_OPTIONS) diff --git a/Tests/RunCMake/CommandLine/trace-redirect-check.cmake b/Tests/RunCMake/CommandLine/trace-redirect-check.cmake new file mode 100644 index 0000000..1ee0e0d --- /dev/null +++ b/Tests/RunCMake/CommandLine/trace-redirect-check.cmake @@ -0,0 +1,13 @@ +file(READ ${RunCMake_SOURCE_DIR}/trace-stderr.txt expected_content) +string(REGEX REPLACE "\n+$" "" expected_content "${expected_content}") + +file(READ ${RunCMake_BINARY_DIR}/redirected.trace actual_content) +string(REGEX REPLACE "\r\n" "\n" actual_content "${actual_content}") +string(REGEX REPLACE "\n+$" "" actual_content "${actual_content}") +if(NOT "${actual_content}" MATCHES "${expected_content}") + set(RunCMake_TEST_FAILED + "Trace file content does not match that expected." + "Expected to match:\n${expected_content}\n" + "Actual content:\n${actual_content}\n" + ) +endif() diff --git a/Tests/RunCMake/CommandLine/trace-redirect-nofile-result.txt b/Tests/RunCMake/CommandLine/trace-redirect-nofile-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/trace-redirect-nofile-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/trace-redirect-nofile-stderr.txt b/Tests/RunCMake/CommandLine/trace-redirect-nofile-stderr.txt new file mode 100644 index 0000000..edb0c8e --- /dev/null +++ b/Tests/RunCMake/CommandLine/trace-redirect-nofile-stderr.txt @@ -0,0 +1 @@ +^CMake Error: Error opening trace file /no/such/file.txt: .+$ diff --git a/Tests/RunCMake/CommandLine/trace-redirect-nofile.cmake b/Tests/RunCMake/CommandLine/trace-redirect-nofile.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/CommandLine/trace-redirect-nofile.cmake diff --git a/Tests/RunCMake/CommandLine/trace-redirect-stdout.txt b/Tests/RunCMake/CommandLine/trace-redirect-stdout.txt new file mode 100644 index 0000000..775f2b5 --- /dev/null +++ b/Tests/RunCMake/CommandLine/trace-redirect-stdout.txt @@ -0,0 +1 @@ +^.*Trace will be written to .+redirected.trace.*$ diff --git a/Tests/RunCMake/CommandLine/trace-redirect.cmake b/Tests/RunCMake/CommandLine/trace-redirect.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/CommandLine/trace-redirect.cmake diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index 3096358..89f63d0 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -979,6 +979,11 @@ def gen_check_targets(c, g, inSource): "_dllExtra": False, }, { + "path": "^lib/my_interface_exe\\.imp$", + "_aixExtra": True, + "_dllExtra": False, + }, + { "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib)?my_interface_exe\\.(dll\\.a|lib)$", "_dllExtra": True, }, @@ -4928,6 +4933,10 @@ def gen_check_targets(c, g, inSource): for e in expected: e["artifacts"] = filter_list(lambda a: not a["_dllExtra"], e["artifacts"]) + if "aix" not in sys.platform: + for e in expected: + e["artifacts"] = filter_list(lambda a: not a.get("_aixExtra", False), e["artifacts"]) + return expected def check_targets(c, g, inSource): diff --git a/Tests/RunCMake/FindBoost/CMakePackage-stdout.txt b/Tests/RunCMake/FindBoost/CMakePackage-stdout.txt index 0a67488..ebd7232 100644 --- a/Tests/RunCMake/FindBoost/CMakePackage-stdout.txt +++ b/Tests/RunCMake/FindBoost/CMakePackage-stdout.txt @@ -1,2 +1,2 @@ -- Found Boost: [^ -]* \(found suitable version "1\.12345", minimum required is "1\.12345"\) found components: date_time +]* \(found suitable version "1\.12345", minimum required is "1\.12345"\) found components: date_time diff --git a/Tests/RunCMake/FindBoost/LegacyVars-LowercaseTargetPrefix-stdout.txt b/Tests/RunCMake/FindBoost/LegacyVars-LowercaseTargetPrefix-stdout.txt index a781dce..1175425 100644 --- a/Tests/RunCMake/FindBoost/LegacyVars-LowercaseTargetPrefix-stdout.txt +++ b/Tests/RunCMake/FindBoost/LegacyVars-LowercaseTargetPrefix-stdout.txt @@ -1,5 +1,5 @@ -- Found Boost: [^ -]* \(found suitable version "1\.70\.42", minimum required is "1\.70"\) found components: date_time python37 mpi_python2 * +]* \(found suitable version "1\.70\.42", minimum required is "1\.70"\) found components: date_time python37 mpi_python2 * -- Boost_FOUND: TRUE -- Boost_INCLUDE_DIRS: [^ ]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/include diff --git a/Tests/RunCMake/FindBoost/LegacyVars-TargetsDefined-stdout.txt b/Tests/RunCMake/FindBoost/LegacyVars-TargetsDefined-stdout.txt index a4e9c6a..101d60e 100644 --- a/Tests/RunCMake/FindBoost/LegacyVars-TargetsDefined-stdout.txt +++ b/Tests/RunCMake/FindBoost/LegacyVars-TargetsDefined-stdout.txt @@ -1,5 +1,5 @@ -- Found Boost: [^ -]* \(found suitable version "1\.70\.42", minimum required is "1\.70"\) found components: date_time python37 mpi_python2 * +]* \(found suitable version "1\.70\.42", minimum required is "1\.70"\) found components: date_time python37 mpi_python2 * -- Boost_FOUND: TRUE -- Boost_INCLUDE_DIRS: [^ ]*/Tests/RunCMake/FindBoost/CMakePackage[^/]*/include diff --git a/Tests/RunCMake/FindBoost/MissingTarget-stdout.txt b/Tests/RunCMake/FindBoost/MissingTarget-stdout.txt index 8e9d684..9853c01 100644 --- a/Tests/RunCMake/FindBoost/MissingTarget-stdout.txt +++ b/Tests/RunCMake/FindBoost/MissingTarget-stdout.txt @@ -1,5 +1,5 @@ -- Found Boost: [^ -]* \(found suitable version "1\.70\.42", minimum required is "1\.70"\) found components: date_time * +]* \(found suitable version "1\.70\.42", minimum required is "1\.70"\) found components: date_time * -- Boost_FOUND: TRUE -- Boost_INCLUDE_DIRS: [^ ]*/Tests/RunCMake/FindBoost/CMakePackage_MissingTarget/include diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_FILE_PREFIX-imported-target.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_FILE_PREFIX-imported-target.cmake index 34e500a..f52776e 100644 --- a/Tests/RunCMake/GeneratorExpression/TARGET_FILE_PREFIX-imported-target.cmake +++ b/Tests/RunCMake/GeneratorExpression/TARGET_FILE_PREFIX-imported-target.cmake @@ -38,7 +38,7 @@ set_property (TARGET static2 PROPERTY IMPORT_PREFIX static2_import_prefix) string (APPEND GENERATE_CONTENT "\ncheck_value (\"TARGET_FILE_PREFIX executable custom\" \"$<TARGET_FILE_PREFIX:exec2>\" \"exec2_prefix\") -check_value (\"TARGET_LINKER_FILE_PREFIX executable linker custom\" \"$<TARGET_LINKER_FILE_PREFIX:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms}>,exec2_import_prefix,exec2_prefix>\") +check_value (\"TARGET_LINKER_FILE_PREFIX executable linker custom\" \"$<TARGET_LINKER_FILE_PREFIX:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms};AIX>,exec2_import_prefix,exec2_prefix>\") check_value (\"TARGET_FILE_PREFIX shared custom\" \"$<TARGET_FILE_PREFIX:shared2>\" \"shared2_prefix\") check_value (\"TARGET_LINKER_FILE_PREFIX shared linker custom\" \"$<TARGET_LINKER_FILE_PREFIX:shared2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms}>,shared2_import_prefix,shared2_prefix>\") check_value (\"TARGET_FILE_PREFIX static custom\" \"$<TARGET_FILE_PREFIX:static2>\" \"static2_prefix\") diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_FILE_PREFIX.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_FILE_PREFIX.cmake index 6bb1e44..bef7bbf 100644 --- a/Tests/RunCMake/GeneratorExpression/TARGET_FILE_PREFIX.cmake +++ b/Tests/RunCMake/GeneratorExpression/TARGET_FILE_PREFIX.cmake @@ -38,7 +38,7 @@ set_property (TARGET static2 PROPERTY IMPORT_PREFIX static2_import_prefix) string (APPEND GENERATE_CONTENT "\ncheck_value (\"TARGET_FILE_PREFIX executable custom\" \"$<TARGET_FILE_PREFIX:exec2>\" \"exec2_prefix\") -check_value (\"TARGET_LINKER_FILE_PREFIX executable linker custom\" \"$<TARGET_LINKER_FILE_PREFIX:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms}>,exec2_import_prefix,exec2_prefix>\") +check_value (\"TARGET_LINKER_FILE_PREFIX executable linker custom\" \"$<TARGET_LINKER_FILE_PREFIX:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms};AIX>,exec2_import_prefix,exec2_prefix>\") check_value (\"TARGET_FILE_PREFIX shared custom\" \"$<TARGET_FILE_PREFIX:shared2>\" \"shared2_prefix\") check_value (\"TARGET_LINKER_FILE_PREFIX shared linker custom\" \"$<TARGET_LINKER_FILE_PREFIX:shared2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms}>,shared2_import_prefix,shared2_prefix>\") check_value (\"TARGET_FILE_PREFIX static custom\" \"$<TARGET_FILE_PREFIX:static2>\" \"static2_prefix\") diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_FILE_SUFFIX-imported-target.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_FILE_SUFFIX-imported-target.cmake index e1b7654..cefeb86 100644 --- a/Tests/RunCMake/GeneratorExpression/TARGET_FILE_SUFFIX-imported-target.cmake +++ b/Tests/RunCMake/GeneratorExpression/TARGET_FILE_SUFFIX-imported-target.cmake @@ -38,7 +38,7 @@ set_property (TARGET static2 PROPERTY IMPORT_SUFFIX static2_import_suffix) string (APPEND GENERATE_CONTENT "\ncheck_value (\"TARGET_FILE_SUFFIX executable custom\" \"$<TARGET_FILE_SUFFIX:exec2>\" \"exec2_suffix\") -check_value (\"TARGET_LINKER_FILE_SUFFIX executable linker custom\" \"$<TARGET_LINKER_FILE_SUFFIX:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms}>,exec2_import_suffix,exec2_suffix>\") +check_value (\"TARGET_LINKER_FILE_SUFFIX executable linker custom\" \"$<TARGET_LINKER_FILE_SUFFIX:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms};AIX>,exec2_import_suffix,exec2_suffix>\") check_value (\"TARGET_FILE_SUFFIX shared custom\" \"$<TARGET_FILE_SUFFIX:shared2>\" \"shared2_suffix\") check_value (\"TARGET_LINKER_FILE_SUFFIX shared linker custom\" \"$<TARGET_LINKER_FILE_SUFFIX:shared2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms}>,shared2_import_suffix,shared2_suffix>\") check_value (\"TARGET_FILE_SUFFIX static custom\" \"$<TARGET_FILE_SUFFIX:static2>\" \"static2_suffix\") diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_FILE_SUFFIX.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_FILE_SUFFIX.cmake index 78afecd..39e39fd 100644 --- a/Tests/RunCMake/GeneratorExpression/TARGET_FILE_SUFFIX.cmake +++ b/Tests/RunCMake/GeneratorExpression/TARGET_FILE_SUFFIX.cmake @@ -38,7 +38,7 @@ set_property (TARGET static2 PROPERTY IMPORT_SUFFIX static2_import_suffix) string (APPEND GENERATE_CONTENT "\ncheck_value (\"TARGET_FILE_SUFFIX executable custom\" \"$<TARGET_FILE_SUFFIX:exec2>\" \"exec2_suffix\") -check_value (\"TARGET_LINKER_FILE_SUFFIX executable linker custom\" \"$<TARGET_LINKER_FILE_SUFFIX:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms}>,exec2_import_suffix,exec2_suffix>\") +check_value (\"TARGET_LINKER_FILE_SUFFIX executable linker custom\" \"$<TARGET_LINKER_FILE_SUFFIX:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms};AIX>,exec2_import_suffix,exec2_suffix>\") check_value (\"TARGET_FILE_SUFFIX shared custom\" \"$<TARGET_FILE_SUFFIX:shared2>\" \"shared2_suffix\") check_value (\"TARGET_LINKER_FILE_SUFFIX shared linker custom\" \"$<TARGET_LINKER_FILE_SUFFIX:shared2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${win_platforms}>,shared2_import_suffix,shared2_suffix>\") check_value (\"TARGET_FILE_SUFFIX static custom\" \"$<TARGET_FILE_SUFFIX:static2>\" \"static2_suffix\") diff --git a/Tests/RunCMake/ObjectLibrary/InstallLinkedObj1-stderr.txt b/Tests/RunCMake/ObjectLibrary/InstallLinkedObj1-stderr.txt index f2f0f94..c663707 100644 --- a/Tests/RunCMake/ObjectLibrary/InstallLinkedObj1-stderr.txt +++ b/Tests/RunCMake/ObjectLibrary/InstallLinkedObj1-stderr.txt @@ -1 +1 @@ -CMake Error: install\(EXPORT "exp" ...\) includes target "UseA" which requires target "A" that is not in the export set. +CMake Error: install\(EXPORT "exp" ...\) includes target "UseA" which requires target "A" that is not in any export set. diff --git a/Tests/RunCMake/README.rst b/Tests/RunCMake/README.rst index d8b43fe..ebe40cf 100644 --- a/Tests/RunCMake/README.rst +++ b/Tests/RunCMake/README.rst @@ -55,6 +55,12 @@ but do not actually build anything. To add a test: ``<SubTest>-check.cmake`` Custom result check. + Note that when a specific platform expects differing stdout or stderr that + can be done by adding a platform specific output file. These follow the + naming convention of: + ``<SubTest>-stdout-<platform_lower_case>.txt`` + ``<SubTest>-stderr-<platform_lower_case>.txt`` + Note that trailing newlines will be stripped from actual and expected test output before matching against the stdout and stderr expressions. The code in ``<SubTest>-check.cmake`` may use variables diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index ad3f8f6..568bdf8 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -21,10 +21,20 @@ function(run_cmake test) else() set(expect_result 0) endif() + + string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} platform_name) + if(platform_name MATCHES cygwin) + #remove all additional bits from cygwin name + set(platform_name cygwin) + endif() + foreach(o out err) if(RunCMake-std${o}-file AND EXISTS ${top_src}/${RunCMake-std${o}-file}) file(READ ${top_src}/${RunCMake-std${o}-file} expect_std${o}) string(REGEX REPLACE "\n+$" "" expect_std${o} "${expect_std${o}}") + elseif(EXISTS ${top_src}/${test}-std${o}-${platform_name}.txt) + file(READ ${top_src}/${test}-std${o}-${platform_name}.txt expect_std${o}) + string(REGEX REPLACE "\n+$" "" expect_std${o} "${expect_std${o}}") elseif(EXISTS ${top_src}/${test}-std${o}.txt) file(READ ${top_src}/${test}-std${o}.txt expect_std${o}) string(REGEX REPLACE "\n+$" "" expect_std${o} "${expect_std${o}}") @@ -134,8 +144,6 @@ function(run_cmake test) "|Error kstat returned" "|Hit xcodebuild bug" "|[^\n]*xcodebuild[^\n]*warning: file type[^\n]*is based on missing file type" - "|ld: 0711-224 WARNING: Duplicate symbol: .__init_aix_libgcc_cxa_atexit" - "|ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information" "|[^\n]*is a member of multiple groups" "|[^\n]*from Time Machine by path" "|[^\n]*Bullseye Testing Technology" diff --git a/Tests/RunCMake/RuntimePath/Genex.cmake b/Tests/RunCMake/RuntimePath/Genex.cmake new file mode 100644 index 0000000..152238a --- /dev/null +++ b/Tests/RunCMake/RuntimePath/Genex.cmake @@ -0,0 +1,29 @@ +enable_language(C) + +add_library(A STATIC A.c) + +add_executable(buildge main.c) +target_link_libraries(buildge A) +set_target_properties(buildge PROPERTIES + BUILD_RPATH $<1:/opt/foo/lib> + ) + +add_executable(buildnoge main.c) +target_link_libraries(buildnoge A) +set_target_properties(buildnoge PROPERTIES + BUILD_RPATH /opt/foo/lib + ) + +add_executable(installge main.c) +target_link_libraries(installge A) +set_target_properties(installge PROPERTIES + INSTALL_RPATH $<1:/opt/foo/lib> + BUILD_WITH_INSTALL_RPATH 1 + ) + +add_executable(installnoge main.c) +target_link_libraries(installnoge A) +set_target_properties(installnoge PROPERTIES + INSTALL_RPATH /opt/foo/lib + BUILD_WITH_INSTALL_RPATH 1 + ) diff --git a/Tests/RunCMake/RuntimePath/GenexCheck.cmake b/Tests/RunCMake/RuntimePath/GenexCheck.cmake new file mode 100644 index 0000000..07dc496 --- /dev/null +++ b/Tests/RunCMake/RuntimePath/GenexCheck.cmake @@ -0,0 +1,7 @@ +file(GLOB_RECURSE files "${dir}/*") + +foreach(file IN LISTS files) + if(file MATCHES "/(build|install)(no)?ge$") + file(RPATH_CHANGE FILE "${file}" OLD_RPATH "/opt/foo/lib" NEW_RPATH "/opt/bar/lib") + endif() +endforeach() diff --git a/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake b/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake index 6f1baa1..4c9ddcd 100644 --- a/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake +++ b/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake @@ -1,32 +1,26 @@ include(RunCMake) -function(run_SymlinkImplicit) +function(run_RuntimePath name) # Use a single build tree for a few tests without cleaning. - set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/SymlinkImplicit-build) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build) set(RunCMake_TEST_NO_CLEAN 1) if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug) endif() file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") - run_cmake(SymlinkImplicit) - run_cmake_command(SymlinkImplicit-build ${CMAKE_COMMAND} --build . --config Debug) - run_cmake_command(SymlinkImplicitCheck - ${CMAKE_COMMAND} -Ddir=${RunCMake_TEST_BINARY_DIR} -P ${RunCMake_SOURCE_DIR}/SymlinkImplicitCheck.cmake) + run_cmake(${name}) + run_cmake_command(${name}-build ${CMAKE_COMMAND} --build . --config Debug) endfunction() -run_SymlinkImplicit() -function(run_Relative) - # Use a single build tree for a few tests without cleaning. - set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Relative-build) - set(RunCMake_TEST_NO_CLEAN 1) - if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) - set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug) - endif() - file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") - file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") - run_cmake(Relative) - run_cmake_command(Relative-build ${CMAKE_COMMAND} --build . --config Debug) -endfunction() -run_Relative() +run_RuntimePath(SymlinkImplicit) +run_cmake_command(SymlinkImplicitCheck + ${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/SymlinkImplicit-build -P ${RunCMake_SOURCE_DIR}/SymlinkImplicitCheck.cmake) + +run_RuntimePath(Relative) +# FIXME: Run RelativeCheck (appears to be broken currently) + +run_RuntimePath(Genex) +run_cmake_command(GenexCheck + ${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/Genex-build -P ${RunCMake_SOURCE_DIR}/GenexCheck.cmake) diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt index 0bcf886..6d72fac 100644 --- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt +++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt @@ -27,6 +27,7 @@ \* CMP0076 \* CMP0081 \* CMP0083 + \* CMP0095 Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/VS10Project/Dir/DirNested/foo_nested.cpp b/Tests/RunCMake/VS10Project/Dir/DirNested/foo_nested.cpp new file mode 100644 index 0000000..3695dc9 --- /dev/null +++ b/Tests/RunCMake/VS10Project/Dir/DirNested/foo_nested.cpp @@ -0,0 +1,3 @@ +void foo() +{ +} diff --git a/Tests/RunCMake/VS10Project/Dir/foo.cpp b/Tests/RunCMake/VS10Project/Dir/foo.cpp new file mode 100644 index 0000000..3695dc9 --- /dev/null +++ b/Tests/RunCMake/VS10Project/Dir/foo.cpp @@ -0,0 +1,3 @@ +void foo() +{ +} diff --git a/Tests/RunCMake/VS10Project/Prefixed/PrefixedNested/bar_nested.cpp b/Tests/RunCMake/VS10Project/Prefixed/PrefixedNested/bar_nested.cpp new file mode 100644 index 0000000..3695dc9 --- /dev/null +++ b/Tests/RunCMake/VS10Project/Prefixed/PrefixedNested/bar_nested.cpp @@ -0,0 +1,3 @@ +void foo() +{ +} diff --git a/Tests/RunCMake/VS10Project/Prefixed/bar.cpp b/Tests/RunCMake/VS10Project/Prefixed/bar.cpp new file mode 100644 index 0000000..b72a1a5 --- /dev/null +++ b/Tests/RunCMake/VS10Project/Prefixed/bar.cpp @@ -0,0 +1,3 @@ +void bar() +{ +} diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake index 27b81b7..5ca069a 100644 --- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake +++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake @@ -5,6 +5,7 @@ run_cmake(VsCSharpCompilerOpts) run_cmake(ExplicitCMakeLists) run_cmake(RuntimeLibrary) run_cmake(SourceGroupCMakeLists) +run_cmake(SourceGroupTreeCMakeLists) run_cmake(VsConfigurationType) run_cmake(VsTargetsFileReferences) @@ -22,6 +23,8 @@ run_cmake(VsSdkDirectories) run_cmake(VsGlobals) run_cmake(VsProjectImport) run_cmake(VsPackageReferences) +run_cmake(VsDpiAware) +run_cmake(VsDpiAwareBadParam) if(CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.05) run_cmake(VsJustMyCode) diff --git a/Tests/RunCMake/VS10Project/SourceGroupCMakeLists-check.cmake b/Tests/RunCMake/VS10Project/SourceGroupCMakeLists-check.cmake index c2a94bb..616f38b 100644 --- a/Tests/RunCMake/VS10Project/SourceGroupCMakeLists-check.cmake +++ b/Tests/RunCMake/VS10Project/SourceGroupCMakeLists-check.cmake @@ -4,30 +4,8 @@ if(NOT EXISTS "${vcFiltersFile}") return() endif() -set(foundFileFilter 0) -set(foundFilter 0) file(STRINGS "${vcFiltersFile}" lines) -foreach(line IN LISTS lines) - if(line MATCHES "<Filter>CMakeListsSourceGroup</Filter>") - set(rule "${CMAKE_MATCH_1}") - if(foundFileFilter) - set(RunCMake_TEST_FAILED "Multiple files listed with filter for CMakeListsSourceGroup.") - return() - endif() - set(foundFileFilter 1) - endif() - if(line MATCHES "<Filter.*Include=\"CMakeListsSourceGroup\"") - set(rule "${CMAKE_MATCH_1}") - if(foundFilter) - set(RunCMake_TEST_FAILED "Multiple copies of CMakeListsSourceGroup filter listed.") - return() - endif() - set(foundFilter 1) - endif() -endforeach() -if(NOT foundFileFilter) - set(RunCMake_TEST_FAILED "File filter for CMakeListsSourceGroup not found.") -endif() -if(NOT foundFilter) - set(RunCMake_TEST_FAILED "Filter CMakeListsSourceGroup not found.") -endif() + +include(${RunCMake_TEST_SOURCE_DIR}/SourceGroupHelpers.cmake) + +find_source_group("${lines}" CMakeListsSourceGroup) diff --git a/Tests/RunCMake/VS10Project/SourceGroupHelpers.cmake b/Tests/RunCMake/VS10Project/SourceGroupHelpers.cmake new file mode 100644 index 0000000..c82a66e --- /dev/null +++ b/Tests/RunCMake/VS10Project/SourceGroupHelpers.cmake @@ -0,0 +1,35 @@ +function(find_source_group LINES NAME) + set(foundFileFilter 0) + set(foundFilter 0) + foreach(line IN LISTS LINES) + if(line MATCHES "<Filter>${NAME}</Filter>") + if(foundFileFilter) + set(RunCMake_TEST_FAILED "Multiple files listed with filter for ${NAME}." PARENT_SCOPE) + set(FILTER_FOUND 0 PARENT_SCOPE) + return() + endif() + set(foundFileFilter 1) + endif() + if(line MATCHES "<Filter.*Include=\"${NAME}\"") + if(foundFilter) + set(RunCMake_TEST_FAILED "Multiple copies of ${NAME} filter listed." PARENT_SCOPE) + set(FILTER_FOUND 0 PARENT_SCOPE) + return() + endif() + set(foundFilter 1) + endif() + endforeach() + + if(NOT foundFileFilter) + set(RunCMake_TEST_FAILED "File filter for ${NAME} not found." PARENT_SCOPE) + set(FILTER_FOUND 0 PARENT_SCOPE) + return() + endif() + if(NOT foundFilter) + set(RunCMake_TEST_FAILED "Filter ${NAME} not found." PARENT_SCOPE) + set(FILTER_FOUND 0 PARENT_SCOPE) + return() + endif() + + set(FILTER_FOUND 1 PARENT_SCOPE) +endfunction() diff --git a/Tests/RunCMake/VS10Project/SourceGroupTreeCMakeLists-check.cmake b/Tests/RunCMake/VS10Project/SourceGroupTreeCMakeLists-check.cmake new file mode 100644 index 0000000..655120a --- /dev/null +++ b/Tests/RunCMake/VS10Project/SourceGroupTreeCMakeLists-check.cmake @@ -0,0 +1,25 @@ +cmake_policy(SET CMP0011 NEW) + +set(vcFiltersFile "${RunCMake_TEST_BINARY_DIR}/SourceGroupTree.vcxproj.filters") +if(NOT EXISTS "${vcFiltersFile}") + set(RunCMake_TEST_FAILED "Filters file ${vcFiltersFile} does not exist.") + return() +endif() + +file(STRINGS "${vcFiltersFile}" lines) + +include(${RunCMake_TEST_SOURCE_DIR}/SourceGroupHelpers.cmake) + +set(SOURCE_GROUPS_TO_FIND + "Dir" + "Dir\\DirNested" + "SourcesPrefix" + "SourcesPrefix\\PrefixedNested" +) + +foreach(GROUP_NAME IN LISTS ${SOURCE_GROUPS_TO_FIND}) + find_source_group("${lines}" ${GROUP_NAME}) + if(NOT ${FILTER_FOUND}) + return() + endif() +endforeach() diff --git a/Tests/RunCMake/VS10Project/SourceGroupTreeCMakeLists.cmake b/Tests/RunCMake/VS10Project/SourceGroupTreeCMakeLists.cmake new file mode 100644 index 0000000..83c87a9 --- /dev/null +++ b/Tests/RunCMake/VS10Project/SourceGroupTreeCMakeLists.cmake @@ -0,0 +1,16 @@ +set(CMAKE_CONFIGURATION_TYPES Debug) + +set(SRC_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/Dir/foo.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Dir/DirNested/foo_nested.cpp +) + +set(PREFIXED_SRC_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/Prefixed/bar.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Prefixed/PrefixedNested/bar_nested.cpp +) + +add_custom_target(SourceGroupTree SOURCES ${SRC_FILES} ${PREFIXED_SRC_FILES}) + +source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SRC_FILES}) +source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/Prefixed PREFIX SourcesPrefix FILES ${PREFIXED_SRC_FILES}) diff --git a/Tests/RunCMake/VS10Project/VsDpiAware-check.cmake b/Tests/RunCMake/VS10Project/VsDpiAware-check.cmake new file mode 100644 index 0000000..fbb64f0 --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsDpiAware-check.cmake @@ -0,0 +1,41 @@ +macro(VSDpiAware_check tgt dpiaware_match_expect) + set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/${tgt}.vcxproj") + if(NOT EXISTS "${vcProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not exist.") + return() + endif() + + set(HAVE_DPIAWARE_MATCH 0) + set(IN_MANIFEST_SETTINGS 0) + + file(STRINGS "${vcProjectFile}" lines) + foreach(line IN LISTS lines) + if(line MATCHES "^ *<Manifest>") + set(IN_MANIFEST_SETTINGS 1) + elseif(line MATCHES "^ *</Manifest>") + set(IN_MANIFEST_SETTINGS 0) + elseif(IN_MANIFEST_SETTINGS AND (line MATCHES "^ *<EnableDpiAwareness>([^<>]+)</EnableDpiAwareness>")) + set(dpiaware_match_actual "${CMAKE_MATCH_1}") + if(NOT "${dpiaware_match_actual}" STREQUAL "${dpiaware_match_expect}") + set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj has <EnableDpiAwareness> '${dpiaware_match_actual}', not '${dpiaware_match_expect}'.") + return() + endif() + set(HAVE_DPIAWARE_MATCH 1) + break() + endif() + endforeach() + + if(NOT HAVE_DPIAWARE_MATCH AND NOT "${dpiaware_match_expect}" STREQUAL "") + set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not have a <EnableDpiAwareness> property group.") + return() + endif() +endmacro() + +VSDpiAware_check(DPIAWARE-default-C "") +VSDpiAware_check(DPIAWARE-default-CXX "") +VSDpiAware_check(DPIAWARE-TGT-PERMONITOR-C "PerMonitorHighDPIAware") +VSDpiAware_check(DPIAWARE-TGT-PERMONITOR-CXX "PerMonitorHighDPIAware") +VSDpiAware_check(DPIAWARE-TGT-ON-C "true") +VSDpiAware_check(DPIAWARE-TGT-ON-CXX "true") +VSDpiAware_check(DPIAWARE-TGT-OFF-C "false") +VSDpiAware_check(DPIAWARE-TGT-OFF-CXX "false") diff --git a/Tests/RunCMake/VS10Project/VsDpiAware.cmake b/Tests/RunCMake/VS10Project/VsDpiAware.cmake new file mode 100644 index 0000000..74e3d21 --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsDpiAware.cmake @@ -0,0 +1,19 @@ +set(CMAKE_CONFIGURATION_TYPES Debug) +enable_language(C) +enable_language(CXX) + +add_executable(DPIAWARE-default-C empty.c) +add_executable(DPIAWARE-default-CXX empty.cxx) + +add_executable(DPIAWARE-TGT-PERMONITOR-C empty.c) +set_property(TARGET DPIAWARE-TGT-PERMONITOR-C PROPERTY VS_DPI_AWARE "PerMonitor") +add_executable(DPIAWARE-TGT-PERMONITOR-CXX empty.cxx) +set_property(TARGET DPIAWARE-TGT-PERMONITOR-CXX PROPERTY VS_DPI_AWARE "PerMonitor") +add_executable(DPIAWARE-TGT-ON-C empty.c) +set_property(TARGET DPIAWARE-TGT-ON-C PROPERTY VS_DPI_AWARE ON) +add_executable(DPIAWARE-TGT-ON-CXX empty.cxx) +set_property(TARGET DPIAWARE-TGT-ON-CXX PROPERTY VS_DPI_AWARE ON) +add_executable(DPIAWARE-TGT-OFF-C empty.c) +set_property(TARGET DPIAWARE-TGT-OFF-C PROPERTY VS_DPI_AWARE OFF) +add_executable(DPIAWARE-TGT-OFF-CXX empty.cxx) +set_property(TARGET DPIAWARE-TGT-OFF-CXX PROPERTY VS_DPI_AWARE OFF) diff --git a/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-result.txt b/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-stderr.txt b/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-stderr.txt new file mode 100644 index 0000000..95fc5ca --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsDpiAwareBadParam-stderr.txt @@ -0,0 +1,3 @@ +CMake Error: Bad parameter for VS_DPI_AWARE: Bar +CMake Error: Bad parameter for VS_DPI_AWARE: Foo +CMake Generate step failed. Build files cannot be regenerated correctly. diff --git a/Tests/RunCMake/VS10Project/VsDpiAwareBadParam.cmake b/Tests/RunCMake/VS10Project/VsDpiAwareBadParam.cmake new file mode 100644 index 0000000..e05452b --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsDpiAwareBadParam.cmake @@ -0,0 +1,8 @@ +set(CMAKE_CONFIGURATION_TYPES Debug) +enable_language(C) +enable_language(CXX) + +add_executable(DPIAWARE-TGT-BADPARAM-C empty.c) +set_property(TARGET DPIAWARE-TGT-BADPARAM-C PROPERTY VS_DPI_AWARE "Foo") +add_executable(DPIAWARE-TGT-BADPARAM-CXX empty.cxx) +set_property(TARGET DPIAWARE-TGT-BADPARAM-CXX PROPERTY VS_DPI_AWARE "Bar") diff --git a/Tests/RunCMake/VS10Project/VsPackageReferences-check.cmake b/Tests/RunCMake/VS10Project/VsPackageReferences-check.cmake index 4ff5327..512a1c9 100644 --- a/Tests/RunCMake/VS10Project/VsPackageReferences-check.cmake +++ b/Tests/RunCMake/VS10Project/VsPackageReferences-check.cmake @@ -25,7 +25,7 @@ foreach(i 1 2) if(line MATCHES "^ *<PackageReference .* Version=\"${testVersion}\".*>$") set(Library${i}Found TRUE) message(STATUS "foo.vcxproj is using package reference ${testLibrary} with version ${testVersion}") - elseif() + else() message(STATUS "foo.vcxproj failed to define reference ${testLibrary} with version ${testVersion}") set(Library${i}Found FALSE) endif() diff --git a/Tests/RunCMake/VS10ProjectWinCE/VsCEDebuggerDeploy-check.cmake b/Tests/RunCMake/VS10ProjectWinCE/VsCEDebuggerDeploy-check.cmake index dab1c33..b1deb99 100644 --- a/Tests/RunCMake/VS10ProjectWinCE/VsCEDebuggerDeploy-check.cmake +++ b/Tests/RunCMake/VS10ProjectWinCE/VsCEDebuggerDeploy-check.cmake @@ -14,6 +14,9 @@ endif() set(FoundCEAdditionalFiles FALSE) set(FoundRemoteDirectory FALSE) set(FoundToolsVersion4 FALSE) +set(FoundEnableRedirectPlatform FALSE) +set(FoundRedirectPlatformValue FALSE) + file(STRINGS "${vcProjectFile}" lines) foreach(line IN LISTS lines) @@ -23,6 +26,10 @@ foreach(line IN LISTS lines) set(FoundRemoteDirectory TRUE) elseif(line MATCHES " *<Project +.*ToolsVersion=\"4.0\".*> *$") set(FoundToolsVersion4 TRUE) + elseif(line MATCHES "^ *<EnableRedirectPlatform>true</EnableRedirectPlatform> *$") + set(FoundEnableRedirectPlatform TRUE) + elseif(line MATCHES "^ *<RedirectPlatformValue>.+</RedirectPlatformValue> *$") + set(FoundRedirectPlatformValue TRUE) endif() endforeach() @@ -41,6 +48,16 @@ if(NOT FoundToolsVersion4) return() endif() +if(NOT FoundEnableRedirectPlatform) + set(RunCMake_TEST_FAILED "Failed to find EnableRedirectPlatform true property.") + return() +endif() + +if(NOT FoundRedirectPlatformValue) + set(RunCMake_TEST_FAILED "Failed to find RedirectPlatformValue property.") + return() +endif() + # # Test solution file deployment items. # diff --git a/Tests/RunCMake/add_library/UNKNOWNwithOnlyObjectSources-stderr.txt b/Tests/RunCMake/add_library/UNKNOWNwithOnlyObjectSources-stderr.txt index e332281..838992b 100644 --- a/Tests/RunCMake/add_library/UNKNOWNwithOnlyObjectSources-stderr.txt +++ b/Tests/RunCMake/add_library/UNKNOWNwithOnlyObjectSources-stderr.txt @@ -1,4 +1,4 @@ ^CMake Error at UNKNOWNwithOnlyObjectSources.cmake:[0-9]+ \(target_sources\): - target_sources called with non-compilable target type + target_sources may only set INTERFACE properties on IMPORTED targets Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/color_warning.c b/Tests/RunCMake/color_warning.c new file mode 100644 index 0000000..831abd9 --- /dev/null +++ b/Tests/RunCMake/color_warning.c @@ -0,0 +1,7 @@ +#include <stdio.h> +int main(void) +{ + printf( + "/tmp/hello.c:3:2: \033[35mwarning:\033[0m Hello, World! [-W#warnings]\n"); + return 0; +} diff --git a/Tests/RunCMake/ctest_build/IgnoreColor-stdout.txt b/Tests/RunCMake/ctest_build/IgnoreColor-stdout.txt new file mode 100644 index 0000000..cd1720f --- /dev/null +++ b/Tests/RunCMake/ctest_build/IgnoreColor-stdout.txt @@ -0,0 +1,2 @@ + 0 Compiler errors + 1 Compiler warnings diff --git a/Tests/RunCMake/ctest_build/RunCMakeTest.cmake b/Tests/RunCMake/ctest_build/RunCMakeTest.cmake index 1092d2a..b2e562a 100644 --- a/Tests/RunCMake/ctest_build/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_build/RunCMakeTest.cmake @@ -1,6 +1,8 @@ include(RunCTest) set(CASE_CTEST_BUILD_ARGS "") +set(RunCMake_USE_LAUNCHERS TRUE) +set(RunCMake_USE_CUSTOM_BUILD_COMMAND FALSE) function(run_ctest_build CASE_NAME) set(CASE_CTEST_BUILD_ARGS "${ARGN}") @@ -45,3 +47,9 @@ function(run_BuildChangeId) run_ctest(BuildChangeId) endfunction() run_BuildChangeId() + +set(RunCMake_USE_LAUNCHERS FALSE) +set(RunCMake_USE_CUSTOM_BUILD_COMMAND TRUE) +set(RunCMake_BUILD_COMMAND "${COLOR_WARNING}") +run_ctest(IgnoreColor) +unset(RunCMake_BUILD_COMMAND) diff --git a/Tests/RunCMake/ctest_build/test.cmake.in b/Tests/RunCMake/ctest_build/test.cmake.in index 6f15ec9..9f7fa13 100644 --- a/Tests/RunCMake/ctest_build/test.cmake.in +++ b/Tests/RunCMake/ctest_build/test.cmake.in @@ -9,7 +9,10 @@ set(CTEST_CMAKE_GENERATOR "@RunCMake_GENERATOR@") set(CTEST_CMAKE_GENERATOR_PLATFORM "@RunCMake_GENERATOR_PLATFORM@") set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@") set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") -set(CTEST_USE_LAUNCHERS TRUE) +set(CTEST_USE_LAUNCHERS "@RunCMake_USE_LAUNCHERS@") +if (@RunCMake_USE_CUSTOM_BUILD_COMMAND@) + set(CTEST_BUILD_COMMAND "\"@RunCMake_BUILD_COMMAND@\"") +endif() set(ctest_build_args "@CASE_CTEST_BUILD_ARGS@") ctest_start(Experimental) diff --git a/Tests/RunCMake/ctest_start/AppendDifferentGroup-stderr.txt b/Tests/RunCMake/ctest_start/AppendDifferentGroup-stderr.txt new file mode 100644 index 0000000..9e493a6 --- /dev/null +++ b/Tests/RunCMake/ctest_start/AppendDifferentGroup-stderr.txt @@ -0,0 +1 @@ +^Group given in TAG does not match group given in ctest_start\(\)$ diff --git a/Tests/RunCMake/ctest_start/AppendDifferentGroup-stdout.txt b/Tests/RunCMake/ctest_start/AppendDifferentGroup-stdout.txt new file mode 100644 index 0000000..5f83653 --- /dev/null +++ b/Tests/RunCMake/ctest_start/AppendDifferentGroup-stdout.txt @@ -0,0 +1,8 @@ +Run dashboard with to-be-determined model + Source directory: .*/Tests/RunCMake/ctest_start/AppendDifferentGroup + Build directory: .*/Tests/RunCMake/ctest_start/AppendDifferentGroup-build + Group: ExperimentalDifferent + Site: test-site + Build name: test-build-name + Use existing tag: 19551112-2204 - ExperimentalDifferent + Use ExperimentalDifferent tag: [0-9-]+ diff --git a/Tests/RunCMake/ctest_start/AppendDifferentTrack-stderr.txt b/Tests/RunCMake/ctest_start/AppendDifferentTrack-stderr.txt index 0d6d19d..9e493a6 100644 --- a/Tests/RunCMake/ctest_start/AppendDifferentTrack-stderr.txt +++ b/Tests/RunCMake/ctest_start/AppendDifferentTrack-stderr.txt @@ -1 +1 @@ -^Track given in TAG does not match track given in ctest_start\(\)$ +^Group given in TAG does not match group given in ctest_start\(\)$ diff --git a/Tests/RunCMake/ctest_start/AppendDifferentTrack-stdout.txt b/Tests/RunCMake/ctest_start/AppendDifferentTrack-stdout.txt index 25085ef..022e2ec 100644 --- a/Tests/RunCMake/ctest_start/AppendDifferentTrack-stdout.txt +++ b/Tests/RunCMake/ctest_start/AppendDifferentTrack-stdout.txt @@ -1,7 +1,7 @@ Run dashboard with to-be-determined model Source directory: .*/Tests/RunCMake/ctest_start/AppendDifferentTrack Build directory: .*/Tests/RunCMake/ctest_start/AppendDifferentTrack-build - Track: ExperimentalDifferent + Group: ExperimentalDifferent Site: test-site Build name: test-build-name Use existing tag: 19551112-2204 - ExperimentalDifferent diff --git a/Tests/RunCMake/ctest_start/MissingGroupArg-result.txt b/Tests/RunCMake/ctest_start/MissingGroupArg-result.txt new file mode 100644 index 0000000..b57e2de --- /dev/null +++ b/Tests/RunCMake/ctest_start/MissingGroupArg-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_start/MissingGroupArg-stderr.txt b/Tests/RunCMake/ctest_start/MissingGroupArg-stderr.txt new file mode 100644 index 0000000..e0480f6 --- /dev/null +++ b/Tests/RunCMake/ctest_start/MissingGroupArg-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error at .*/Tests/RunCMake/ctest_start/MissingGroupArg/test\.cmake:[0-9]+ \(ctest_start\): + ctest_start GROUP argument missing group name$ diff --git a/Tests/RunCMake/ctest_start/MissingGroupArgAppend-result.txt b/Tests/RunCMake/ctest_start/MissingGroupArgAppend-result.txt new file mode 100644 index 0000000..b57e2de --- /dev/null +++ b/Tests/RunCMake/ctest_start/MissingGroupArgAppend-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_start/MissingGroupArgAppend-stderr.txt b/Tests/RunCMake/ctest_start/MissingGroupArgAppend-stderr.txt new file mode 100644 index 0000000..8ae53ff --- /dev/null +++ b/Tests/RunCMake/ctest_start/MissingGroupArgAppend-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error at .*/Tests/RunCMake/ctest_start/MissingGroupArgAppend/test\.cmake:[0-9]+ \(ctest_start\): + ctest_start GROUP argument missing group name$ diff --git a/Tests/RunCMake/ctest_start/MissingGroupArgQuiet-result.txt b/Tests/RunCMake/ctest_start/MissingGroupArgQuiet-result.txt new file mode 100644 index 0000000..b57e2de --- /dev/null +++ b/Tests/RunCMake/ctest_start/MissingGroupArgQuiet-result.txt @@ -0,0 +1 @@ +(-1|255) diff --git a/Tests/RunCMake/ctest_start/MissingGroupArgQuiet-stderr.txt b/Tests/RunCMake/ctest_start/MissingGroupArgQuiet-stderr.txt new file mode 100644 index 0000000..c4f8900 --- /dev/null +++ b/Tests/RunCMake/ctest_start/MissingGroupArgQuiet-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error at .*/Tests/RunCMake/ctest_start/MissingGroupArgQuiet/test\.cmake:[0-9]+ \(ctest_start\): + ctest_start GROUP argument missing group name$ diff --git a/Tests/RunCMake/ctest_start/MissingTrackArg-stderr.txt b/Tests/RunCMake/ctest_start/MissingTrackArg-stderr.txt index 7b42bc9..2a72a83 100644 --- a/Tests/RunCMake/ctest_start/MissingTrackArg-stderr.txt +++ b/Tests/RunCMake/ctest_start/MissingTrackArg-stderr.txt @@ -1,2 +1,2 @@ ^CMake Error at .*/Tests/RunCMake/ctest_start/MissingTrackArg/test\.cmake:[0-9]+ \(ctest_start\): - ctest_start TRACK argument missing track name$ + ctest_start TRACK argument missing group name$ diff --git a/Tests/RunCMake/ctest_start/MissingTrackArgAppend-stderr.txt b/Tests/RunCMake/ctest_start/MissingTrackArgAppend-stderr.txt index 695bfad..7ff82ab 100644 --- a/Tests/RunCMake/ctest_start/MissingTrackArgAppend-stderr.txt +++ b/Tests/RunCMake/ctest_start/MissingTrackArgAppend-stderr.txt @@ -1,2 +1,2 @@ ^CMake Error at .*/Tests/RunCMake/ctest_start/MissingTrackArgAppend/test\.cmake:[0-9]+ \(ctest_start\): - ctest_start TRACK argument missing track name$ + ctest_start TRACK argument missing group name$ diff --git a/Tests/RunCMake/ctest_start/MissingTrackArgQuiet-stderr.txt b/Tests/RunCMake/ctest_start/MissingTrackArgQuiet-stderr.txt index 9438522..c23b1bf 100644 --- a/Tests/RunCMake/ctest_start/MissingTrackArgQuiet-stderr.txt +++ b/Tests/RunCMake/ctest_start/MissingTrackArgQuiet-stderr.txt @@ -1,2 +1,2 @@ ^CMake Error at .*/Tests/RunCMake/ctest_start/MissingTrackArgQuiet/test\.cmake:[0-9]+ \(ctest_start\): - ctest_start TRACK argument missing track name$ + ctest_start TRACK argument missing group name$ diff --git a/Tests/RunCMake/ctest_start/NoAppendDifferentGroup-stdout.txt b/Tests/RunCMake/ctest_start/NoAppendDifferentGroup-stdout.txt new file mode 100644 index 0000000..13a3883 --- /dev/null +++ b/Tests/RunCMake/ctest_start/NoAppendDifferentGroup-stdout.txt @@ -0,0 +1,7 @@ +Run dashboard with model Experimental + Source directory: .*/Tests/RunCMake/ctest_start/NoAppendDifferentGroup + Build directory: .*/Tests/RunCMake/ctest_start/NoAppendDifferentGroup-build + Group: ExperimentalDifferent + Site: test-site + Build name: test-build-name + Use ExperimentalDifferent tag: [0-9-]+ diff --git a/Tests/RunCMake/ctest_start/NoAppendDifferentTrack-stdout.txt b/Tests/RunCMake/ctest_start/NoAppendDifferentTrack-stdout.txt index 20a29be..c511e0d 100644 --- a/Tests/RunCMake/ctest_start/NoAppendDifferentTrack-stdout.txt +++ b/Tests/RunCMake/ctest_start/NoAppendDifferentTrack-stdout.txt @@ -1,7 +1,7 @@ Run dashboard with model Experimental Source directory: .*/Tests/RunCMake/ctest_start/NoAppendDifferentTrack Build directory: .*/Tests/RunCMake/ctest_start/NoAppendDifferentTrack-build - Track: ExperimentalDifferent + Group: ExperimentalDifferent Site: test-site Build name: test-build-name Use ExperimentalDifferent tag: [0-9-]+ diff --git a/Tests/RunCMake/ctest_start/RunCMakeTest.cmake b/Tests/RunCMake/ctest_start/RunCMakeTest.cmake index 905ad00..da85b39 100644 --- a/Tests/RunCMake/ctest_start/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_start/RunCMakeTest.cmake @@ -26,18 +26,24 @@ run_ctest_start(WriteModelToTagExperimental Experimental QUIET) run_ctest_start(WriteModelToTagContinuous Continuous QUIET) run_ctest_start(WriteModelToTagNightly Nightly QUIET) run_ctest_start(WriteModelToTagNoMatchingTrack Continuous TRACK SomeWeirdTrackName QUIET) +run_ctest_start(WriteModelToTagNoMatchingGroup Continuous GROUP SomeWeirdTrackName QUIET) run_ctest_start(AppendSameModel Continuous APPEND) run_ctest_start(AppendDifferentModel Experimental APPEND) run_ctest_start(AppendNoModel APPEND) run_ctest_start(AppendDifferentTrack TRACK ExperimentalDifferent APPEND) +run_ctest_start(AppendDifferentGroup GROUP ExperimentalDifferent APPEND) run_ctest_start(NoAppendDifferentTrack Experimental TRACK ExperimentalDifferent) +run_ctest_start(NoAppendDifferentGroup Experimental GROUP ExperimentalDifferent) run_ctest_start(AppendNoMatchingTrack Continuous APPEND) run_ctest_start(AppendOldContinuous Continuous APPEND) run_ctest_start(AppendOldNoModel APPEND) run_ctest_start(NoModel QUIET) run_ctest_start(MissingTrackArg Experimental TRACK) +run_ctest_start(MissingGroupArg Experimental GROUP) run_ctest_start(MissingTrackArgAppend Experimental TRACK APPEND) +run_ctest_start(MissingGroupArgAppend Experimental GROUP APPEND) run_ctest_start(MissingTrackArgQuiet Experimental TRACK QUIET) +run_ctest_start(MissingGroupArgQuiet Experimental GROUP QUIET) run_ctest_start(TooManyArgs Experimental ${RunCMake_BINARY_DIR}/TooManyArgs-build ${RunCMake_BINARY_DIR}/TooManyArgs-build diff --git a/Tests/RunCMake/ctest_start/WriteModelToTagNoMatchingGroup-check.cmake b/Tests/RunCMake/ctest_start/WriteModelToTagNoMatchingGroup-check.cmake new file mode 100644 index 0000000..bd2862d --- /dev/null +++ b/Tests/RunCMake/ctest_start/WriteModelToTagNoMatchingGroup-check.cmake @@ -0,0 +1 @@ +check_tag_contents("^[0-9-]+\nSomeWeirdTrackName\nContinuous\n$") diff --git a/Tests/RunCMake/export/DependOnDoubleExport-result.txt b/Tests/RunCMake/export/DependOnDoubleExport-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/export/DependOnDoubleExport-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/export/DependOnDoubleExport-stderr.txt b/Tests/RunCMake/export/DependOnDoubleExport-stderr.txt new file mode 100644 index 0000000..b78c7e4 --- /dev/null +++ b/Tests/RunCMake/export/DependOnDoubleExport-stderr.txt @@ -0,0 +1,13 @@ +CMake Error in CMakeLists.txt: + export called with target "exported" which requires target "doubleexported" + that is not in this export set, but in multiple other export sets: + .*/Tests/RunCMake/export/DependOnDoubleExport-build/exportset.cmake, + .*/Tests/RunCMake/export/DependOnDoubleExport-build/manual.cmake. + + + An exported target cannot depend upon another target which is exported + multiple times. Consider consolidating the exports of the "doubleexported" + target to a single export. + + +CMake Generate step failed. Build files cannot be regenerated correctly. diff --git a/Tests/RunCMake/export/DependOnDoubleExport.cmake b/Tests/RunCMake/export/DependOnDoubleExport.cmake new file mode 100644 index 0000000..8d108d7 --- /dev/null +++ b/Tests/RunCMake/export/DependOnDoubleExport.cmake @@ -0,0 +1,7 @@ +add_library(doubleexported INTERFACE) +install(TARGETS doubleexported EXPORT exportset) +export(TARGETS doubleexported FILE "${CMAKE_CURRENT_BINARY_DIR}/manual.cmake") +export(EXPORT exportset FILE "${CMAKE_CURRENT_BINARY_DIR}/exportset.cmake") +add_library(exported INTERFACE) +target_link_libraries(exported INTERFACE doubleexported) +export(TARGETS exported FILE "${CMAKE_CURRENT_BINARY_DIR}/exports.cmake") diff --git a/Tests/RunCMake/export/DependOnNotExport-result.txt b/Tests/RunCMake/export/DependOnNotExport-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/export/DependOnNotExport-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/export/DependOnNotExport-stderr.txt b/Tests/RunCMake/export/DependOnNotExport-stderr.txt new file mode 100644 index 0000000..80f5758 --- /dev/null +++ b/Tests/RunCMake/export/DependOnNotExport-stderr.txt @@ -0,0 +1,6 @@ +CMake Error in CMakeLists.txt: + export called with target "exported" which requires target "notexported" + that is not in any export set. + + +CMake Generate step failed. Build files cannot be regenerated correctly. diff --git a/Tests/RunCMake/export/DependOnNotExport.cmake b/Tests/RunCMake/export/DependOnNotExport.cmake new file mode 100644 index 0000000..06c1ad9 --- /dev/null +++ b/Tests/RunCMake/export/DependOnNotExport.cmake @@ -0,0 +1,4 @@ +add_library(notexported INTERFACE) +add_library(exported INTERFACE) +target_link_libraries(exported INTERFACE notexported) +export(TARGETS exported FILE "${CMAKE_CURRENT_BINARY_DIR}/exports.cmake") diff --git a/Tests/RunCMake/export/RunCMakeTest.cmake b/Tests/RunCMake/export/RunCMakeTest.cmake index 97a0ca6..4d2f217 100644 --- a/Tests/RunCMake/export/RunCMakeTest.cmake +++ b/Tests/RunCMake/export/RunCMakeTest.cmake @@ -10,3 +10,5 @@ run_cmake(ForbiddenToExportInterfaceProperties) run_cmake(ForbiddenToExportImportedProperties) run_cmake(ForbiddenToExportPropertyWithGenExp) run_cmake(ExportPropertiesUndefined) +run_cmake(DependOnNotExport) +run_cmake(DependOnDoubleExport) diff --git a/Tests/RunCMake/find_file/FromPATHEnv-stdout-cygwin.txt b/Tests/RunCMake/find_file/FromPATHEnv-stdout-cygwin.txt new file mode 100644 index 0000000..6912bdf --- /dev/null +++ b/Tests/RunCMake/find_file/FromPATHEnv-stdout-cygwin.txt @@ -0,0 +1,9 @@ +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' diff --git a/Tests/RunCMake/find_file/FromPATHEnv-stdout-windows.txt b/Tests/RunCMake/find_file/FromPATHEnv-stdout-windows.txt new file mode 100644 index 0000000..6912bdf --- /dev/null +++ b/Tests/RunCMake/find_file/FromPATHEnv-stdout-windows.txt @@ -0,0 +1,9 @@ +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' diff --git a/Tests/RunCMake/find_file/FromPATHEnv-stdout.txt b/Tests/RunCMake/find_file/FromPATHEnv-stdout.txt new file mode 100644 index 0000000..27a83ad --- /dev/null +++ b/Tests/RunCMake/find_file/FromPATHEnv-stdout.txt @@ -0,0 +1,9 @@ +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' diff --git a/Tests/RunCMake/find_file/FromPATHEnv.cmake b/Tests/RunCMake/find_file/FromPATHEnv.cmake new file mode 100644 index 0000000..9f058dd --- /dev/null +++ b/Tests/RunCMake/find_file/FromPATHEnv.cmake @@ -0,0 +1,24 @@ +set(ENV_PATH "$ENV{PATH}") +foreach(path "/does_not_exist" "/include" "") + unset(PrefixInPATH_File CACHE) + set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}") + find_file(PrefixInPATH_File NAMES PrefixInPATH.h) + message(STATUS "PrefixInPATH_File='${PrefixInPATH_File}'") +endforeach() + +set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF) +foreach(path "/does_not_exist" "/include" "") + unset(PrefixInPATH_File CACHE) + set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}") + find_file(PrefixInPATH_File NAMES PrefixInPATH.h) + message(STATUS "PrefixInPATH_File='${PrefixInPATH_File}'") +endforeach() + +set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH ON) +foreach(path "/does_not_exist" "/include" "") + unset(PrefixInPATH_File CACHE) + set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}") + find_file(PrefixInPATH_File NAMES PrefixInPATH.h NO_SYSTEM_ENVIRONMENT_PATH) + message(STATUS "PrefixInPATH_File='${PrefixInPATH_File}'") +endforeach() +set(ENV{PATH} "${ENV_PATH}") diff --git a/Tests/RunCMake/find_file/FromPrefixPath-stdout.txt b/Tests/RunCMake/find_file/FromPrefixPath-stdout.txt new file mode 100644 index 0000000..4bd24aa --- /dev/null +++ b/Tests/RunCMake/find_file/FromPrefixPath-stdout.txt @@ -0,0 +1,6 @@ +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_File='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' +-- PrefixInPATH_File='PrefixInPATH_File-NOTFOUND' diff --git a/Tests/RunCMake/find_file/FromPrefixPath.cmake b/Tests/RunCMake/find_file/FromPrefixPath.cmake new file mode 100644 index 0000000..63c6a07 --- /dev/null +++ b/Tests/RunCMake/find_file/FromPrefixPath.cmake @@ -0,0 +1,19 @@ +set(ENV_PATH "$ENV{PATH}") +set(ENV{PATH} "") +foreach(path "/does_not_exist" "/include" "") + unset(PrefixInPATH_File CACHE) + set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}${path}") + find_file(PrefixInPATH_File NAMES PrefixInPATH.h) + message(STATUS "PrefixInPATH_File='${PrefixInPATH_File}'") +endforeach() + +set(CMAKE_FIND_USE_CMAKE_PATH OFF) +set(CMAKE_PREFIX_PATH ) +foreach(path "/does_not_exist" "/include" "") + unset(PrefixInPATH_File CACHE) + set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}${path}") + find_file(PrefixInPATH_File NAMES PrefixInPATH.h) + message(STATUS "PrefixInPATH_File='${PrefixInPATH_File}'") +endforeach() +set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH ON) +set(ENV{PATH} "${ENV_PATH}") diff --git a/Tests/RunCMake/find_file/PrefixInPATH-stdout-cygwin.txt b/Tests/RunCMake/find_file/PrefixInPATH-stdout-cygwin.txt new file mode 100644 index 0000000..d73bc1d --- /dev/null +++ b/Tests/RunCMake/find_file/PrefixInPATH-stdout-cygwin.txt @@ -0,0 +1,4 @@ +-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' diff --git a/Tests/RunCMake/find_file/PrefixInPATH-stdout-windows.txt b/Tests/RunCMake/find_file/PrefixInPATH-stdout-windows.txt new file mode 100644 index 0000000..d73bc1d --- /dev/null +++ b/Tests/RunCMake/find_file/PrefixInPATH-stdout-windows.txt @@ -0,0 +1,4 @@ +-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' diff --git a/Tests/RunCMake/find_file/PrefixInPATH-stdout.txt b/Tests/RunCMake/find_file/PrefixInPATH-stdout.txt index d73bc1d..947a900 100644 --- a/Tests/RunCMake/find_file/PrefixInPATH-stdout.txt +++ b/Tests/RunCMake/find_file/PrefixInPATH-stdout.txt @@ -1,4 +1,4 @@ -- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND' --- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' --- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' --- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND' +-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND' +-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND' diff --git a/Tests/RunCMake/find_file/RunCMakeTest.cmake b/Tests/RunCMake/find_file/RunCMakeTest.cmake index 5ce96e0..9f56a57 100644 --- a/Tests/RunCMake/find_file/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_file/RunCMakeTest.cmake @@ -1,5 +1,5 @@ include(RunCMake) -if(WIN32 OR CYGWIN) - run_cmake(PrefixInPATH) -endif() +run_cmake(FromPATHEnv) +run_cmake(FromPrefixPath) +run_cmake(PrefixInPATH) diff --git a/Tests/RunCMake/find_library/FromPATHEnv-stdout-cygwin.txt b/Tests/RunCMake/find_library/FromPATHEnv-stdout-cygwin.txt new file mode 100644 index 0000000..01e2720 --- /dev/null +++ b/Tests/RunCMake/find_library/FromPATHEnv-stdout-cygwin.txt @@ -0,0 +1,6 @@ +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' +-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPATHEnv-build/lib/libcreated.a' +-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPATHEnv-build/lib/libcreated.a' +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' diff --git a/Tests/RunCMake/find_library/FromPATHEnv-stdout-windows.txt b/Tests/RunCMake/find_library/FromPATHEnv-stdout-windows.txt new file mode 100644 index 0000000..01e2720 --- /dev/null +++ b/Tests/RunCMake/find_library/FromPATHEnv-stdout-windows.txt @@ -0,0 +1,6 @@ +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' +-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPATHEnv-build/lib/libcreated.a' +-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPATHEnv-build/lib/libcreated.a' +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' diff --git a/Tests/RunCMake/find_library/FromPATHEnv-stdout.txt b/Tests/RunCMake/find_library/FromPATHEnv-stdout.txt new file mode 100644 index 0000000..4e570a6 --- /dev/null +++ b/Tests/RunCMake/find_library/FromPATHEnv-stdout.txt @@ -0,0 +1,6 @@ +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' +-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPATHEnv-build/lib/libcreated.a' +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' diff --git a/Tests/RunCMake/find_library/FromPATHEnv.cmake b/Tests/RunCMake/find_library/FromPATHEnv.cmake new file mode 100644 index 0000000..fec041d --- /dev/null +++ b/Tests/RunCMake/find_library/FromPATHEnv.cmake @@ -0,0 +1,22 @@ +list(APPEND CMAKE_FIND_LIBRARY_PREFIXES lib) +list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES .a) +set(ENV_PATH "$ENV{PATH}") +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib) +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib/libcreated.a" "created") + +foreach(path "/does_not_exist" "/lib" "") + unset(CREATED_LIBRARY CACHE) + set(ENV{PATH} "${CMAKE_CURRENT_BINARY_DIR}${path}") + find_library(CREATED_LIBRARY NAMES created) + message(STATUS "CREATED_LIBRARY='${CREATED_LIBRARY}'") +endforeach() + +set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF) +foreach(path "/does_not_exist" "/lib" "") + unset(CREATED_LIBRARY CACHE) + set(ENV{PATH} "${CMAKE_CURRENT_BINARY_DIR}${path}") + find_library(CREATED_LIBRARY NAMES created) + message(STATUS "CREATED_LIBRARY='${CREATED_LIBRARY}'") +endforeach() +set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH ON) +set(ENV{PATH} "${ENV_PATH}") diff --git a/Tests/RunCMake/find_library/FromPrefixPath-stdout.txt b/Tests/RunCMake/find_library/FromPrefixPath-stdout.txt new file mode 100644 index 0000000..de3df1a --- /dev/null +++ b/Tests/RunCMake/find_library/FromPrefixPath-stdout.txt @@ -0,0 +1,6 @@ +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' +-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPrefixPath-build/lib/libcreated.a' +-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/FromPrefixPath-build/lib/libcreated.a' +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' +-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND' diff --git a/Tests/RunCMake/find_library/FromPrefixPath.cmake b/Tests/RunCMake/find_library/FromPrefixPath.cmake new file mode 100644 index 0000000..04763a9 --- /dev/null +++ b/Tests/RunCMake/find_library/FromPrefixPath.cmake @@ -0,0 +1,24 @@ +list(APPEND CMAKE_FIND_LIBRARY_PREFIXES lib) +list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES .a) +set(ENV_PATH "$ENV{PATH}") +set(ENV{PATH} "") +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib) +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib/libcreated.a" "created") + +foreach(path "/does_not_exist" "/lib" "") + unset(CREATED_LIBRARY CACHE) + set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}${path}") + find_library(CREATED_LIBRARY NAMES created) + message(STATUS "CREATED_LIBRARY='${CREATED_LIBRARY}'") +endforeach() + +set(CMAKE_FIND_USE_CMAKE_PATH OFF) +set(CMAKE_PREFIX_PATH ) +foreach(path "/does_not_exist" "/lib" "") + unset(CREATED_LIBRARY CACHE) + set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}${path}") + find_library(CREATED_LIBRARY NAMES created) + message(STATUS "CREATED_LIBRARY='${CREATED_LIBRARY}'") +endforeach() +set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH ON) +set(ENV{PATH} "${ENV_PATH}") diff --git a/Tests/RunCMake/find_library/PrefixInPATH-stdout-cygwin.txt b/Tests/RunCMake/find_library/PrefixInPATH-stdout-cygwin.txt new file mode 100644 index 0000000..1ab884c --- /dev/null +++ b/Tests/RunCMake/find_library/PrefixInPATH-stdout-cygwin.txt @@ -0,0 +1,4 @@ +-- PrefixInPATH_LIBRARY='PrefixInPATH_LIBRARY-NOTFOUND' +-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' +-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' +-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' diff --git a/Tests/RunCMake/find_library/PrefixInPATH-stdout-windows.txt b/Tests/RunCMake/find_library/PrefixInPATH-stdout-windows.txt new file mode 100644 index 0000000..1ab884c --- /dev/null +++ b/Tests/RunCMake/find_library/PrefixInPATH-stdout-windows.txt @@ -0,0 +1,4 @@ +-- PrefixInPATH_LIBRARY='PrefixInPATH_LIBRARY-NOTFOUND' +-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' +-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' +-- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' diff --git a/Tests/RunCMake/find_library/PrefixInPATH-stdout.txt b/Tests/RunCMake/find_library/PrefixInPATH-stdout.txt index 1ab884c..c6ff513 100644 --- a/Tests/RunCMake/find_library/PrefixInPATH-stdout.txt +++ b/Tests/RunCMake/find_library/PrefixInPATH-stdout.txt @@ -1,4 +1,4 @@ -- PrefixInPATH_LIBRARY='PrefixInPATH_LIBRARY-NOTFOUND' --- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' --- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' --- PrefixInPATH_LIBRARY='.*/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' +-- PrefixInPATH_LIBRARY='PrefixInPATH_LIBRARY-NOTFOUND' +-- PrefixInPATH_LIBRARY='PrefixInPATH_LIBRARY-NOTFOUND' +-- PrefixInPATH_LIBRARY='PrefixInPATH_LIBRARY-NOTFOUND' diff --git a/Tests/RunCMake/find_library/RunCMakeTest.cmake b/Tests/RunCMake/find_library/RunCMakeTest.cmake index e7e8db3..643a5b9 100644 --- a/Tests/RunCMake/find_library/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_library/RunCMakeTest.cmake @@ -1,9 +1,9 @@ include(RunCMake) run_cmake(Created) +run_cmake(FromPrefixPath) +run_cmake(FromPATHEnv) if(CMAKE_HOST_UNIX) run_cmake(LibArchLink) endif() -if(WIN32 OR CYGWIN) - run_cmake(PrefixInPATH) -endif() +run_cmake(PrefixInPATH) diff --git a/Tests/RunCMake/find_package/FromPATHEnv-stdout.txt b/Tests/RunCMake/find_package/FromPATHEnv-stdout.txt new file mode 100644 index 0000000..2ead349 --- /dev/null +++ b/Tests/RunCMake/find_package/FromPATHEnv-stdout.txt @@ -0,0 +1,9 @@ +-- Resolved_FOUND='0' +-- Resolved_FOUND='1' +-- Resolved_FOUND='0' +-- Resolved_FOUND='0' +-- Resolved_FOUND='0' +-- Resolved_FOUND='0' +-- Resolved_FOUND='0' +-- Resolved_FOUND='0' +-- Resolved_FOUND='0' diff --git a/Tests/RunCMake/find_package/FromPATHEnv.cmake b/Tests/RunCMake/find_package/FromPATHEnv.cmake new file mode 100644 index 0000000..4822b13 --- /dev/null +++ b/Tests/RunCMake/find_package/FromPATHEnv.cmake @@ -0,0 +1,27 @@ +set(ENV_PATH "$ENV{PATH}") +foreach(path "/does_not_exist" "/PackageRoot" "") + unset(Resolved_FOUND CACHE) + set(Resolved_DIR "") + set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}") + find_package(Resolved QUIET) + message(STATUS "Resolved_FOUND='${Resolved_FOUND}'") +endforeach() + +set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF) +foreach(path "/does_not_exist" "/PackageRoot" "") + unset(Resolved_FOUND CACHE) + set(Resolved_DIR "") + set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}") + find_package(Resolved QUIET) + message(STATUS "Resolved_FOUND='${Resolved_FOUND}'") +endforeach() + +set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH ON) +foreach(path "/does_not_exist" "/PackageRoot" "") + unset(Resolved_FOUND CACHE) + set(Resolved_DIR "") + set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}") + find_package(Resolved NO_SYSTEM_ENVIRONMENT_PATH QUIET) + message(STATUS "Resolved_FOUND='${Resolved_FOUND}'") +endforeach() +set(ENV{PATH} "${ENV_PATH}") diff --git a/Tests/RunCMake/find_package/FromPrefixPath-stdout.txt b/Tests/RunCMake/find_package/FromPrefixPath-stdout.txt new file mode 100644 index 0000000..2ead349 --- /dev/null +++ b/Tests/RunCMake/find_package/FromPrefixPath-stdout.txt @@ -0,0 +1,9 @@ +-- Resolved_FOUND='0' +-- Resolved_FOUND='1' +-- Resolved_FOUND='0' +-- Resolved_FOUND='0' +-- Resolved_FOUND='0' +-- Resolved_FOUND='0' +-- Resolved_FOUND='0' +-- Resolved_FOUND='0' +-- Resolved_FOUND='0' diff --git a/Tests/RunCMake/find_package/FromPrefixPath.cmake b/Tests/RunCMake/find_package/FromPrefixPath.cmake new file mode 100644 index 0000000..be853c1 --- /dev/null +++ b/Tests/RunCMake/find_package/FromPrefixPath.cmake @@ -0,0 +1,29 @@ +set(ENV_PATH "$ENV{PATH}") +set(ENV{PATH} "") +foreach(path "/does_not_exist" "/PackageRoot" "") + unset(Resolved_FOUND CACHE) + set(Resolved_DIR "") + set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}${path}") + find_package(Resolved QUIET) + message(STATUS "Resolved_FOUND='${Resolved_FOUND}'") +endforeach() + +set(CMAKE_FIND_USE_CMAKE_PATH OFF) +set(CMAKE_PREFIX_PATH ) +foreach(path "/does_not_exist" "/PackageRoot" "") + unset(Resolved_FOUND CACHE) + set(Resolved_DIR "") + set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}${path}") + find_package(Resolved QUIET) + message(STATUS "Resolved_FOUND='${Resolved_FOUND}'") +endforeach() + +set(CMAKE_FIND_USE_CMAKE_PATH ON) +foreach(path "/does_not_exist" "/PackageRoot" "") + unset(Resolved_FOUND CACHE) + set(Resolved_DIR "") + set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}${path}") + find_package(Resolved NO_CMAKE_PATH QUIET) + message(STATUS "Resolved_FOUND='${Resolved_FOUND}'") +endforeach() +set(ENV{PATH} "${ENV_PATH}") diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake index 066523e..208f83c 100644 --- a/Tests/RunCMake/find_package/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake @@ -3,6 +3,8 @@ include(RunCMake) run_cmake(CMP0074-WARN) run_cmake(CMP0074-OLD) run_cmake(ComponentRequiredAndOptional) +run_cmake(FromPATHEnv) +run_cmake(FromPrefixPath) run_cmake(MissingNormal) run_cmake(MissingNormalRequired) run_cmake(MissingNormalVersion) diff --git a/Tests/RunCMake/find_path/FromPATHEnv-stdout-cygwin.txt b/Tests/RunCMake/find_path/FromPATHEnv-stdout-cygwin.txt new file mode 100644 index 0000000..8f3e7ca --- /dev/null +++ b/Tests/RunCMake/find_path/FromPATHEnv-stdout-cygwin.txt @@ -0,0 +1,9 @@ +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='.*/Tests/RunCMake/find_path/include' +-- PATH_IN_ENV_PATH='.*/Tests/RunCMake/find_path/include' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' diff --git a/Tests/RunCMake/find_path/FromPATHEnv-stdout-windows.txt b/Tests/RunCMake/find_path/FromPATHEnv-stdout-windows.txt new file mode 100644 index 0000000..8f3e7ca --- /dev/null +++ b/Tests/RunCMake/find_path/FromPATHEnv-stdout-windows.txt @@ -0,0 +1,9 @@ +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='.*/Tests/RunCMake/find_path/include' +-- PATH_IN_ENV_PATH='.*/Tests/RunCMake/find_path/include' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' diff --git a/Tests/RunCMake/find_path/FromPATHEnv-stdout.txt b/Tests/RunCMake/find_path/FromPATHEnv-stdout.txt new file mode 100644 index 0000000..fd41bf4 --- /dev/null +++ b/Tests/RunCMake/find_path/FromPATHEnv-stdout.txt @@ -0,0 +1,9 @@ +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='.*/Tests/RunCMake/find_path/include' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' +-- PATH_IN_ENV_PATH='PATH_IN_ENV_PATH-NOTFOUND' diff --git a/Tests/RunCMake/find_path/FromPATHEnv.cmake b/Tests/RunCMake/find_path/FromPATHEnv.cmake new file mode 100644 index 0000000..af13d09 --- /dev/null +++ b/Tests/RunCMake/find_path/FromPATHEnv.cmake @@ -0,0 +1,25 @@ +set(ENV_PATH "$ENV{PATH}") +foreach(path "/does_not_exist" "/include" "") + unset(PATH_IN_ENV_PATH CACHE) + set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}") + find_path(PATH_IN_ENV_PATH NAMES PrefixInPATH.h) + message(STATUS "PATH_IN_ENV_PATH='${PATH_IN_ENV_PATH}'") +endforeach() + +set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF) +foreach(path "/does_not_exist" "/include" "") + unset(PATH_IN_ENV_PATH CACHE) + set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}") + find_path(PATH_IN_ENV_PATH NAMES PrefixInPATH.h) + message(STATUS "PATH_IN_ENV_PATH='${PATH_IN_ENV_PATH}'") +endforeach() + +set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH ON) +foreach(path "/does_not_exist" "/include" "") + unset(PATH_IN_ENV_PATH CACHE) + set(ENV{PATH} "${CMAKE_CURRENT_SOURCE_DIR}${path}") + find_path(PATH_IN_ENV_PATH NAMES PrefixInPATH.h NO_SYSTEM_ENVIRONMENT_PATH) + message(STATUS "PATH_IN_ENV_PATH='${PATH_IN_ENV_PATH}'") +endforeach() + +set(ENV{PATH} "${ENV_PATH}") diff --git a/Tests/RunCMake/find_path/PrefixInPATH-stdout-cygwin.txt b/Tests/RunCMake/find_path/PrefixInPATH-stdout-cygwin.txt new file mode 100644 index 0000000..bb2ceb7 --- /dev/null +++ b/Tests/RunCMake/find_path/PrefixInPATH-stdout-cygwin.txt @@ -0,0 +1,4 @@ +-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include' diff --git a/Tests/RunCMake/find_path/PrefixInPATH-stdout-windows.txt b/Tests/RunCMake/find_path/PrefixInPATH-stdout-windows.txt new file mode 100644 index 0000000..bb2ceb7 --- /dev/null +++ b/Tests/RunCMake/find_path/PrefixInPATH-stdout-windows.txt @@ -0,0 +1,4 @@ +-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include' +-- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include' diff --git a/Tests/RunCMake/find_path/PrefixInPATH-stdout.txt b/Tests/RunCMake/find_path/PrefixInPATH-stdout.txt index bb2ceb7..947a900 100644 --- a/Tests/RunCMake/find_path/PrefixInPATH-stdout.txt +++ b/Tests/RunCMake/find_path/PrefixInPATH-stdout.txt @@ -1,4 +1,4 @@ -- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND' --- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include' --- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include' --- PrefixInPATH_INCLUDE_DIR='.*/Tests/RunCMake/find_path/include' +-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND' +-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND' +-- PrefixInPATH_INCLUDE_DIR='PrefixInPATH_INCLUDE_DIR-NOTFOUND' diff --git a/Tests/RunCMake/find_path/RunCMakeTest.cmake b/Tests/RunCMake/find_path/RunCMakeTest.cmake index bf0fa89..8b5b5b7 100644 --- a/Tests/RunCMake/find_path/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_path/RunCMakeTest.cmake @@ -1,8 +1,7 @@ include(RunCMake) -if(WIN32 OR CYGWIN) - run_cmake(PrefixInPATH) -endif() +run_cmake(FromPATHEnv) +run_cmake(PrefixInPATH) if(APPLE) run_cmake(FrameworksWithSubdirs) diff --git a/Tests/RunCMake/find_program/EnvAndHints-stdout.txt b/Tests/RunCMake/find_program/EnvAndHints-stdout.txt index 39329b2..0051636 100644 --- a/Tests/RunCMake/find_program/EnvAndHints-stdout.txt +++ b/Tests/RunCMake/find_program/EnvAndHints-stdout.txt @@ -1 +1,4 @@ -- PROG='[^']*/Tests/RunCMake/find_program/A/testAandB' +-- PROG='PROG-NOTFOUND' +-- PROG='[^']*/Tests/RunCMake/find_program/B/testAandB' +-- PROG='[^']*/Tests/RunCMake/find_program/A/testAandB' diff --git a/Tests/RunCMake/find_program/EnvAndHints.cmake b/Tests/RunCMake/find_program/EnvAndHints.cmake index 14ebd6e..0f12eff 100644 --- a/Tests/RunCMake/find_program/EnvAndHints.cmake +++ b/Tests/RunCMake/find_program/EnvAndHints.cmake @@ -1,8 +1,31 @@ + set(ENV_PATH "$ENV{PATH}") set(ENV{PATH} ${CMAKE_CURRENT_SOURCE_DIR}/A) find_program(PROG NAMES testAandB + ) +message(STATUS "PROG='${PROG}'") +unset(PROG CACHE) + +set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF) +find_program(PROG + NAMES testAandB + ) +message(STATUS "PROG='${PROG}'") +unset(PROG CACHE) + +find_program(PROG + NAMES testAandB + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/B ${CMAKE_CURRENT_SOURCE_DIR}/A + ) +message(STATUS "PROG='${PROG}'") +unset(PROG CACHE) +set(ENV{PATH} "${ENV_PATH}") + +find_program(PROG + NAMES testAandB HINTS ${CMAKE_CURRENT_SOURCE_DIR}/A ${CMAKE_CURRENT_SOURCE_DIR}/B ) message(STATUS "PROG='${PROG}'") +unset(PROG CACHE) set(ENV{PATH} "${ENV_PATH}") diff --git a/Tests/RunCMake/find_program/RelAndAbsPath-stdout.txt b/Tests/RunCMake/find_program/RelAndAbsPath-stdout.txt index cb3c99f..d2312e7 100644 --- a/Tests/RunCMake/find_program/RelAndAbsPath-stdout.txt +++ b/Tests/RunCMake/find_program/RelAndAbsPath-stdout.txt @@ -1,6 +1,8 @@ -- PROG_ABS='PROG_ABS-NOTFOUND' -- PROG_ABS_NPD='PROG_ABS_NPD-NOTFOUND' -- PROG_CWD='PROG_CWD-NOTFOUND' +-- PROG_CWD='PROG_CWD-NOTFOUND' +-- PROG_CWD='[^']*/Tests/RunCMake/find_program/testCWD' -- PROG_CWD_NPD='PROG_CWD_NPD-NOTFOUND' -- PROG_CWD_DOT='[^']*/Tests/RunCMake/find_program/testCWD' -- PROG_CWD_DOT_NPD='[^']*/Tests/RunCMake/find_program/testCWD' diff --git a/Tests/RunCMake/find_program/RelAndAbsPath.cmake b/Tests/RunCMake/find_program/RelAndAbsPath.cmake index 9a42c5e..6b61980 100644 --- a/Tests/RunCMake/find_program/RelAndAbsPath.cmake +++ b/Tests/RunCMake/find_program/RelAndAbsPath.cmake @@ -10,7 +10,6 @@ endfunction() strip_windows_path_prefix("${CMAKE_CURRENT_SOURCE_DIR}" srcdir) -file(MAKE_DIRECTORY "tmp${srcdir}") configure_file(testCWD "tmp${srcdir}/testNoSuchFile" COPYONLY) find_program(PROG_ABS @@ -38,6 +37,28 @@ find_program(PROG_CWD ) message(STATUS "PROG_CWD='${PROG_CWD}'") + +set(CMAKE_PREFIX_PATH ".") +# On some platforms / dashboards the current working +# directory can be in PATH or other search locations +# so disable all searching to make sure this fails +set(CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH OFF) +set(CMAKE_FIND_USE_CMAKE_PATH OFF) +set(CMAKE_FIND_USE_CMAKE_SYSTEM_PATH OFF) +set(CMAKE_FIND_USE_PACKAGE_ROOT_PATH OFF) +set(CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH OFF) +find_program(PROG_CWD + NAMES testCWD + ) +message(STATUS "PROG_CWD='${PROG_CWD}'") + +set(CMAKE_PREFIX_PATH ".") +set(CMAKE_FIND_USE_CMAKE_PATH ON) +find_program(PROG_CWD + NAMES testCWD + ) +message(STATUS "PROG_CWD='${PROG_CWD}'") + find_program(PROG_CWD_NPD NAMES testCWD NAMES_PER_DIR diff --git a/Tests/RunCMake/install/CMakeLists.txt b/Tests/RunCMake/install/CMakeLists.txt index 6dd8cdf..c7e99ad 100644 --- a/Tests/RunCMake/install/CMakeLists.txt +++ b/Tests/RunCMake/install/CMakeLists.txt @@ -1,3 +1,6 @@ cmake_minimum_required(VERSION 3.4) +if(RunCMake_TEST MATCHES "^file-GET_RUNTIME_DEPENDENCIES") + cmake_policy(SET CMP0087 NEW) +endif() project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index c637db1..21c320b 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -48,6 +48,22 @@ in directory: endif() endfunction() +# Wrapper for run_cmake() that skips platforms that are non-ELF or have no RPATH support +function(run_cmake_ELFRPATH_only case) + if(UNIX AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG AND CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF") + run_cmake(${case}) + else() + # Sanity check against a platform known to be ELF-based + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + message(FATAL_ERROR "Expected platform Linux to advertize itself as ELF-based, but it did not.") + else() + message(STATUS "${case} - SKIPPED (No ELF-based platform found)") + endif() + endif() +endfunction() + +run_cmake(TARGETS-FILE_RPATH_CHANGE-old_rpath) +run_cmake_ELFRPATH_only(TARGETS-FILE_RPATH_CHANGE-new_rpath) run_cmake(DIRECTORY-MESSAGE_NEVER) run_cmake(DIRECTORY-PATTERN-MESSAGE_NEVER) run_cmake(DIRECTORY-message) @@ -139,6 +155,36 @@ run_install_test(FILES-PERMISSIONS) run_install_test(TARGETS-RPATH) run_install_test(InstallRequiredSystemLibraries) +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + run_install_test(file-GET_RUNTIME_DEPENDENCIES-macos) + run_install_test(file-GET_RUNTIME_DEPENDENCIES-macos-unresolved) + run_install_test(file-GET_RUNTIME_DEPENDENCIES-macos-conflict) + run_install_test(file-GET_RUNTIME_DEPENDENCIES-macos-notfile) + run_cmake(file-GET_RUNTIME_DEPENDENCIES-project) + run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs1) + run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs2) +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + run_install_test(file-GET_RUNTIME_DEPENDENCIES-windows) + run_install_test(file-GET_RUNTIME_DEPENDENCIES-windows-unresolved) + run_install_test(file-GET_RUNTIME_DEPENDENCIES-windows-conflict) + run_install_test(file-GET_RUNTIME_DEPENDENCIES-windows-notfile) + run_cmake(file-GET_RUNTIME_DEPENDENCIES-project) + run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs1) + run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs2) +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + if(NOT CMAKE_C_COMPILER_ID MATCHES "^XL") + run_install_test(file-GET_RUNTIME_DEPENDENCIES-linux) + endif() + run_install_test(file-GET_RUNTIME_DEPENDENCIES-linux-unresolved) + run_install_test(file-GET_RUNTIME_DEPENDENCIES-linux-conflict) + run_install_test(file-GET_RUNTIME_DEPENDENCIES-linux-notfile) + run_cmake(file-GET_RUNTIME_DEPENDENCIES-project) + run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs1) + run_cmake(file-GET_RUNTIME_DEPENDENCIES-badargs2) +else() + run_cmake(file-GET_RUNTIME_DEPENDENCIES-unsupported) +endif() + set(run_install_test_components 1) run_install_test(FILES-EXCLUDE_FROM_ALL) run_install_test(TARGETS-EXCLUDE_FROM_ALL) diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake new file mode 100644 index 0000000..673fdde --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake @@ -0,0 +1,30 @@ +file(READ ${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake install_script) +#message(STATUS ${install_script}) + +set(wsnl " *[\n\r]+ *") # whitespace + single newline + whitespace +set(wssl " *[\n\r]+[^\n\r]*[\n\r]+ *") # ws nl skipline nl ws +string(CONCAT prefix [[file\(RPATH_CHANGE]]) +set(_msg "cmake_install.cmake does not match ") + +macro(check) + if(NOT install_script MATCHES "${regex}") + message(STATUS "${test} - check \"${target}\" - FAILED:") + string(CONCAT RunCMake_TEST_FAILED "${_msg}" ">>>${regex}<<<") + return() + else() + message(STATUS "${test} - check \"${target}\" - PASSED") + endif() +endmacro() + +macro(skip_without_rpath_change_rule) +# Not all platforms generate a file(RPATH_CHANGE) rule + if(NOT install_script MATCHES [[file\(RPATH_CHANGE]]) + # Sanity check against a platform known to generate a file(RPATH_CHANGE) rule + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + message(FATAL_ERROR "Expected generated file(RPATH_CHANGE) rule on platform Linux.") + else() + message(STATUS "${test} - All checks skipped. No file(RPATH_CHANGE) rule found on this platform.") + return() + endif() + endif() +endmacro() diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake new file mode 100644 index 0000000..930ef70 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake @@ -0,0 +1,63 @@ +include(${RunCMake_SOURCE_DIR}/TARGETS-FILE_RPATH_CHANGE-check-common.cmake) +skip_without_rpath_change_rule() +string(APPEND prefix "${wsnl}" [[FILE "[^"]*/]]) + +set(target "exe1_cmp0095_old") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "/foo/bar]]) +check() + +set(target "exe1_cmp0095_warn") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "/foo/bar]]) +check() + +set(target "exe1_cmp0095_new") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "/foo/bar]]) +check() + +set(target "exe2_cmp0095_old") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "\$ORIGIN/../lib]]) +check() + +set(target "exe2_cmp0095_warn") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "\$ORIGIN/../lib]]) +check() + +set(target "exe2_cmp0095_new") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "\\\$ORIGIN/../lib]]) +check() + +set(target "exe3_cmp0095_old") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "\${ORIGIN}/../lib]]) +check() + +set(target "exe3_cmp0095_warn") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "\${ORIGIN}/../lib]]) +check() + +set(target "exe3_cmp0095_new") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "\\\${ORIGIN}/../lib]]) +check() + +set(target "exe4_cmp0095_old") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "/foo/bar/\${PLATFORM}]]) +check() + +set(target "exe4_cmp0095_warn") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "/foo/bar/\${PLATFORM}]]) +check() + +set(target "exe4_cmp0095_new") +string(CONCAT regex "${prefix}${target}\"${wssl}" + [[NEW_RPATH "/foo/bar/\\\${PLATFORM}]]) +check() diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt new file mode 100644 index 0000000..1e123f6 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt @@ -0,0 +1,23 @@ +^CMake Warning \(dev\) at TARGETS-FILE_RPATH_CHANGE-new_rpath\.cmake:[0-9]+ \(install\): + Policy CMP0095 is not set: RPATH entries are properly escaped in the + intermediary CMake install script\. Run "cmake --help-policy CMP0095" for + policy details\. Use the cmake_policy command to set the policy and + suppress this warning\. + + RPATH entries for target 'exe3_cmp0095_warn' will not be escaped in the + intermediary cmake_install\.cmake script\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\. + +CMake Warning \(dev\) at TARGETS-FILE_RPATH_CHANGE-new_rpath\.cmake:[0-9]+ \(install\): + Policy CMP0095 is not set: RPATH entries are properly escaped in the + intermediary CMake install script\. Run "cmake --help-policy CMP0095" for + policy details\. Use the cmake_policy command to set the policy and + suppress this warning\. + + RPATH entries for target 'exe4_cmp0095_warn' will not be escaped in the + intermediary cmake_install\.cmake script\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\.$ diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath.cmake new file mode 100644 index 0000000..cba04b2 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath.cmake @@ -0,0 +1,72 @@ +cmake_minimum_required(VERSION 3.14) +enable_language(C) + +# test matrix +# +# A := +# | no cmake syntax | cmake syntax | +# -----------------------+-----------------+--------------+ +# absolute install RPATH | exe1 | exe4 | +# relative install RPATH | exe2 | exe3 | +# +# all := A * CMP005_OLD + A * CMP0095_WARN + A * CMP0095_NEW + +add_library(utils SHARED obj1.c) +set(targets utils) + +set(exe1_install_rpath "/foo/bar") +set(exe2_install_rpath "\$ORIGIN/../lib") +set(exe3_install_rpath "\${ORIGIN}/../lib") +set(exe4_install_rpath "/foo/bar/\${PLATFORM}") + +macro(A_CMP0095 policy_value) + cmake_policy(PUSH) + if(NOT "x${policy_value}x" STREQUAL "xWARNx") + cmake_policy(SET CMP0095 ${policy_value}) + endif() + string(TOLOWER "${policy_value}" p) + + # exe1: absolute install RPATH, no cmake syntax + set(case "exe1") + set(target "${case}_cmp0095_${p}") + list(APPEND targets ${target}) + add_executable(${target} main.c) + target_link_libraries(${target} PRIVATE utils) + set_target_properties(${target} PROPERTIES + INSTALL_RPATH "${${case}_install_rpath}") + + # exe2: relative install RPATH, no cmake syntax + set(case "exe2") + set(target "${case}_cmp0095_${p}") + list(APPEND targets ${target}) + add_executable(${target} main.c) + target_link_libraries(${target} PRIVATE utils) + set_target_properties(${target} PROPERTIES + INSTALL_RPATH "${${case}_install_rpath}") + + # exe3: relative install RPATH, cmake syntax + set(case "exe3") + set(target "${case}_cmp0095_${p}") + list(APPEND targets ${target}) + add_executable(${target} main.c) + target_link_libraries(${target} PRIVATE utils) + set_target_properties(${target} PROPERTIES + INSTALL_RPATH "${${case}_install_rpath}") + + # exe4: absolute install RPATH, cmake syntax + set(case "exe4") + set(target "${case}_cmp0095_${p}") + list(APPEND targets ${target}) + add_executable(${target} main.c) + target_link_libraries(${target} PRIVATE utils) + set_target_properties(${target} PROPERTIES + INSTALL_RPATH "${${case}_install_rpath}") + + cmake_policy(POP) +endmacro() + +A_CMP0095("OLD") +A_CMP0095("WARN") # exe3 and exe4 are expected to issue an author warning +A_CMP0095("NEW") + +install(TARGETS ${targets}) diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake new file mode 100644 index 0000000..814f405 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake @@ -0,0 +1,15 @@ +include(${RunCMake_SOURCE_DIR}/TARGETS-FILE_RPATH_CHANGE-check-common.cmake) +skip_without_rpath_change_rule() +string(APPEND prefix "${wsnl}" [[FILE "[^"]*/]]) + +set(target "exe1") +string(CONCAT regex "${prefix}${target}\"${wsnl}" + [[OLD_RPATH "]] "${RunCMake_BINARY_DIR}") +check() + +if("x${CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN}" STREQUAL "x\$ORIGIN") + set(target "exe2") + string(CONCAT regex "${prefix}${target}\"${wsnl}" + [[OLD_RPATH "\\\$ORIGIN]]) + check() +endif() diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath.cmake new file mode 100644 index 0000000..43ae787 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath.cmake @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.14) +enable_language(C) + +add_library(utils SHARED obj1.c) + +# exe1: absolute build RPATH, no cmake syntax +set(CMAKE_BUILD_RPATH_USE_ORIGIN OFF) +set(CMAKE_INSTALL_RPATH "/foo/bar") +add_executable(exe1 main.c) +target_link_libraries(exe1 PRIVATE utils) + +# exe2: relative build RPATH, no cmake syntax +set(CMAKE_BUILD_RPATH_USE_ORIGIN ON) +set(CMAKE_INSTALL_RPATH "/foo/bar") +add_executable(exe2 main.c) +target_link_libraries(exe2 PRIVATE utils) + +install(TARGETS utils exe1 exe2) diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1-stderr.txt new file mode 100644 index 0000000..b66d1fe --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1-stderr.txt @@ -0,0 +1,18 @@ +^CMake Warning \(dev\) at file-GET_RUNTIME_DEPENDENCIES-badargs1\.cmake:[0-9]+ \(file\): + You have used file\(GET_RUNTIME_DEPENDENCIES\) in project mode\. This is + probably not what you intended to do\. Instead, please consider using it in + an install\(CODE\) or install\(SCRIPT\) command\. For example: + + install\(CODE \[\[ + file\(GET_RUNTIME_DEPENDENCIES + # \.\.\. + \) + ]]\) +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\. + +CMake Error at file-GET_RUNTIME_DEPENDENCIES-badargs1\.cmake:[0-9]+ \(file\): + file Unrecognized argument: "invalid" +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1.cmake new file mode 100644 index 0000000..f3b8ce4 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs1.cmake @@ -0,0 +1,2 @@ +file(GET_RUNTIME_DEPENDENCIES invalid) +message(FATAL_ERROR "This message should not be displayed") diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2-stderr.txt new file mode 100644 index 0000000..94f0f46 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2-stderr.txt @@ -0,0 +1,18 @@ +^CMake Warning \(dev\) at file-GET_RUNTIME_DEPENDENCIES-badargs2\.cmake:[0-9]+ \(file\): + You have used file\(GET_RUNTIME_DEPENDENCIES\) in project mode\. This is + probably not what you intended to do\. Instead, please consider using it in + an install\(CODE\) or install\(SCRIPT\) command\. For example: + + install\(CODE \[\[ + file\(GET_RUNTIME_DEPENDENCIES + # \.\.\. + \) + ]]\) +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\. + +CMake Error at file-GET_RUNTIME_DEPENDENCIES-badargs2\.cmake:[0-9]+ \(file\): + file Keyword missing value: BUNDLE_EXECUTABLE +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2.cmake new file mode 100644 index 0000000..138ab95 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-badargs2.cmake @@ -0,0 +1,2 @@ +file(GET_RUNTIME_DEPENDENCIES BUNDLE_EXECUTABLE) +message(FATAL_ERROR "This message should not be displayed") diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-all-check.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-all-check.cmake new file mode 100644 index 0000000..ab630f0 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-all-check.cmake @@ -0,0 +1,44 @@ +function(check_contents filename contents_regex) + if(EXISTS "${CMAKE_INSTALL_PREFIX}/${filename}") + file(READ "${CMAKE_INSTALL_PREFIX}/${filename}" contents) + if(NOT contents MATCHES "${contents_regex}") + string(APPEND RunCMake_TEST_FAILED "File contents: + ${contents} +do not match what we expected: + ${contents_regex} +in file: + ${CMAKE_INSTALL_PREFIX}/${filename}\n") + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) + endif() + else() + string(APPEND RunCMake_TEST_FAILED "File ${CMAKE_INSTALL_PREFIX}/${filename} does not exist") + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) + endif() +endfunction() + +set(_check + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/libtest_rpath\.so]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/libtest_runpath\.so]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath/librpath\.so]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_parent/librpath_parent\.so]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search/librpath_search\.so]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath/librunpath\.so]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search/librunpath_search\.so]] + ) +check_contents(deps/deps1.txt "^${_check}$") +check_contents(deps/deps2.txt "^${_check}$") +check_contents(deps/deps3.txt "^${_check}$") +set(_check + [[librpath_unresolved\.so]] + [[librunpath_parent_unresolved\.so]] + [[librunpath_unresolved\.so]] + ) +check_contents(deps/udeps1.txt "^${_check}$") +check_contents(deps/udeps2.txt "^${_check}$") +check_contents(deps/udeps3.txt "^${_check}$") +set(_check + "^libconflict\\.so:[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/conflict/libconflict\\.so;[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/conflict2/libconflict\\.so\n$" + ) +check_contents(deps/cdeps1.txt "${_check}") +check_contents(deps/cdeps2.txt "${_check}") +check_contents(deps/cdeps3.txt "${_check}") diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-all-stderr.txt new file mode 100644 index 0000000..123ae48 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-all-stderr.txt @@ -0,0 +1,119 @@ +^CMake Warning at cmake_install\.cmake:[0-9]+ \(file\): + Dependency librpath_search_postexcluded\.so found in search directory: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search_postexcluded + + See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\. +Call Stack \(most recent call first\): + cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\) + +*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\): + Dependency librpath_search\.so found in search directory: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search + + See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\. +Call Stack \(most recent call first\): + cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\) + +*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\): + Dependency librunpath_search_postexcluded\.so found in search directory: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search_postexcluded + + See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\. +Call Stack \(most recent call first\): + cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\) + +*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\): + Dependency librunpath_search\.so found in search directory: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search + + See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\. +Call Stack \(most recent call first\): + cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\) + +*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\): + Dependency librpath_search_postexcluded\.so found in search directory: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search_postexcluded + + See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\. +Call Stack \(most recent call first\): + cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\) + +*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\): + Dependency librpath_search\.so found in search directory: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search + + See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\. +Call Stack \(most recent call first\): + cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\) + +*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\): + Dependency librunpath_search_postexcluded\.so found in search directory: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search_postexcluded + + See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\. +Call Stack \(most recent call first\): + cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\) + +*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\): + Dependency librunpath_search\.so found in search directory: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search + + See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\. +Call Stack \(most recent call first\): + cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\) + +*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\): + Dependency librpath_search_postexcluded\.so found in search directory: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search_postexcluded + + See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\. +Call Stack \(most recent call first\): + cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\) + +*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\): + Dependency librpath_search\.so found in search directory: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/rpath_search + + See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\. +Call Stack \(most recent call first\): + cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\) + +*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\): + Dependency librunpath_search_postexcluded\.so found in search directory: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search_postexcluded + + See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\. +Call Stack \(most recent call first\): + cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\) + +*CMake Warning at cmake_install\.cmake:[0-9]+ \(file\): + Dependency librunpath_search\.so found in search directory: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-build/root-all/lib/runpath_search + + See file\(GET_RUNTIME_DEPENDENCIES\) documentation for more information\. +Call Stack \(most recent call first\): + cmake_install\.cmake:[0-9]+ \(exec_get_runtime_dependencies\)$ diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-all-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-all-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-all-stderr.txt new file mode 100644 index 0000000..1692348 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-all-stderr.txt @@ -0,0 +1,7 @@ +^CMake Error at cmake_install\.cmake:[0-9]+ \(file\): + file Multiple conflicting paths found for librpath\.so: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-build/root-all/lib/rpath1/librpath\.so + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict-build/root-all/lib/rpath2/librpath\.so$ diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict.cmake new file mode 100644 index 0000000..f719499 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-conflict.cmake @@ -0,0 +1,54 @@ +enable_language(C) + +set(test1_names rpath) +set(test2_names rpath) + +file(WRITE "${CMAKE_BINARY_DIR}/rpath.c" "void rpath(void) {}\n") +add_library(rpath SHARED "${CMAKE_BINARY_DIR}/rpath.c") +install(TARGETS rpath DESTINATION lib/rpath1) +install(TARGETS rpath DESTINATION lib/rpath2) + +file(REMOVE "${CMAKE_BINARY_DIR}/test1.c") +add_library(test1 SHARED "${CMAKE_BINARY_DIR}/test1.c") +foreach(name ${test1_names}) + file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "extern void ${name}(void);\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "void test1(void)\n{\n") +foreach(name ${test1_names}) + file(APPEND "${CMAKE_BINARY_DIR}/test1.c" " ${name}();\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "}\n") + +target_link_libraries(test1 PRIVATE ${test1_names}) +set_property(TARGET test1 PROPERTY INSTALL_RPATH + "${CMAKE_BINARY_DIR}/root-all/lib/rpath1" + ) + +file(REMOVE "${CMAKE_BINARY_DIR}/test2.c") +add_library(test2 SHARED "${CMAKE_BINARY_DIR}/test2.c") +foreach(name ${test2_names}) + file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "extern void ${name}(void);\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "void test2(void)\n{\n") +foreach(name ${test2_names}) + file(APPEND "${CMAKE_BINARY_DIR}/test2.c" " ${name}();\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "}\n") + +target_link_libraries(test2 PRIVATE ${test2_names}) +set_property(TARGET test2 PROPERTY INSTALL_RPATH + "${CMAKE_BINARY_DIR}/root-all/lib/rpath2" + ) + +install(TARGETS test1 test2 DESTINATION lib) + +install(CODE [[ + file(GET_RUNTIME_DEPENDENCIES + LIBRARIES + "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test1>" + "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test2>" + PRE_INCLUDE_REGEXES "^librpath\\.so$" + PRE_EXCLUDE_REGEXES ".*" + ) + message(FATAL_ERROR "This message should not be displayed") + ]]) diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile-all-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile-all-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile-all-stderr.txt new file mode 100644 index 0000000..83a87c9 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile-all-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at cmake_install\.cmake:[0-9]+ \(file\): + file Failed to run objdump on: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile-build/root-all/bin/\.\./lib/libtest\.so$ diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile.cmake new file mode 100644 index 0000000..6567438 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile.cmake @@ -0,0 +1,30 @@ +enable_language(C) +cmake_policy(SET CMP0095 NEW) + +file(WRITE "${CMAKE_BINARY_DIR}/test.c" "void test(void) {}\n") +file(WRITE "${CMAKE_BINARY_DIR}/main.c" [[extern void test(void); + +int main(void) +{ + test(); + return 0; +} +]]) + +add_library(test SHARED "${CMAKE_BINARY_DIR}/test.c") +add_executable(exe "${CMAKE_BINARY_DIR}/main.c") +target_link_libraries(exe PRIVATE test) +set_property(TARGET exe PROPERTY INSTALL_RPATH "\${ORIGIN}/../lib") + +install(TARGETS exe DESTINATION bin) + +install(CODE [[ + file(MAKE_DIRECTORY "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test>") + file(GET_RUNTIME_DEPENDENCIES + EXECUTABLES + "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:exe>" + PRE_INCLUDE_REGEXES "^libtest\\.so$" + PRE_EXCLUDE_REGEXES ".*" + ) + message(FATAL_ERROR "This message should not be displayed") + ]]) diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved-all-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved-all-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved-all-stderr.txt new file mode 100644 index 0000000..eaca512 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved-all-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error at cmake_install\.cmake:[0-9]+ \(file\): + file Could not resolve file libunresolved\.so$ diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved.cmake new file mode 100644 index 0000000..3efa305 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-unresolved.cmake @@ -0,0 +1,18 @@ +enable_language(C) + +file(WRITE "${CMAKE_BINARY_DIR}/testlib.c" "extern void unresolved(void);\nvoid testlib(void)\n{\n unresolved();\n}\n") +add_library(testlib SHARED "${CMAKE_BINARY_DIR}/testlib.c") +file(WRITE "${CMAKE_BINARY_DIR}/unresolved.c" "void unresolved(void) {}\n") +add_library(unresolved SHARED "${CMAKE_BINARY_DIR}/unresolved.c") +target_link_libraries(testlib PRIVATE unresolved) +install(TARGETS testlib DESTINATION lib) + +install(CODE [[ + file(GET_RUNTIME_DEPENDENCIES + PRE_INCLUDE_REGEXES "^libunresolved\\.so$" + PRE_EXCLUDE_REGEXES ".*" + LIBRARIES + "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:testlib>" + ) + message(FATAL_ERROR "This message should not be displayed") + ]]) diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux.cmake new file mode 100644 index 0000000..bd0f9f1 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux.cmake @@ -0,0 +1,169 @@ +enable_language(C) +cmake_policy(SET CMP0095 NEW) + +set(test_rpath_names + preexcluded + rpath_postexcluded + rpath + rpath_parent_postexcluded + rpath_parent + rpath_origin_postexcluded + rpath_origin + rpath_search_postexcluded + rpath_search + rpath_unresolved + conflict + ) +set(test_runpath_names + runpath_postexcluded + runpath + runpath_origin_postexcluded + runpath_origin + runpath_parent_unresolved + runpath_search_postexcluded + runpath_search + runpath_unresolved + ) + +file(REMOVE "${CMAKE_BINARY_DIR}/test_rpath.c") +add_library(test_rpath SHARED "${CMAKE_BINARY_DIR}/test_rpath.c") +foreach(name ${test_rpath_names}) + file(WRITE "${CMAKE_BINARY_DIR}/${name}.c" "void ${name}(void) {}\n") + add_library(${name} SHARED "${CMAKE_BINARY_DIR}/${name}.c") + + file(APPEND "${CMAKE_BINARY_DIR}/test_rpath.c" "extern void ${name}(void);\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/test_rpath.c" "void test_rpath(void)\n{\n") +foreach(name ${test_rpath_names}) + file(APPEND "${CMAKE_BINARY_DIR}/test_rpath.c" " ${name}();\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/test_rpath.c" "}\n") + +install(TARGETS rpath_postexcluded DESTINATION lib/rpath_postexcluded) +install(TARGETS rpath DESTINATION lib/rpath) +install(TARGETS rpath_origin_postexcluded DESTINATION lib/rpath_origin_postexcluded) +install(TARGETS rpath_origin DESTINATION lib/rpath_origin) +install(TARGETS rpath_parent_postexcluded DESTINATION lib/rpath_parent_postexcluded) +install(TARGETS rpath rpath_origin rpath_parent DESTINATION lib/rpath_parent) +install(TARGETS rpath_search_postexcluded DESTINATION lib/rpath_search_postexcluded) +install(TARGETS rpath rpath_origin rpath_parent rpath_search DESTINATION lib/rpath_search) +install(TARGETS conflict DESTINATION lib/conflict) + +target_link_libraries(test_rpath PRIVATE ${test_rpath_names}) +set_property(TARGET test_rpath PROPERTY INSTALL_RPATH + "${CMAKE_BINARY_DIR}/root-all/lib/rpath_postexcluded" + "${CMAKE_BINARY_DIR}/root-all/lib/rpath" + "\$ORIGIN/rpath_origin_postexcluded" + "\${ORIGIN}/rpath_origin" + "${CMAKE_BINARY_DIR}/root-all/lib/conflict" + ) +target_link_options(test_rpath PRIVATE -Wl,--disable-new-dtags) + +file(REMOVE "${CMAKE_BINARY_DIR}/test_runpath.c") +add_library(test_runpath SHARED "${CMAKE_BINARY_DIR}/test_runpath.c") +foreach(name ${test_runpath_names} rpath conflict) + file(WRITE "${CMAKE_BINARY_DIR}/${name}.c" "void ${name}(void) {}\n") + if(NOT name MATCHES "^(rpath|conflict)$") + add_library(${name} SHARED "${CMAKE_BINARY_DIR}/${name}.c") + endif() + + file(APPEND "${CMAKE_BINARY_DIR}/test_runpath.c" "extern void ${name}(void);\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/test_runpath.c" "void test_runpath(void)\n{\n") +foreach(name ${test_runpath_names} rpath conflict) + file(APPEND "${CMAKE_BINARY_DIR}/test_runpath.c" " ${name}();\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/test_runpath.c" "}\n") + +install(TARGETS runpath_postexcluded DESTINATION lib/runpath_postexcluded) +install(TARGETS runpath DESTINATION lib/runpath) +install(TARGETS runpath_origin_postexcluded DESTINATION lib/runpath_origin_postexcluded) +install(TARGETS runpath_origin DESTINATION lib/runpath_origin) +install(TARGETS runpath_parent_unresolved DESTINATION lib/runpath_parent_unresolved) +install(TARGETS runpath_search_postexcluded DESTINATION lib/runpath_search_postexcluded) +install(TARGETS runpath runpath_origin runpath_search DESTINATION lib/runpath_search) +install(TARGETS conflict DESTINATION lib/conflict2) + +target_link_libraries(test_runpath PRIVATE ${test_runpath_names} rpath conflict) +set_property(TARGET test_runpath PROPERTY INSTALL_RPATH + "${CMAKE_BINARY_DIR}/root-all/lib/runpath/../rpath" # Ensure that files that don't conflict are treated correctly + "${CMAKE_BINARY_DIR}/root-all/lib/runpath_postexcluded" + "${CMAKE_BINARY_DIR}/root-all/lib/runpath" + "\${ORIGIN}/runpath_origin_postexcluded" + "\$ORIGIN/runpath_origin" + "${CMAKE_BINARY_DIR}/root-all/lib/conflict2" + ) +target_link_options(test_runpath PRIVATE -Wl,--enable-new-dtags) + +set_property(TARGET test_rpath ${test_rpath_names} test_runpath ${test_runpath_names} PROPERTY LIBRARY_OUTPUT_DIRECTORY lib) +install(TARGETS test_rpath test_runpath DESTINATION lib) + +add_executable(topexe file-GET_RUNTIME_DEPENDENCIES-linux/topexe.c) +add_library(toplib SHARED file-GET_RUNTIME_DEPENDENCIES-linux/toplib.c) +add_library(topmod MODULE file-GET_RUNTIME_DEPENDENCIES-linux/toplib.c) +target_link_libraries(topexe PRIVATE test_rpath test_runpath) +target_link_libraries(toplib PRIVATE test_rpath test_runpath) +target_link_libraries(topmod PRIVATE test_rpath test_runpath) +set_property(TARGET topexe toplib topmod PROPERTY INSTALL_RPATH + "${CMAKE_BINARY_DIR}/root-all/lib" + "${CMAKE_BINARY_DIR}/root-all/lib/rpath_parent_postexcluded" + "${CMAKE_BINARY_DIR}/root-all/lib/rpath_parent" + "${CMAKE_BINARY_DIR}/root-all/lib/runpath_parent_unresolved" + ) +target_link_options(topexe PRIVATE -Wl,--disable-new-dtags) +target_link_options(toplib PRIVATE -Wl,--disable-new-dtags) +target_link_options(topmod PRIVATE -Wl,--disable-new-dtags) + +install(TARGETS topexe toplib RUNTIME DESTINATION bin LIBRARY DESTINATION lib) +install(TARGETS topmod LIBRARY DESTINATION lib/modules) + +install(CODE [[ + function(exec_get_runtime_dependencies depsfile udepsfile cdepsfile) + file(GET_RUNTIME_DEPENDENCIES + RESOLVED_DEPENDENCIES_VAR deps + UNRESOLVED_DEPENDENCIES_VAR udeps + CONFLICTING_DEPENDENCIES_PREFIX cdeps + PRE_INCLUDE_REGEXES + "^lib(test_rpath|rpath_postexcluded|rpath|rpath_parent_postexcluded|rpath_parent|rpath_origin_postexcluded|rpath_origin|rpath_search_postexcluded|rpath_search|rpath_unresolved|test_runpath|runpath_postexcluded|runpath|runpath_origin_postexcluded|runpath_origin|runpath_parent_unresolved|runpath_search_postexcluded|runpath_search|runpath_unresolved|conflict)\\.so$" + "^libc\\.so" + PRE_EXCLUDE_REGEXES ".*" + POST_INCLUDE_REGEXES "^.*/(libtest_rpath|rpath/librpath|rpath_parent/librpath_parent|rpath_search/librpath_search|libtest_runpath|runpath/librunpath|runpath_origin_postexcluded|runpath_origin|runpath_search/librunpath_search|conflict2?/libconflict)\\.so$" + POST_EXCLUDE_REGEXES ".*" + DIRECTORIES + "${CMAKE_INSTALL_PREFIX}/lib/rpath_search_postexcluded" + "${CMAKE_INSTALL_PREFIX}/lib/rpath_search" + "${CMAKE_INSTALL_PREFIX}/lib/runpath_search_postexcluded" + "${CMAKE_INSTALL_PREFIX}/lib/runpath_search" + ${ARGN} + ) + list(SORT deps) + list(SORT udeps) + list(SORT cdeps_FILENAMES) + file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${depsfile}" "${deps}") + file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${udepsfile}" "${udeps}") + file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "") + foreach(cdep IN LISTS cdeps_FILENAMES) + set(cdep_values ${cdeps_${cdep}}) + list(SORT cdep_values) + file(APPEND "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "${cdep}:${cdep_values}\n") + endforeach() + endfunction() + + exec_get_runtime_dependencies( + deps1.txt udeps1.txt cdeps1.txt + EXECUTABLES + "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:topexe>" + ) + + exec_get_runtime_dependencies( + deps2.txt udeps2.txt cdeps2.txt + LIBRARIES + "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:toplib>" + ) + + exec_get_runtime_dependencies( + deps3.txt udeps3.txt cdeps3.txt + MODULES + "${CMAKE_INSTALL_PREFIX}/lib/modules/$<TARGET_FILE_NAME:topmod>" + ) + ]]) diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux/topexe.c b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux/topexe.c new file mode 100644 index 0000000..d196afe --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux/topexe.c @@ -0,0 +1,9 @@ +extern void test_rpath(void); +extern void test_runpath(void); + +int main(void) +{ + test_rpath(); + test_runpath(); + return 0; +} diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux/toplib.c b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux/toplib.c new file mode 100644 index 0000000..040e591 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux/toplib.c @@ -0,0 +1,8 @@ +extern void test_rpath(void); +extern void test_runpath(void); + +void toplib(void) +{ + test_rpath(); + test_runpath(); +} diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-all-check.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-all-check.cmake new file mode 100644 index 0000000..4d6dde1 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-all-check.cmake @@ -0,0 +1,157 @@ +function(check_contents filename contents_regex) + if(EXISTS "${CMAKE_INSTALL_PREFIX}/${filename}") + file(READ "${CMAKE_INSTALL_PREFIX}/${filename}" contents) + if(NOT contents MATCHES "${contents_regex}") + string(APPEND RunCMake_TEST_FAILED "File contents: + ${contents} +do not match what we expected: + ${contents_regex} +in file: + ${CMAKE_INSTALL_PREFIX}/${filename}\n") + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) + endif() + else() + string(APPEND RunCMake_TEST_FAILED "File ${CMAKE_INSTALL_PREFIX}/${filename} does not exist") + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) + endif() +endfunction() + +set(_check + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/bin/../lib/executable_path/libexecutable_path\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/bin/../lib/rpath_executable_path/librpath_executable_path\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]] + [[/usr/lib/libSystem\.B\.dylib]] + ) +check_contents(deps/deps1.txt "^${_check}$") + +set(_check + [[@executable_path/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]] + [[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]] + [[@rpath/librpath_executable_path_bundle\.dylib]] + [[@rpath/librpath_loader_path_unresolved\.dylib]] + [[@rpath/librpath_unresolved\.dylib]] + ) +check_contents(deps/udeps1.txt "^${_check}$") + +set(_check + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]] + [[/usr/lib/libSystem\.B\.dylib]] + ) +check_contents(deps/deps2.txt "^${_check}$") + +set(_check + [[@executable_path/../lib/executable_path/libexecutable_path\.dylib]] + [[@executable_path/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]] + [[@executable_path/../lib/executable_path_postexcluded/libexecutable_path_postexcluded\.dylib]] + [[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]] + [[@rpath/librpath_executable_path\.dylib]] + [[@rpath/librpath_executable_path_bundle\.dylib]] + [[@rpath/librpath_executable_path_postexcluded\.dylib]] + [[@rpath/librpath_loader_path_unresolved\.dylib]] + [[@rpath/librpath_unresolved\.dylib]] + ) +check_contents(deps/udeps2.txt "^${_check}$") + +set(_check + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]] + [[/usr/lib/libSystem\.B\.dylib]] + ) +check_contents(deps/deps3.txt "^${_check}$") + +set(_check + [[@executable_path/../lib/executable_path/libexecutable_path\.dylib]] + [[@executable_path/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]] + [[@executable_path/../lib/executable_path_postexcluded/libexecutable_path_postexcluded\.dylib]] + [[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]] + [[@rpath/librpath_executable_path\.dylib]] + [[@rpath/librpath_executable_path_bundle\.dylib]] + [[@rpath/librpath_executable_path_postexcluded\.dylib]] + [[@rpath/librpath_loader_path_unresolved\.dylib]] + [[@rpath/librpath_unresolved\.dylib]] + ) +check_contents(deps/udeps3.txt "^${_check}$") + +set(_check + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/bin/../lib/executable_path/libexecutable_path\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/bin/../lib/rpath_executable_path/librpath_executable_path\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]] + [[/usr/lib/libSystem\.B\.dylib]] + ) +check_contents(deps/deps4.txt "^${_check}$") + +set(_check + [[@executable_path/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]] + [[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]] + [[@rpath/librpath_executable_path_bundle\.dylib]] + [[@rpath/librpath_loader_path_unresolved\.dylib]] + [[@rpath/librpath_unresolved\.dylib]] + ) +check_contents(deps/udeps4.txt "^${_check}$") + +set(_check + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/bundle_executable/bin/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]] + [[/usr/lib/libSystem\.B\.dylib]] + ) +check_contents(deps/deps5.txt "^${_check}$") + +set(_check + [[@executable_path/../lib/executable_path/libexecutable_path\.dylib]] + [[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]] + [[@rpath/librpath_executable_path\.dylib]] + [[@rpath/librpath_executable_path_bundle\.dylib]] + [[@rpath/librpath_loader_path_unresolved\.dylib]] + [[@rpath/librpath_unresolved\.dylib]] + ) +check_contents(deps/udeps5.txt "^${_check}$") + +set(_check + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/bundle_executable/bin/../lib/executable_path_bundle/libexecutable_path_bundle\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/libtestlib\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/loader_path/libloader_path\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/../rpath/librpath\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/normal/libnormal\.dylib]] + [[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/rpath_loader_path/librpath_loader_path\.dylib]] + [[/usr/lib/libSystem\.B\.dylib]] + ) +check_contents(deps/deps6.txt "^${_check}$") + +set(_check + [[@executable_path/../lib/executable_path/libexecutable_path\.dylib]] + [[@loader_path/loader_path_unresolved/libloader_path_unresolved\.dylib]] + [[@rpath/librpath_executable_path\.dylib]] + [[@rpath/librpath_executable_path_bundle\.dylib]] + [[@rpath/librpath_loader_path_unresolved\.dylib]] + [[@rpath/librpath_unresolved\.dylib]] + ) +check_contents(deps/udeps6.txt "^${_check}$") + +set(_check + "^libconflict\\.dylib:[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/conflict/libconflict\\.dylib;[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-build/root-all/executable/lib/conflict2/libconflict\\.dylib\n$" + ) +check_contents(deps/cdeps1.txt "${_check}") +check_contents(deps/cdeps2.txt "${_check}") +check_contents(deps/cdeps3.txt "${_check}") +check_contents(deps/cdeps4.txt "${_check}") +check_contents(deps/cdeps5.txt "${_check}") +check_contents(deps/cdeps6.txt "${_check}") diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-all-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-all-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-all-stderr.txt new file mode 100644 index 0000000..bc9e97a --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-all-stderr.txt @@ -0,0 +1,7 @@ +^CMake Error at cmake_install\.cmake:[0-9]+ \(file\): + file Multiple conflicting paths found for librpath\.dylib: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-build/root-all/lib/rpath1/librpath\.dylib + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict-build/root-all/lib/rpath2/librpath\.dylib$ diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict.cmake new file mode 100644 index 0000000..a8446fe --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-conflict.cmake @@ -0,0 +1,55 @@ +enable_language(C) + +set(test1_names rpath) +set(test2_names rpath) + +file(WRITE "${CMAKE_BINARY_DIR}/rpath.c" "void rpath(void) {}\n") +add_library(rpath SHARED "${CMAKE_BINARY_DIR}/rpath.c") +set_property(TARGET rpath PROPERTY INSTALL_NAME_DIR @rpath) +install(TARGETS rpath DESTINATION lib/rpath1) +install(TARGETS rpath DESTINATION lib/rpath2) + +file(REMOVE "${CMAKE_BINARY_DIR}/test1.c") +add_library(test1 SHARED "${CMAKE_BINARY_DIR}/test1.c") +foreach(name ${test1_names}) + file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "extern void ${name}(void);\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "void test1(void)\n{\n") +foreach(name ${test1_names}) + file(APPEND "${CMAKE_BINARY_DIR}/test1.c" " ${name}();\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "}\n") + +target_link_libraries(test1 PRIVATE ${test1_names}) +set_property(TARGET test1 PROPERTY INSTALL_RPATH + "${CMAKE_BINARY_DIR}/root-all/lib/rpath1" + ) + +file(REMOVE "${CMAKE_BINARY_DIR}/test2.c") +add_library(test2 SHARED "${CMAKE_BINARY_DIR}/test2.c") +foreach(name ${test2_names}) + file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "extern void ${name}(void);\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "void test2(void)\n{\n") +foreach(name ${test2_names}) + file(APPEND "${CMAKE_BINARY_DIR}/test2.c" " ${name}();\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "}\n") + +target_link_libraries(test2 PRIVATE ${test2_names}) +set_property(TARGET test2 PROPERTY INSTALL_RPATH + "${CMAKE_BINARY_DIR}/root-all/lib/rpath2" + ) + +install(TARGETS test1 test2 DESTINATION lib) + +install(CODE [[ + file(GET_RUNTIME_DEPENDENCIES + LIBRARIES + "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test1>" + "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test2>" + PRE_INCLUDE_REGEXES "^@rpath/librpath\\.dylib$" + PRE_EXCLUDE_REGEXES ".*" + ) + message(FATAL_ERROR "This message should not be displayed") + ]]) diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile-all-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile-all-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile-all-stderr.txt new file mode 100644 index 0000000..73ab9f1 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile-all-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at cmake_install\.cmake:[0-9]+ \(file\): + file Failed to run otool on: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile-build/root-all/bin/\.\./lib/libtest\.dylib$ diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile.cmake new file mode 100644 index 0000000..3e4c434 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-notfile.cmake @@ -0,0 +1,30 @@ +enable_language(C) + +file(WRITE "${CMAKE_BINARY_DIR}/test.c" "void test(void) {}\n") +file(WRITE "${CMAKE_BINARY_DIR}/main.c" [[extern void test(void); + +int main(void) +{ + test(); + return 0; +} +]]) + +add_library(test SHARED "${CMAKE_BINARY_DIR}/test.c") +set_property(TARGET test PROPERTY INSTALL_NAME_DIR @rpath) +add_executable(exe "${CMAKE_BINARY_DIR}/main.c") +target_link_libraries(exe PRIVATE test) +set_property(TARGET exe PROPERTY INSTALL_RPATH "@loader_path/../lib") + +install(TARGETS exe DESTINATION bin) + +install(CODE [[ + file(MAKE_DIRECTORY "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:test>") + file(GET_RUNTIME_DEPENDENCIES + EXECUTABLES + "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:exe>" + PRE_INCLUDE_REGEXES "^@rpath/libtest\\.dylib$" + PRE_EXCLUDE_REGEXES ".*" + ) + message(FATAL_ERROR "This message should not be displayed") + ]]) diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved-all-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved-all-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved-all-stderr.txt new file mode 100644 index 0000000..01762b4 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved-all-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error at cmake_install\.cmake:[0-9]+ \(file\): + file Could not resolve file @rpath/libunresolved\.dylib$ diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved.cmake new file mode 100644 index 0000000..c9b6c95 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos-unresolved.cmake @@ -0,0 +1,18 @@ +enable_language(C) + +file(WRITE "${CMAKE_BINARY_DIR}/testlib.c" "extern void unresolved(void);\nvoid testlib(void)\n{\n unresolved();\n}\n") +add_library(testlib SHARED "${CMAKE_BINARY_DIR}/testlib.c") +file(WRITE "${CMAKE_BINARY_DIR}/unresolved.c" "void unresolved(void) {}\n") +add_library(unresolved SHARED "${CMAKE_BINARY_DIR}/unresolved.c") +target_link_libraries(testlib PRIVATE unresolved) +install(TARGETS testlib DESTINATION lib) + +install(CODE [[ + file(GET_RUNTIME_DEPENDENCIES + PRE_INCLUDE_REGEXES "^@rpath/libunresolved\\.dylib$" + PRE_EXCLUDE_REGEXES ".*" + LIBRARIES + "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:testlib>" + ) + message(FATAL_ERROR "This message should not be displayed") + ]]) diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos.cmake new file mode 100644 index 0000000..6db05b3 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos.cmake @@ -0,0 +1,216 @@ +enable_language(C) + +set(testlib_names + preexcluded + executable_path + executable_path_bundle + executable_path_postexcluded + loader_path + loader_path_unresolved + loader_path_postexcluded + rpath + rpath_unresolved + rpath_postexcluded + rpath_executable_path + rpath_executable_path_bundle + rpath_executable_path_postexcluded + rpath_loader_path + rpath_loader_path_unresolved + rpath_loader_path_postexcluded + normal + normal_unresolved + normal_postexcluded + conflict + ) + +file(REMOVE "${CMAKE_BINARY_DIR}/testlib.c") +add_library(testlib SHARED "${CMAKE_BINARY_DIR}/testlib.c") +foreach(name ${testlib_names}) + if(name STREQUAL "normal") + file(WRITE "${CMAKE_BINARY_DIR}/normal.c" "extern void rpath(void);\nvoid normal(void)\n{\n rpath();\n}\n") + else() + file(WRITE "${CMAKE_BINARY_DIR}/${name}.c" "void ${name}(void) {}\n") + endif() + add_library(${name} SHARED "${CMAKE_BINARY_DIR}/${name}.c") + + file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "extern void ${name}(void);\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "void testlib(void)\n{\n") +foreach(name ${testlib_names}) + file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" " ${name}();\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "}\n") +set_property(TARGET ${testlib_names} PROPERTY BUILD_WITH_INSTALL_NAME_DIR 1) +target_link_libraries(normal PRIVATE rpath) +set_property(TARGET normal PROPERTY INSTALL_RPATH + "${CMAKE_BINARY_DIR}/root-all/executable/lib/normal/../rpath" + ) + +file(WRITE "${CMAKE_BINARY_DIR}/testlib_conflict.c" "extern void conflict(void);\nvoid testlib_conflict(void)\n{\n conflict();\n}\n") +add_library(testlib_conflict SHARED "${CMAKE_BINARY_DIR}/testlib_conflict.c") +target_link_libraries(testlib_conflict PRIVATE conflict) + +set_property(TARGET testlib PROPERTY INSTALL_RPATH + "${CMAKE_BINARY_DIR}/root-all/executable/lib/rpath" + "${CMAKE_BINARY_DIR}/root-all/executable/lib/rpath_unresolved" + "${CMAKE_BINARY_DIR}/root-all/executable/lib/rpath_postexcluded" + "${CMAKE_BINARY_DIR}/root-all/executable/lib/conflict" + @executable_path/../lib/rpath_executable_path + @executable_path/../lib/rpath_executable_path_unresolved + @executable_path/../lib/rpath_executable_path_postexcluded + @loader_path/rpath_loader_path + @loader_path/rpath_loader_path_unresolved + @loader_path/rpath_loader_path_postexcluded + ) +set_property(TARGET testlib_conflict PROPERTY INSTALL_RPATH + "${CMAKE_BINARY_DIR}/root-all/executable/lib/conflict2" + ) + +foreach(t + executable_path + executable_path_postexcluded + loader_path + loader_path_postexcluded + rpath + rpath_postexcluded + rpath_executable_path + rpath_executable_path_postexcluded + rpath_loader_path + rpath_loader_path_postexcluded + conflict + ) + install(TARGETS ${t} DESTINATION executable/lib/${t}) +endforeach() +install(TARGETS conflict DESTINATION executable/lib/conflict2) + +foreach(t + executable_path_bundle + executable_path_postexcluded + loader_path_postexcluded + rpath_postexcluded + rpath_executable_path_bundle + rpath_executable_path_postexcluded + rpath_loader_path_postexcluded + ) + install(TARGETS ${t} DESTINATION bundle_executable/lib/${t}) +endforeach() + +foreach(t executable_path executable_path_bundle executable_path_postexcluded) + set_property(TARGET ${t} PROPERTY INSTALL_NAME_DIR @executable_path/../lib/${t}) +endforeach() + +foreach(t loader_path loader_path_unresolved loader_path_postexcluded) + set_property(TARGET ${t} PROPERTY INSTALL_NAME_DIR @loader_path/${t}) +endforeach() + +foreach(t + rpath + rpath_unresolved + rpath_postexcluded + rpath_executable_path + rpath_executable_path_bundle + rpath_executable_path_postexcluded + rpath_loader_path + rpath_loader_path_unresolved + rpath_loader_path_postexcluded + conflict + ) + set_property(TARGET ${t} PROPERTY INSTALL_NAME_DIR @rpath) +endforeach() + +foreach(t normal normal_unresolved normal_postexcluded) + set_property(TARGET ${t} PROPERTY INSTALL_NAME_DIR "${CMAKE_BINARY_DIR}/root-all/executable/lib/${t}") + if(NOT t STREQUAL "normal_unresolved") + install(TARGETS ${t} DESTINATION executable/lib/${t}) + endif() +endforeach() + +target_link_libraries(testlib PRIVATE ${testlib_names}) + +add_executable(topexe file-GET_RUNTIME_DEPENDENCIES-macos/topexe.c) +add_library(toplib SHARED file-GET_RUNTIME_DEPENDENCIES-macos/toplib.c) +add_library(topmod MODULE file-GET_RUNTIME_DEPENDENCIES-macos/toplib.c) +target_link_libraries(topexe PRIVATE testlib) +target_link_libraries(toplib PRIVATE testlib) +target_link_libraries(topmod PRIVATE testlib) + +set_property(TARGET topexe toplib topmod PROPERTY INSTALL_RPATH "${CMAKE_BINARY_DIR}/root-all/executable/lib") + +install(TARGETS topexe toplib topmod testlib testlib_conflict RUNTIME DESTINATION executable/bin LIBRARY DESTINATION executable/lib) +install(TARGETS topexe toplib topmod testlib testlib_conflict RUNTIME DESTINATION bundle_executable/bin LIBRARY DESTINATION bundle_executable/lib) + +install(CODE [[ + function(exec_get_runtime_dependencies depsfile udepsfile cdepsfile) + file(GET_RUNTIME_DEPENDENCIES + RESOLVED_DEPENDENCIES_VAR deps + UNRESOLVED_DEPENDENCIES_VAR udeps + CONFLICTING_DEPENDENCIES_PREFIX cdeps + PRE_INCLUDE_REGEXES "^.*/lib(testlib|executable_path|executable_path_bundle|executable_path_postexcluded|loader_path|loader_path_unresolved|loader_path_postexcluded|rpath|rpath_unresolved|rpath_postexcluded|rpath_executable_path|rpath_executable_path_bundle|rpath_executable_path_postexcluded|rpath_loader_path|rpath_loader_path_unresolved|rpath_loader_path_postexcluded|normal|normal_unresolved|normal_postexcluded|conflict|System\\.B)\\.dylib$" + PRE_EXCLUDE_REGEXES ".*" + POST_INCLUDE_REGEXES "^.*/lib(testlib|executable_path|executable_path_bundle|loader_path|rpath|rpath_executable_path|rpath_executable_path_bundle|rpath_loader_path|normal|conflict|System\\.B)\\.dylib$" + POST_EXCLUDE_REGEXES ".*" + ${ARGN} + ) + list(SORT deps) + list(SORT udeps) + list(SORT cdeps_FILENAMES) + file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${depsfile}" "${deps}") + file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${udepsfile}" "${udeps}") + file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "") + foreach(cdep IN LISTS cdeps_FILENAMES) + set(cdep_values ${cdeps_${cdep}}) + list(SORT cdep_values) + file(APPEND "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "${cdep}:${cdep_values}\n") + endforeach() + endfunction() + + exec_get_runtime_dependencies( + deps1.txt udeps1.txt cdeps1.txt + EXECUTABLES + "${CMAKE_INSTALL_PREFIX}/executable/bin/$<TARGET_FILE_NAME:topexe>" + LIBRARIES + "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>" + ) + + exec_get_runtime_dependencies( + deps2.txt udeps2.txt cdeps2.txt + LIBRARIES + "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:toplib>" + "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>" + ) + + exec_get_runtime_dependencies( + deps3.txt udeps3.txt cdeps3.txt + MODULES + "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:topmod>" + LIBRARIES + "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>" + ) + + exec_get_runtime_dependencies( + deps4.txt udeps4.txt cdeps4.txt + EXECUTABLES + "${CMAKE_INSTALL_PREFIX}/executable/bin/$<TARGET_FILE_NAME:topexe>" + LIBRARIES + "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>" + BUNDLE_EXECUTABLE + "${CMAKE_INSTALL_PREFIX}/bundle_executable/bin/$<TARGET_FILE_NAME:topexe>" + ) + + exec_get_runtime_dependencies( + deps5.txt udeps5.txt cdeps5.txt + LIBRARIES + "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:toplib>" + "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>" + BUNDLE_EXECUTABLE "${CMAKE_INSTALL_PREFIX}/bundle_executable/bin/$<TARGET_FILE_NAME:topexe>" + ) + + exec_get_runtime_dependencies( + deps6.txt udeps6.txt cdeps6.txt + MODULES + "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:topmod>" + LIBRARIES + "${CMAKE_INSTALL_PREFIX}/executable/lib/$<TARGET_FILE_NAME:testlib_conflict>" + BUNDLE_EXECUTABLE "${CMAKE_INSTALL_PREFIX}/bundle_executable/bin/$<TARGET_FILE_NAME:topexe>" + ) + ]]) diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos/topexe.c b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos/topexe.c new file mode 100644 index 0000000..20c6087 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos/topexe.c @@ -0,0 +1,7 @@ +extern void testlib(void); + +int main(void) +{ + testlib(); + return 0; +} diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos/toplib.c b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos/toplib.c new file mode 100644 index 0000000..cff1bff --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-macos/toplib.c @@ -0,0 +1,6 @@ +extern void testlib(void); + +void toplib(void) +{ + testlib(); +} diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-project-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-project-stderr.txt new file mode 100644 index 0000000..d506645 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-project-stderr.txt @@ -0,0 +1,13 @@ +^CMake Warning \(dev\) at file-GET_RUNTIME_DEPENDENCIES-project\.cmake:[0-9]+ \(file\): + You have used file\(GET_RUNTIME_DEPENDENCIES\) in project mode\. This is + probably not what you intended to do\. Instead, please consider using it in + an install\(CODE\) or install\(SCRIPT\) command\. For example: + + install\(CODE \[\[ + file\(GET_RUNTIME_DEPENDENCIES + # \.\.\. + \) + ]]\) +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\.$ diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-project.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-project.cmake new file mode 100644 index 0000000..842d7ab --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-project.cmake @@ -0,0 +1 @@ +file(GET_RUNTIME_DEPENDENCIES RESOLVED_DEPENDENCIES_VAR deps) diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported-stderr.txt new file mode 100644 index 0000000..3db835c --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at file-GET_RUNTIME_DEPENDENCIES-unsupported\.cmake:[0-9]+ \(file\): + file GET_RUNTIME_DEPENDENCIES is not supported on system "[^ + ]+" +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported.cmake new file mode 100644 index 0000000..b91eefe --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-unsupported.cmake @@ -0,0 +1,2 @@ +file(GET_RUNTIME_DEPENDENCIES RESOLVED_DEPENDENCIES_VAR deps) +message(FATAL_ERROR "This message should not be displayed") diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-all-check.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-all-check.cmake new file mode 100644 index 0000000..c120ce4 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-all-check.cmake @@ -0,0 +1,38 @@ +function(check_contents filename contents_regex) + if(EXISTS "${CMAKE_INSTALL_PREFIX}/${filename}") + file(READ "${CMAKE_INSTALL_PREFIX}/${filename}" contents) + if(NOT contents MATCHES "${contents_regex}") + string(APPEND RunCMake_TEST_FAILED "File contents: + ${contents} +do not match what we expected: + ${contents_regex} +in file: + ${CMAKE_INSTALL_PREFIX}/${filename}\n") + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) + endif() + else() + string(APPEND RunCMake_TEST_FAILED "File ${CMAKE_INSTALL_PREFIX}/${filename} does not exist") + set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE) + endif() +endfunction() + +set(_check + [=[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-build/root-all/bin/\.conflict/\.\./(lib)?libdir\.dll]=] + [=[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-build/root-all/bin/\.search/(lib)?search\.dll]=] + [=[[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-build/root-all/bin/(lib)?testlib\.dll]=] + ) +check_contents(deps/deps1.txt "^${_check}$") +check_contents(deps/deps2.txt "^${_check}$") +check_contents(deps/deps3.txt "^${_check}$") +set(_check + [=[(lib)?unresolved\.dll]=] + ) +check_contents(deps/udeps1.txt "^${_check}$") +check_contents(deps/udeps2.txt "^${_check}$") +check_contents(deps/udeps3.txt "^${_check}$") +set(_check + "^(lib)?conflict\\.dll:[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-build/root-all/bin/\\.conflict/(lib)?conflict\\.dll;[^;]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-build/root-all/bin/(lib)?conflict\\.dll\n$" + ) +check_contents(deps/cdeps1.txt "${_check}") +check_contents(deps/cdeps2.txt "${_check}") +check_contents(deps/cdeps3.txt "${_check}") diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-all-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-all-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-all-stderr.txt new file mode 100644 index 0000000..66ecb93 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-all-stderr.txt @@ -0,0 +1,7 @@ +^CMake Error at cmake_install\.cmake:[0-9]+ \(file\): + file Multiple conflicting paths found for (lib)?path\.dll: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-build/root-all/lib/test1/(lib)?path\.dll + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict-build/root-all/lib/test2/(lib)?path\.dll$ diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict.cmake new file mode 100644 index 0000000..d413443 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-conflict.cmake @@ -0,0 +1,47 @@ +enable_language(C) + +set(test1_names path) +set(test2_names path) + +file(WRITE "${CMAKE_BINARY_DIR}/path.c" "__declspec(dllexport) void path(void) {}\n") +add_library(path SHARED "${CMAKE_BINARY_DIR}/path.c") + +file(REMOVE "${CMAKE_BINARY_DIR}/test1.c") +add_library(test1 SHARED "${CMAKE_BINARY_DIR}/test1.c") +foreach(name ${test1_names}) + file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "__declspec(dllimport) extern void ${name}(void);\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "__declspec(dllexport) void test1(void)\n{\n") +foreach(name ${test1_names}) + file(APPEND "${CMAKE_BINARY_DIR}/test1.c" " ${name}();\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/test1.c" "}\n") + +target_link_libraries(test1 PRIVATE ${test1_names}) + +file(REMOVE "${CMAKE_BINARY_DIR}/test2.c") +add_library(test2 SHARED "${CMAKE_BINARY_DIR}/test2.c") +foreach(name ${test2_names}) + file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "__declspec(dllimport) extern void ${name}(void);\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "__declspec(dllexport) void test2(void)\n{\n") +foreach(name ${test2_names}) + file(APPEND "${CMAKE_BINARY_DIR}/test2.c" " ${name}();\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/test2.c" "}\n") + +target_link_libraries(test2 PRIVATE ${test2_names}) + +install(TARGETS test1 path DESTINATION lib/test1) +install(TARGETS test2 path DESTINATION lib/test2) + +install(CODE [[ + file(GET_RUNTIME_DEPENDENCIES + LIBRARIES + "${CMAKE_INSTALL_PREFIX}/lib/test1/$<TARGET_FILE_NAME:test1>" + "${CMAKE_INSTALL_PREFIX}/lib/test2/$<TARGET_FILE_NAME:test2>" + PRE_INCLUDE_REGEXES "^(lib)?path\\.dll$" + PRE_EXCLUDE_REGEXES ".*" + ) + message(FATAL_ERROR "This message should not be displayed") + ]]) diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile-all-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile-all-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile-all-stderr.txt new file mode 100644 index 0000000..f921409 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile-all-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at cmake_install\.cmake:[0-9]+ \(file\): + file Failed to run (dumpbin|objdump) on: + + [^ +]*/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile-build/root-all/bin/(lib)?test\.dll$ diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile.cmake new file mode 100644 index 0000000..6665a3b --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-notfile.cmake @@ -0,0 +1,28 @@ +enable_language(C) + +file(WRITE "${CMAKE_BINARY_DIR}/test.c" "__declspec(dllexport) void test(void) {}\n") +file(WRITE "${CMAKE_BINARY_DIR}/main.c" [[__declspec(dllimport) extern void test(void); + +int main(void) +{ + test(); + return 0; +} +]]) + +add_library(test SHARED "${CMAKE_BINARY_DIR}/test.c") +add_executable(exe "${CMAKE_BINARY_DIR}/main.c") +target_link_libraries(exe PRIVATE test) + +install(TARGETS exe DESTINATION bin) + +install(CODE [[ + file(MAKE_DIRECTORY "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:test>") + file(GET_RUNTIME_DEPENDENCIES + EXECUTABLES + "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:exe>" + PRE_INCLUDE_REGEXES "^(lib)?test\\.dll$" + PRE_EXCLUDE_REGEXES ".*" + ) + message(FATAL_ERROR "This message should not be displayed") + ]]) diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved-all-result.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved-all-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved-all-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved-all-stderr.txt b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved-all-stderr.txt new file mode 100644 index 0000000..a20654c --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved-all-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error at cmake_install\.cmake:[0-9]+ \(file\): + file Could not resolve file (lib)?unresolved\.dll$ diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved.cmake new file mode 100644 index 0000000..4cc74c7 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows-unresolved.cmake @@ -0,0 +1,18 @@ +enable_language(C) + +file(WRITE "${CMAKE_BINARY_DIR}/testlib.c" "__declspec(dllimport) extern void unresolved(void);\n__declspec(dllexport) void testlib(void)\n{\n unresolved();\n}\n") +add_library(testlib SHARED "${CMAKE_BINARY_DIR}/testlib.c") +file(WRITE "${CMAKE_BINARY_DIR}/unresolved.c" "__declspec(dllexport) void unresolved(void) {}\n") +add_library(unresolved SHARED "${CMAKE_BINARY_DIR}/unresolved.c") +target_link_libraries(testlib PRIVATE unresolved) +install(TARGETS testlib DESTINATION lib) + +install(CODE [[ + file(GET_RUNTIME_DEPENDENCIES + PRE_INCLUDE_REGEXES "^(lib)?unresolved\\.dll$" + PRE_EXCLUDE_REGEXES ".*" + LIBRARIES + "${CMAKE_INSTALL_PREFIX}/lib/$<TARGET_FILE_NAME:testlib>" + ) + message(FATAL_ERROR "This message should not be displayed") + ]]) diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows.cmake new file mode 100644 index 0000000..19288d8 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows.cmake @@ -0,0 +1,114 @@ +enable_language(C) + +set(testlib_names + preexcluded + libdir_postexcluded + libdir + search_postexcluded + search + unresolved + conflict + ) + +file(REMOVE "${CMAKE_BINARY_DIR}/testlib.c") +add_library(testlib SHARED "${CMAKE_BINARY_DIR}/testlib.c") +foreach(name ${testlib_names}) + file(WRITE "${CMAKE_BINARY_DIR}/${name}.c" "__declspec(dllexport) void ${name}(void) {}\n") + add_library(${name} SHARED "${CMAKE_BINARY_DIR}/${name}.c") + + file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "__declspec(dllimport) extern void ${name}(void);\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "__declspec(dllexport) void testlib(void)\n{\n") +foreach(name ${testlib_names}) + file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" " ${name}();\n") +endforeach() +file(APPEND "${CMAKE_BINARY_DIR}/testlib.c" "}\n") + +target_link_libraries(testlib PRIVATE ${testlib_names}) + +file(WRITE "${CMAKE_BINARY_DIR}/testlib_conflict.c" "__declspec(dllimport) extern void conflict(void);\n__declspec(dllexport) void testlib_conflict(void)\n{\n conflict();\n}\n") +add_library(testlib_conflict SHARED "${CMAKE_BINARY_DIR}/testlib_conflict.c") +target_link_libraries(testlib_conflict PRIVATE conflict) + +file(WRITE "${CMAKE_BINARY_DIR}/testlib_noconflict.c" "__declspec(dllimport) extern void libdir(void);\n__declspec(dllexport) void testlib_noconflict(void)\n{\n libdir();\n}\n") +add_library(testlib_noconflict SHARED "${CMAKE_BINARY_DIR}/testlib_noconflict.c") +target_link_libraries(testlib_noconflict PRIVATE libdir) + +install(TARGETS testlib libdir_postexcluded libdir conflict testlib_noconflict DESTINATION bin) +install(TARGETS libdir search_postexcluded search DESTINATION bin/.search) # Prefixing with "." ensures it is the first item after list(SORT) +install(TARGETS testlib_conflict conflict DESTINATION bin/.conflict) + +add_executable(topexe file-GET_RUNTIME_DEPENDENCIES-windows/topexe.c) +add_library(toplib SHARED file-GET_RUNTIME_DEPENDENCIES-windows/toplib.c) +add_library(topmod MODULE file-GET_RUNTIME_DEPENDENCIES-windows/toplib.c) +target_link_libraries(topexe PRIVATE testlib) +target_link_libraries(toplib PRIVATE testlib) +target_link_libraries(topmod PRIVATE testlib) + +install(TARGETS topexe toplib topmod DESTINATION bin) + +install(CODE [[ + function(exec_get_runtime_dependencies depsfile udepsfile cdepsfile) + file(GET_RUNTIME_DEPENDENCIES + RESOLVED_DEPENDENCIES_VAR deps + UNRESOLVED_DEPENDENCIES_VAR udeps + CONFLICTING_DEPENDENCIES_PREFIX cdeps + PRE_INCLUDE_REGEXES + "^(lib)?testlib\\.dll$" + "^(lib)?libdir_postexcluded\\.dll$" + "^(lib)?libdir\\.dll$" + "^(lib)?search_postexcluded\\.dll$" + "^(lib)?search\\.dll$" + "^(lib)?unresolved\\.dll$" + "^(lib)?conflict\\.dll$" + "^kernel32\\.dll$" + PRE_EXCLUDE_REGEXES ".*" + POST_INCLUDE_REGEXES + "^.*/(lib)?testlib\\.dll$" + "^.*/(lib)?libdir\\.dll$" + "^.*/(lib)?search\\.dll$" + "^.*/(lib)?conflict\\.dll$" + POST_EXCLUDE_REGEXES ".*" + DIRECTORIES + "${CMAKE_INSTALL_PREFIX}/bin/.search" + ${ARGN} + ) + list(SORT deps) + list(SORT udeps) + list(SORT cdeps_FILENAMES) + file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${depsfile}" "${deps}") + file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${udepsfile}" "${udeps}") + file(WRITE "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "") + foreach(cdep IN LISTS cdeps_FILENAMES) + set(cdep_values ${cdeps_${cdep}}) + list(SORT cdep_values) + file(APPEND "${CMAKE_INSTALL_PREFIX}/deps/${cdepsfile}" "${cdep}:${cdep_values}\n") + endforeach() + endfunction() + + exec_get_runtime_dependencies( + deps1.txt udeps1.txt cdeps1.txt + EXECUTABLES + "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:topexe>" + LIBRARIES + "${CMAKE_INSTALL_PREFIX}/bin/.conflict/$<TARGET_FILE_NAME:testlib_conflict>" + "${CMAKE_INSTALL_PREFIX}/bin/.conflict/../$<TARGET_FILE_NAME:testlib_noconflict>" + ) + + exec_get_runtime_dependencies( + deps2.txt udeps2.txt cdeps2.txt + LIBRARIES + "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:toplib>" + "${CMAKE_INSTALL_PREFIX}/bin/.conflict/$<TARGET_FILE_NAME:testlib_conflict>" + "${CMAKE_INSTALL_PREFIX}/bin/.conflict/../$<TARGET_FILE_NAME:testlib_noconflict>" + ) + + exec_get_runtime_dependencies( + deps3.txt udeps3.txt cdeps3.txt + MODULES + "${CMAKE_INSTALL_PREFIX}/bin/$<TARGET_FILE_NAME:topmod>" + LIBRARIES + "${CMAKE_INSTALL_PREFIX}/bin/.conflict/$<TARGET_FILE_NAME:testlib_conflict>" + "${CMAKE_INSTALL_PREFIX}/bin/.conflict/../$<TARGET_FILE_NAME:testlib_noconflict>" + ) + ]]) diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows/topexe.c b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows/topexe.c new file mode 100644 index 0000000..713b8eb --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows/topexe.c @@ -0,0 +1,7 @@ +__declspec(dllimport) extern void testlib(void); + +int main(void) +{ + testlib(); + return 0; +} diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows/toplib.c b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows/toplib.c new file mode 100644 index 0000000..6997175 --- /dev/null +++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-windows/toplib.c @@ -0,0 +1,6 @@ +__declspec(dllimport) extern void testlib(void); + +__declspec(dllexport) void toplib(void) +{ + testlib(); +} diff --git a/Tests/RunCMake/math/MATH-InvalidExpression-stderr.txt b/Tests/RunCMake/math/MATH-InvalidExpression-stderr.txt index 9e73ed5..22226f2 100644 --- a/Tests/RunCMake/math/MATH-InvalidExpression-stderr.txt +++ b/Tests/RunCMake/math/MATH-InvalidExpression-stderr.txt @@ -1,5 +1,5 @@ ^CMake Error at MATH-InvalidExpression.cmake:1 \(math\): - math cannot parse the expression: "INVALID": syntax error, unexpected \$end, - expecting exp_PLUS or exp_MINUS or exp_OPENPARENT or exp_NUMBER \(7\). + math cannot parse the expression: "INVALID": syntax error, unexpected \$end + \(7\). Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\)$ 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) diff --git a/Tests/RunCMake/project/CMP0048-NEW.cmake b/Tests/RunCMake/project/CMP0048-NEW.cmake index 7e16b70..b6e80ac 100644 --- a/Tests/RunCMake/project/CMP0048-NEW.cmake +++ b/Tests/RunCMake/project/CMP0048-NEW.cmake @@ -1,9 +1,4 @@ -macro(print_versions name) - foreach(v "" _MAJOR _MINOR _PATCH _TWEAK) - message(STATUS "PROJECT_VERSION${v}='${PROJECT_VERSION${v}}'") - message(STATUS "${name}_VERSION${v}='${${name}_VERSION${v}}'") - endforeach() -endmacro() +include(PrintVersions.cmake) cmake_policy(SET CMP0048 NEW) diff --git a/Tests/RunCMake/project/CMP0096-NEW-stdout.txt b/Tests/RunCMake/project/CMP0096-NEW-stdout.txt new file mode 100644 index 0000000..f6b999a --- /dev/null +++ b/Tests/RunCMake/project/CMP0096-NEW-stdout.txt @@ -0,0 +1,30 @@ +-- PROJECT_VERSION='2019.07.06' +-- DateVersion_VERSION='2019.07.06' +-- PROJECT_VERSION_MAJOR='2019' +-- DateVersion_VERSION_MAJOR='2019' +-- PROJECT_VERSION_MINOR='07' +-- DateVersion_VERSION_MINOR='07' +-- PROJECT_VERSION_PATCH='06' +-- DateVersion_VERSION_PATCH='06' +-- PROJECT_VERSION_TWEAK='' +-- DateVersion_VERSION_TWEAK='' +-- PROJECT_VERSION='4294967297' +-- LongVersion_VERSION='4294967297' +-- PROJECT_VERSION_MAJOR='4294967297' +-- LongVersion_VERSION_MAJOR='4294967297' +-- PROJECT_VERSION_MINOR='' +-- LongVersion_VERSION_MINOR='' +-- PROJECT_VERSION_PATCH='' +-- LongVersion_VERSION_PATCH='' +-- PROJECT_VERSION_TWEAK='' +-- LongVersion_VERSION_TWEAK='' +-- PROJECT_VERSION='0009999999999.0009999999999.0009999999999.0009999999999' +-- VeryLongVersion_VERSION='0009999999999.0009999999999.0009999999999.0009999999999' +-- PROJECT_VERSION_MAJOR='0009999999999' +-- VeryLongVersion_VERSION_MAJOR='0009999999999' +-- PROJECT_VERSION_MINOR='0009999999999' +-- VeryLongVersion_VERSION_MINOR='0009999999999' +-- PROJECT_VERSION_PATCH='0009999999999' +-- VeryLongVersion_VERSION_PATCH='0009999999999' +-- PROJECT_VERSION_TWEAK='0009999999999' +-- VeryLongVersion_VERSION_TWEAK='0009999999999' diff --git a/Tests/RunCMake/project/CMP0096-NEW.cmake b/Tests/RunCMake/project/CMP0096-NEW.cmake new file mode 100644 index 0000000..e2cdd20 --- /dev/null +++ b/Tests/RunCMake/project/CMP0096-NEW.cmake @@ -0,0 +1,6 @@ +cmake_policy(SET CMP0048 NEW) +cmake_policy(SET CMP0096 NEW) +include(CMP0096-common.cmake) + +project(VeryLongVersion VERSION 0009999999999.0009999999999.0009999999999.0009999999999 LANGUAGES NONE) +print_versions(VeryLongVersion) diff --git a/Tests/RunCMake/project/CMP0096-OLD-stdout.txt b/Tests/RunCMake/project/CMP0096-OLD-stdout.txt new file mode 100644 index 0000000..6a945ce --- /dev/null +++ b/Tests/RunCMake/project/CMP0096-OLD-stdout.txt @@ -0,0 +1,20 @@ +-- PROJECT_VERSION='2019.7.6' +-- DateVersion_VERSION='2019.7.6' +-- PROJECT_VERSION_MAJOR='2019' +-- DateVersion_VERSION_MAJOR='2019' +-- PROJECT_VERSION_MINOR='7' +-- DateVersion_VERSION_MINOR='7' +-- PROJECT_VERSION_PATCH='6' +-- DateVersion_VERSION_PATCH='6' +-- PROJECT_VERSION_TWEAK='' +-- DateVersion_VERSION_TWEAK='' +-- PROJECT_VERSION='(1|4294967295)' +-- LongVersion_VERSION='(1|4294967295)' +-- PROJECT_VERSION_MAJOR='(1|4294967295)' +-- LongVersion_VERSION_MAJOR='(1|4294967295)' +-- PROJECT_VERSION_MINOR='' +-- LongVersion_VERSION_MINOR='' +-- PROJECT_VERSION_PATCH='' +-- LongVersion_VERSION_PATCH='' +-- PROJECT_VERSION_TWEAK='' +-- LongVersion_VERSION_TWEAK='' diff --git a/Tests/RunCMake/project/CMP0096-OLD.cmake b/Tests/RunCMake/project/CMP0096-OLD.cmake new file mode 100644 index 0000000..25a3b19 --- /dev/null +++ b/Tests/RunCMake/project/CMP0096-OLD.cmake @@ -0,0 +1,3 @@ +cmake_policy(SET CMP0048 NEW) +cmake_policy(SET CMP0096 OLD) +include(CMP0096-common.cmake) diff --git a/Tests/RunCMake/project/CMP0096-WARN-stdout.txt b/Tests/RunCMake/project/CMP0096-WARN-stdout.txt new file mode 100644 index 0000000..6a945ce --- /dev/null +++ b/Tests/RunCMake/project/CMP0096-WARN-stdout.txt @@ -0,0 +1,20 @@ +-- PROJECT_VERSION='2019.7.6' +-- DateVersion_VERSION='2019.7.6' +-- PROJECT_VERSION_MAJOR='2019' +-- DateVersion_VERSION_MAJOR='2019' +-- PROJECT_VERSION_MINOR='7' +-- DateVersion_VERSION_MINOR='7' +-- PROJECT_VERSION_PATCH='6' +-- DateVersion_VERSION_PATCH='6' +-- PROJECT_VERSION_TWEAK='' +-- DateVersion_VERSION_TWEAK='' +-- PROJECT_VERSION='(1|4294967295)' +-- LongVersion_VERSION='(1|4294967295)' +-- PROJECT_VERSION_MAJOR='(1|4294967295)' +-- LongVersion_VERSION_MAJOR='(1|4294967295)' +-- PROJECT_VERSION_MINOR='' +-- LongVersion_VERSION_MINOR='' +-- PROJECT_VERSION_PATCH='' +-- LongVersion_VERSION_PATCH='' +-- PROJECT_VERSION_TWEAK='' +-- LongVersion_VERSION_TWEAK='' diff --git a/Tests/RunCMake/project/CMP0096-WARN.cmake b/Tests/RunCMake/project/CMP0096-WARN.cmake new file mode 100644 index 0000000..7fe0861 --- /dev/null +++ b/Tests/RunCMake/project/CMP0096-WARN.cmake @@ -0,0 +1,3 @@ +cmake_policy(SET CMP0048 NEW) + +include(CMP0096-common.cmake) diff --git a/Tests/RunCMake/project/CMP0096-common.cmake b/Tests/RunCMake/project/CMP0096-common.cmake new file mode 100644 index 0000000..8d26d30 --- /dev/null +++ b/Tests/RunCMake/project/CMP0096-common.cmake @@ -0,0 +1,9 @@ +include(PrintVersions.cmake) + +# Test leading zeros motivating this policy. +project(DateVersion VERSION 2019.07.06 LANGUAGES NONE) +print_versions(DateVersion) + +# Overflow version component in OLD behavior. +project(LongVersion VERSION 4294967297 #[[ uint32_max + 2 ]] LANGUAGES NONE) +print_versions(LongVersion) diff --git a/Tests/RunCMake/project/PrintVersions.cmake b/Tests/RunCMake/project/PrintVersions.cmake new file mode 100644 index 0000000..ce1b25d --- /dev/null +++ b/Tests/RunCMake/project/PrintVersions.cmake @@ -0,0 +1,6 @@ +macro(print_versions name) + foreach(v "" _MAJOR _MINOR _PATCH _TWEAK) + message(STATUS "PROJECT_VERSION${v}='${PROJECT_VERSION${v}}'") + message(STATUS "${name}_VERSION${v}='${${name}_VERSION${v}}'") + endforeach() +endmacro() diff --git a/Tests/RunCMake/project/RunCMakeTest.cmake b/Tests/RunCMake/project/RunCMakeTest.cmake index 3a8ad4b..8f43a51 100644 --- a/Tests/RunCMake/project/RunCMakeTest.cmake +++ b/Tests/RunCMake/project/RunCMakeTest.cmake @@ -27,3 +27,7 @@ run_cmake(CMP0048-OLD) run_cmake(CMP0048-OLD-VERSION) run_cmake(CMP0048-WARN) run_cmake(CMP0048-NEW) + +run_cmake(CMP0096-WARN) +run_cmake(CMP0096-OLD) +run_cmake(CMP0096-NEW) diff --git a/Tests/RunCMake/target_compile_definitions/RunCMakeTest.cmake b/Tests/RunCMake/target_compile_definitions/RunCMakeTest.cmake index b67c598..a419cc9 100644 --- a/Tests/RunCMake/target_compile_definitions/RunCMakeTest.cmake +++ b/Tests/RunCMake/target_compile_definitions/RunCMakeTest.cmake @@ -1,3 +1,4 @@ include(RunCMake) run_cmake(empty_keyword_args) +run_cmake(unknown_imported_target) diff --git a/Tests/RunCMake/target_compile_definitions/unknown_imported_target.cmake b/Tests/RunCMake/target_compile_definitions/unknown_imported_target.cmake new file mode 100644 index 0000000..4ae1c0d --- /dev/null +++ b/Tests/RunCMake/target_compile_definitions/unknown_imported_target.cmake @@ -0,0 +1,11 @@ +# Test that target_compile_definitions works on UNKNOWN IMPORTED target +add_library(imported UNKNOWN IMPORTED) +target_compile_definitions(imported INTERFACE FOO) + +get_target_property(IMPORTED_INTERFACE_CDS imported INTERFACE_COMPILE_DEFINITIONS) + +if (NOT FOO IN_LIST IMPORTED_INTERFACE_CDS) + message( + FATAL_ERROR "FOO should be in INTERFACE_COMPILE_DEFINITIONS.\n" + "Actual INTERFACE_COMPILE_DEFINITIONS: " ${IMPORTED_INTERFACE_CDS}) +endif() diff --git a/Tests/RunCMake/target_link_libraries/StaticPrivateDepNotExported-stderr.txt b/Tests/RunCMake/target_link_libraries/StaticPrivateDepNotExported-stderr.txt index 6bb44ab..3204225 100644 --- a/Tests/RunCMake/target_link_libraries/StaticPrivateDepNotExported-stderr.txt +++ b/Tests/RunCMake/target_link_libraries/StaticPrivateDepNotExported-stderr.txt @@ -1 +1 @@ -CMake Error: install\(EXPORT "Exp" ...\) includes target "foo" which requires target "not_exported" that is not in the export set. +CMake Error: install\(EXPORT "Exp" ...\) includes target "foo" which requires target "not_exported" that is not in any export set. diff --git a/Tests/RunCMake/try_compile/CMP0067-stderr.txt b/Tests/RunCMake/try_compile/CMP0067-stderr.txt index e2677ed..d955dda 100644 --- a/Tests/RunCMake/try_compile/CMP0067-stderr.txt +++ b/Tests/RunCMake/try_compile/CMP0067-stderr.txt @@ -19,6 +19,17 @@ Call Stack \(most recent call first\): This warning is for project developers. Use -Wno-dev to suppress it. after try_compile with CMP0067 WARN-enabled +CMake Deprecation Warning at CMP0067.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0067 will be removed from a future version + of CMake. + + The cmake-policies\(7\) manual explains that the OLD behaviors of all + policies are deprecated and that a policy should be set to OLD only under + specific short-term circumstances. Projects should be ported to the NEW + behavior and not rely on setting a policy to OLD. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) ++ before try_compile with CMP0067 OLD after try_compile with CMP0067 OLD before try_compile with CMP0067 NEW diff --git a/Tests/RuntimePath/CMakeLists.txt b/Tests/RuntimePath/CMakeLists.txt index 6583a87..bb87440 100644 --- a/Tests/RuntimePath/CMakeLists.txt +++ b/Tests/RuntimePath/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 3.15) project(RuntimePath C) # Add a simple chain of shared libraries that must be found. @@ -31,3 +31,14 @@ if(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG) set_property(TARGET bar2 PROPERTY LIBRARY_OUTPUT_DIRECTORY A) target_link_libraries(bar2 foo2) endif() + +# Add a library that is missing the rpath for its dependency. +add_library(bar1_no_rpath SHARED bar1.c) +set_property(TARGET bar1_no_rpath PROPERTY LIBRARY_OUTPUT_DIRECTORY B) +set_property(TARGET bar1_no_rpath PROPERTY SKIP_BUILD_RPATH 1) +target_link_libraries(bar1_no_rpath PRIVATE foo1) + +# Add an executable linking to the library with a missing dependency rpath. +# CMake should generate the proper rpath-link flag to find it at build time. +add_executable(main_with_bar1_no_rpath main.c) +target_link_libraries(main_with_bar1_no_rpath bar1_no_rpath) diff --git a/Tests/Tutorial/Complete/TutorialConfig.h.in b/Tests/Tutorial/Complete/TutorialConfig.h.in deleted file mode 100644 index 8cd2fc9..0000000 --- a/Tests/Tutorial/Complete/TutorialConfig.h.in +++ /dev/null @@ -1,3 +0,0 @@ -// the configured version number -#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ -#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ diff --git a/Tests/Tutorial/Consumer/directions.txt b/Tests/Tutorial/Consumer/directions.txt deleted file mode 100644 index 6a70aab..0000000 --- a/Tests/Tutorial/Consumer/directions.txt +++ /dev/null @@ -1,6 +0,0 @@ -# Import a CMake Project# - -This examples shows how a project can find other CMake packages that -generated Config.cmake files. - -It also shows how to state a projects external dependencies when generating a Config.cmake. diff --git a/Tests/Tutorial/MultiPackage/TutorialConfig.h.in b/Tests/Tutorial/MultiPackage/TutorialConfig.h.in deleted file mode 100644 index 8cd2fc9..0000000 --- a/Tests/Tutorial/MultiPackage/TutorialConfig.h.in +++ /dev/null @@ -1,3 +0,0 @@ -// the configured version number -#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ -#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ diff --git a/Tests/Tutorial/MultiPackage/directions.txt b/Tests/Tutorial/MultiPackage/directions.txt deleted file mode 100644 index c3102bb..0000000 --- a/Tests/Tutorial/MultiPackage/directions.txt +++ /dev/null @@ -1,34 +0,0 @@ -# Packaging Debug and Release # - -By default CMake is model is that a build directory only contains a single -configuration, be it Debug, Release, MinSizeRel, or RelWithDebInfo. - -But it is possible to setup CPack to bundle multiple build directories at the same -time to build a package that contains multiple configurations of the same project. - -First we need to ahead and construct a directory called 'multi_config' this -will contain all the builds that we want to package together. - -Second create a 'debug' and 'release' directory underneath 'multi_config'. At -the end you should have a layout that looks like: - -─ multi_config - ├── debug - └── release - -Now we need to setup debug and release builds, which would roughly entail -the following: - - cd debug - cmake -DCMAKE_BUILD_TYPE=Debug ../../MultiPackage/ - cmake --build . - cd ../release - cmake -DCMAKE_BUILD_TYPE=Release ../../MultiPackage/ - cmake --build . - cd .. - - -Now that both the debug and release builds are complete we can now use -the custom MultiCPackConfig to package both builds into a single release. - - cpack --config ../../MultiPackage/MultiCPackConfig.cmake diff --git a/Tests/Tutorial/Readme.txt b/Tests/Tutorial/Readme.txt deleted file mode 100644 index 74eb01a..0000000 --- a/Tests/Tutorial/Readme.txt +++ /dev/null @@ -1,16 +0,0 @@ - -Step 0: A Starting Point -Step 1: Configure a File and C++11 Controls -Step 2: Adding a Library -Step 3: Usage Requirements for Library -Step 4: Installing and Testing -Step 5: System Introspection -Step 6: Custom Command and Generated File -Step 7: Building an Installer -Step 8: CDash submission -Step 9: Mixing Static and Shared -Step 10: Generator Expressions -Step 11: Adding Export Configuration -Complete: End result of Step 11 -Consumer: Example of Import Packages -MultiPackage: How to package Debug and Release versions diff --git a/Tests/Tutorial/Step1/CMakeLists.txt b/Tests/Tutorial/Step1/CMakeLists.txt deleted file mode 100644 index 141f0c2..0000000 --- a/Tests/Tutorial/Step1/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -project(Tutorial) - -add_executable(Tutorial tutorial.cxx) diff --git a/Tests/Tutorial/Step1/directions.txt b/Tests/Tutorial/Step1/directions.txt deleted file mode 100644 index 827d775..0000000 --- a/Tests/Tutorial/Step1/directions.txt +++ /dev/null @@ -1,95 +0,0 @@ -# Adding a Version Number and Configured Header File # - -The first feature we will add is to provide our executable and project with a -version number. While we could do this exclusively in the source code, using -CMakeLists provides more flexibility. - -To add a version number we modify the CMakeLists file as follows: - - cmake_minimum_required(VERSION 3.3) - project(Tutorial) - - # the version number. - set(Tutorial_VERSION_MAJOR 1) - set(Tutorial_VERSION_MINOR 0) - - # configure a header file to pass some of the CMake settings - # to the source code - configure_file( - "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" - "${PROJECT_BINARY_DIR}/TutorialConfig.h" - ) - - # add the executable - add_executable(Tutorial tutorial.cxx) - - # add the binary tree to the search path for include files - # so that we will find TutorialConfig.h - target_include_directories(Tutorial PUBLIC - "${PROJECT_BINARY_DIR}" - ) - - -We then create a TutorialConfig.h.in file in the source tree with the -following contents: - - // the configured options and settings for Tutorial - #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ - #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ - -When CMake configures this header file the values for @Tutorial_VERSION_MAJOR@ -and @Tutorial_VERSION_MINOR@ will be replaced by the values from the CMakeLists -file. Next we modify tutorial.cxx to include the configured header file and to -make use of the version numbers. The resulting source code is listed below. - - // A simple program that computes the square root of a number - #include <cmath> - #include <iostream> - #include <string> - #include <sstream> - - #include "TutorialConfig.h" - - int main (int argc, char *argv[]) - { - if (argc < 2) { - std::cout << argv[0] << " Version " - << Tutorial_VERSION_MAJOR << "." << Tutorial_VERSION_MINOR - << std::endl; - std::cout << "Usage: " << argv[0] << " number" << std::endl; - return 1; - } - - double inputValue = atof(argv[1]); - - double outputValue = sqrt(inputValue); - std::cout << "The square root of " - << inputValue << " is " << outputValue << std::endl; - return 0; - } - -# Adding C++11 support # - -Let's add some C++11 features to our project. We will need to explicitly state -in the CMake code that it should use the correct flags. The easiest way to -enable C++11 support for CMake is by using the CMAKE_CXX_STANDARD -and CMAKE_CXX_STANDARD_REQUIRED variables. - -First, replace `atof` with `std::stod` in tutorial.cxx. - -Then, add the CMAKE_CXX_STANDARD and CMAKE_CXX_STANDARD_REQUIRED variables to -the CMakeLists file. The STANADARD value should be set to 11, and REQUIRED -should be set to True. - - -# Build and Test # - -Run cmake or cmake-gui to configure the project and then build it with your -chosen build tool - -cd to the directory where Tutorial was built (likely the make directory or -a Debug or Release build configuration subdirectory) and run these commands: - - Tutorial 4294967296 - Tutorial 10 - Tutorial diff --git a/Tests/Tutorial/Step10/MathFunctions/mysqrt.cxx b/Tests/Tutorial/Step10/MathFunctions/mysqrt.cxx deleted file mode 100644 index 96d9421..0000000 --- a/Tests/Tutorial/Step10/MathFunctions/mysqrt.cxx +++ /dev/null @@ -1,45 +0,0 @@ -#include "MathFunctions.h" -#include <iostream> - -// include the generated table -#include "Table.h" - -#include <cmath> - -namespace mathfunctions { -namespace detail { -// a hack square root calculation using simple operations -double mysqrt(double x) -{ - if (x <= 0) { - return 0; - } - - // if we have both log and exp then use them -#if defined(HAVE_LOG) && defined(HAVE_EXP) - double result = exp(log(x) * 0.5); - std::cout << "Computing sqrt of " << x << " to be " << result << " using log" - << std::endl; -#else - // use the table to help find an initial value - double result = x; - if (x >= 1 && x < 10) { - result = sqrtTable[static_cast<int>(x)]; - } - - // if we have both log and exp then use them - - // do ten iterations - for (int i = 0; i < 10; ++i) { - if (result <= 0) { - result = 0.1; - } - double delta = x - (result * result); - result = result + 0.5 * delta / result; - std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; - } -#endif - return result; -} -} -} diff --git a/Tests/Tutorial/Step10/TutorialConfig.h.in b/Tests/Tutorial/Step10/TutorialConfig.h.in deleted file mode 100644 index 8cd2fc9..0000000 --- a/Tests/Tutorial/Step10/TutorialConfig.h.in +++ /dev/null @@ -1,3 +0,0 @@ -// the configured version number -#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ -#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ diff --git a/Tests/Tutorial/Step10/directions.txt b/Tests/Tutorial/Step10/directions.txt deleted file mode 100644 index 5317b54..0000000 --- a/Tests/Tutorial/Step10/directions.txt +++ /dev/null @@ -1,38 +0,0 @@ -# Adding Generator Expressions # - -Generator expressions are evaluated during build system generation to produce -information specific to each build configuration. - -Generator expressions are allowed in the context of many target properties, such -as LINK_LIBRARIES, INCLUDE_DIRECTORIES, COMPILE_DEFINITIONS and others. They may -also be used when using commands to populate those properties, such as -target_link_libraries(), target_include_directories(), -target_compile_definitions() and others. - -Generator expressions may to used to enable conditional linking, conditional -definitions used when compiling, and conditional include directories and more. -The conditions may be based on the build configuration, target properties, -platform information or any other queryable information. - -There are different types of generator expressions including Logical, -Informational, and Output expressions. - -Logical expressions are used to create conditional output. The basic expressions -are the 0 and 1 expressions. A "$<0:...>" results in the empty string, and -"$<1:...>" results in the content of "...". They can also be nested. -For example: - - if(HAVE_LOG AND HAVE_EXP) - target_compile_definitions(SqrtLibrary - PRIVATE "HAVE_LOG" "HAVE_EXP") - endif() - -Can be rewritten with generator expressions: - - target_compile_definitions(SqrtLibrary PRIVATE - "$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>" - "$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>" - ) - -Note that "${HAVE_LOG}" is evaluated at CMake configure time while -"$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>" is evaluated at build system generation time. diff --git a/Tests/Tutorial/Step11/TutorialConfig.h.in b/Tests/Tutorial/Step11/TutorialConfig.h.in deleted file mode 100644 index 8cd2fc9..0000000 --- a/Tests/Tutorial/Step11/TutorialConfig.h.in +++ /dev/null @@ -1,3 +0,0 @@ -// the configured version number -#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ -#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ diff --git a/Tests/Tutorial/Step11/directions.txt b/Tests/Tutorial/Step11/directions.txt deleted file mode 100644 index ebb5def..0000000 --- a/Tests/Tutorial/Step11/directions.txt +++ /dev/null @@ -1,104 +0,0 @@ -# Adding Export Configuration # - -During Step 4 of the tutorial we added the ability for CMake to install the -library and headers of the project. During Step 7 we added the ability -to package up this information so it could be distributed to other people. - -The next step is to add the necessary information so that other CMake projects -can use our project, be it from a build directory, a local install or when -packaged. - -The first step is to update our install(TARGETS) commands to not only specify -a DESTINATION but also an EXPORT. The EXPORT keyword generates and installs a -CMake file containing code to import all targets listed in the install command -from the installation tree. So let's go ahead and explicitly EXPORT the -MathFunctions library by updating the install command in -MathFunctions/CMakeLists.txt to look like: - - install(TARGETS MathFunctions DESTINATION lib EXPORT MathFunctionsTargets) - -Now that we have MathFunctions being exported, we also need to explicitly install -the generated MathFunctionsTargets.cmake file. This is done by adding -the following to the bottom of the top-level CMakeLists.txt: - - # install the configuration targets - install(EXPORT MathFunctionsTargets - FILE MathFunctionsTargets.cmake - DESTINATION lib/cmake/MathFunctions - ) - -At this point you should try and run CMake. If everything is setup properly -you will see that CMake will generate an error that looks like: - - Target "MathFunctions" INTERFACE_INCLUDE_DIRECTORIES property contains - path: - - "/Users/robert/Documents/CMakeClass/Tutorial/Step11/MathFunctions" - - which is prefixed in the source directory. - -What CMake is trying to say is that during generating the export information -it will export a path that is intrinsically tied to the current machine and -will not be valid on other machines. The solution to this is to update the -MathFunctions target_include_directories to understand that it needs different -INTERFACE locations when being used from within the build directory and from an -install / package. This means converting the target_include_directories -call for MathFunctions to look like: - - target_include_directories(MathFunctions - INTERFACE - $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> - $<INSTALL_INTERFACE:include> - ) - -Once this has been updated, we can re-run CMake and see verify that it doesn't -warn anymore. - -At this point, we have CMake properly packaging the target information that is -required but we will still need to generate a MathFunctionsConfig.cmake, so -that the CMake find_package command can find our project. So let's go ahead and -add a new file to the top-level of the project called Config.cmake.in with the -following contents: - - @PACKAGE_INIT@ - - include ( "${CMAKE_CURRENT_LIST_DIR}/MathFunctionsTargets.cmake" ) - -Then, to properly configure and install that file, add the following to the -bottom of the top-level CMakeLists: - - include(CMakePackageConfigHelpers) - # generate the config file that is includes the exports - configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in - "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake" - INSTALL_DESTINATION "lib/cmake/example" - NO_SET_AND_CHECK_MACRO - NO_CHECK_REQUIRED_COMPONENTS_MACRO - ) - # generate the version file for the config file - write_basic_package_version_file( - "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake" - VERSION "${Tutorial_VERSION_MAJOR}.${Tutorial_VERSION_MINOR}" - COMPATIBILITY AnyNewerVersion - ) - - # install the configuration file - install(FILES - ${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake - DESTINATION lib/cmake/MathFunctions - ) - -At this point, we have generated a relocatable CMake Configuration for our project -that can be used after the project has been installed or packaged. If we want -our project to also be used from a build directory we only have to add -the following to the bottom of the top level CMakeLists: - - # generate the export targets for the build tree - # needs to be after the install(TARGETS ) command - export(EXPORT MathFunctionsTargets - FILE "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsTargets.cmake" - ) - -With this export call we now generate a Targets.cmake, allowing the configured -MathFunctionsConfig.cmake in the build directory to be used by other projects, -without needing it to be installed. diff --git a/Tests/Tutorial/Step2/MathFunctions/CMakeLists.txt b/Tests/Tutorial/Step2/MathFunctions/CMakeLists.txt deleted file mode 100644 index 8b443a6..0000000 --- a/Tests/Tutorial/Step2/MathFunctions/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_library(MathFunctions mysqrt.cxx) diff --git a/Tests/Tutorial/Step2/directions.txt b/Tests/Tutorial/Step2/directions.txt deleted file mode 100644 index bb6662c..0000000 --- a/Tests/Tutorial/Step2/directions.txt +++ /dev/null @@ -1,102 +0,0 @@ -# Adding a Library # - -Now we will add a library to our project. This library will contain our own -implementation for computing the square root of a number. The executable can -then use this library instead of the standard square root function provided by -the compiler. - -For this tutorial we will put the library into a subdirectory -called MathFunctions. It will have the following one line CMakeLists file: - - add_library(MathFunctions mysqrt.cxx) - -The source file mysqrt.cxx has one function called mysqrt that provides similar -functionality to the compiler’s sqrt function. To make use of the new library -we add an add_subdirectory call in the top-level CMakeLists file so that the -library will get built. We add the new library to the executable, and add the -MathFunctions as an include directory so that mqsqrt.h header file can be -found. The last few lines of the top-level CMakeLists file now look like: - - - add_subdirectory(MathFunctions) - - #add the executable - add_executable(Tutorial tutorial.cxx) - - target_link_libraries(Tutorial ${EXTRA_LIBS}) - - -Now let us make the MathFunctions library optional. While for the tutorial -there really isn’t any need to do so, but with larger projects this is a common -occurrence. The first step is to add an option to the top-level CMakeLists file. - - option (USE_MYMATH - "Use tutorial provided math implementation" ON) - -This will show up in CMake GUI and ccmake with a default value of ON that can -be changed by the user. This setting will be stored so that the user does not -need to set the value each time they run CMake on this build directory. - -The next change is to make building and linking the MathFunctions library -conditional. To do this we change the top-level CMakeLists file to look like -the following: - - cmake_minimum_required(VERSION 3.3) - project(Tutorial) - - set(CMAKE_CXX_STANDARD 11) - set(CMAKE_CXX_STANDARD_REQUIRED True) - - # the version number. - set(Tutorial_VERSION_MAJOR 1) - set(Tutorial_VERSION_MINOR 0) - - # configure a header file to pass some of the CMake settings - # to the source code - configure_file( - "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" - "${PROJECT_BINARY_DIR}/TutorialConfig.h" - ) - - # should we use our own math functions - option(USE_MYMATH "Use tutorial provided math implementation" ON) - - # add the MathFunctions library? - if(USE_MYMATH) - add_subdirectory(MathFunctions) - list(APPEND EXTRA_LIBS MathFunctions) - list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions") - endif(USE_MYMATH) - - # add the executable - add_executable(Tutorial tutorial.cxx) - - target_link_libraries(Tutorial ${EXTRA_LIBS}) - - # add the binary tree to the search path for include files - # so that we will find TutorialConfig.h - target_include_directories(Tutorial PUBLIC - "${PROJECT_BINARY_DIR}" - ${EXTRA_INCLUDES} - ) - -Note the use of the variables EXTRA_LIBS, and EXTRA_INCLUDES to collect -up any optional libraries to later be linked into the executable. This is a -classic approach when dealing with many optional components, we will cover the -modern approach in the next step. For now the corresponding changes to the -source code are fairly straightforward and leave us with: - - #ifdef USE_MYMATH - double outputValue = mysqrt(inputValue); - #else - double outputValue = sqrt(inputValue); - #endif - -Since the source code now requires USE_MYMATH we can add it to the -TutorialConfig.h.in. Simply add the following line: - #cmakedefine USE_MYMATH - -Run cmake or cmake-gui to configure the project and then build it with your -chosen build tool and then run the built Tutorial executable. - -Which function gives better results, Step1’s sqrt or Step2’s mysqrt? diff --git a/Tests/Tutorial/Step3/directions.txt b/Tests/Tutorial/Step3/directions.txt deleted file mode 100644 index 54d0318..0000000 --- a/Tests/Tutorial/Step3/directions.txt +++ /dev/null @@ -1,26 +0,0 @@ -# Adding Usage Requirements for Library # - -Usage requirements allow for far better control over a library / executable's -link and include line. While also giving more control over the transitive -property of targets inside CMake. The primary commands that leverage usage -requirements are: - - - target_compile_definitions - - target_compile_options - - target_include_directories - - target_link_libraries - -First up is MathFunctions. We first state that anybody linking to MathFunctions -needs to include the current source directory, while MathFunctions itself -doesn't. So this can become an INTERFACE usage requirement. - -Remember INTERFACE means things that consumers require but the producer doesn't. - - target_include_directories(MathFunctions - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) - -Now that we've specified usage requirements for MathFunctions we can safely remove -our uses of the EXTRA_INCLUDES variable. - -Run cmake or cmake-gui to configure the project and then build it with your -chosen build tool. diff --git a/Tests/Tutorial/Step4/directions.txt b/Tests/Tutorial/Step4/directions.txt deleted file mode 100644 index 91e4043..0000000 --- a/Tests/Tutorial/Step4/directions.txt +++ /dev/null @@ -1,72 +0,0 @@ -# Installing and Testing # - -Now we can start adding testing support and install rules to our project. - -The install rules are fairly simple; for MathFunctions we install the library -and header file, for the application we install the executable and configured -header. - -So to MathFunctions/CMakeLists.txt we add: - - install (TARGETS MathFunctions DESTINATION bin) - install (FILES MathFunctions.h DESTINATION include) - -And the to top-level CMakeLists.txt we add: - - install(TARGETS Tutorial DESTINATION bin) - install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h" - DESTINATION include - ) - -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. Then 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. - -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. - -Next let's test our application. Adding testing is an easy process. At the -end of the top-level CMakeLists file we can add a number of basic tests to -verify that the application is working correctly. - - # enable testing - enable_testing() - - # does the application run - add_test(NAME Runs COMMAND Tutorial 25) - - # does the usage message work? - add_test(NAME Usage COMMAND Tutorial) - set_tests_properties(Usage - PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number" - ) - - # define a function to simplify adding tests - function(do_test target arg result) - add_test(NAME Comp${arg} COMMAND ${target} ${arg}) - set_tests_properties(Comp${arg} - PROPERTIES PASS_REGULAR_EXPRESSION ${result} - ) - endfunction(do_test) - - # do a bunch of result based tests - do_test(Tutorial 25 "25 is 5") - do_test(Tutorial -25 "-25 is [-nan|nan|0]") - do_test(Tutorial 0.0001 "0.0001 is 0.01") - -The first test simply verifies that the application runs, does not segfault or -otherwise crash, and has a zero return value. This is the basic form of a CTest -test. - -The Usage test uses a regular expression to verify that the usage message -is printed when an incorrect number of arguments are provided. - -Lastly, we have a function called do_test that simplifies running the -application and verifying that the computed square root is correct for given -input. - -To run tests, cd to the binary directory and run “ctest -N” and “ctest -VV”. diff --git a/Tests/Tutorial/Step5/directions.txt b/Tests/Tutorial/Step5/directions.txt deleted file mode 100644 index e6f5197..0000000 --- a/Tests/Tutorial/Step5/directions.txt +++ /dev/null @@ -1,69 +0,0 @@ -# Adding System Introspection # - -Let us consider adding some code to our project that depends on features the -target platform may not have. For this example, we will add some code that -depends on whether or not the target platform has the log and exp functions. Of -course almost every platform has these functions but for this tutorial assume -that they are not common. - -If the platform has log and exp then we will use them to compute the square -root in the mysqrt function. We first test for the availability of these -functions using the CheckSymbolExists.cmake macro in the top-level CMakeLists -file as follows: - - # does this system provide the log and exp functions? - include(CheckSymbolExists) - set(CMAKE_REQUIRED_LIBRARIES "m") - check_symbol_exists(log "math.h" HAVE_LOG) - check_symbol_exists(exp "math.h" HAVE_EXP) - -Now let's add these defines to TutorialConfig.h.in so that we can use them -from mysqrt.cxx: - - // does the platform provide exp and log functions? - #cmakedefine HAVE_LOG - #cmakedefine HAVE_EXP - -Modify mysqrt.cxx to include math.h. Next, in the mysqrt function we can -provide an alternate implementation based on log and exp if they are available -on the system using the following code: - - // if we have both log and exp then use them - #if defined(HAVE_LOG) && defined (HAVE_EXP) - double result = exp(log(x)*0.5); - std::cout << "Computing sqrt of " << x << " to be " << result << " using log" << std::endl; - #else - ... - -Run cmake or cmake-gui to configure the project and then build it with your -chosen build tool. - -You will notice that even though HAVE_LOG and HAVE_EXP are both defined mysqrt -isn't using them. We should realize quickly that we have forgotten to include -TutorialConfig.h in mysqrt.cxx. We will also need to update -MathFunctions/CMakeLists.txt with where it is located. - -So let's go ahead and update MathFunctions/CMakeLists.txt to look like: - - add_library(MathFunctions mysqrt.cxx) - - target_include_directories(MathFunctions - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} - PRIVATE ${Tutorial_BINARY_DIR} - ) - - install(TARGETS MathFunctions DESTINATION lib) - install(FILES MathFunctions.h DESTINATION include) - -Now all we need to do is include TutorialConfig.h in mysqrt.cxx - -At this point you should go ahead and build the project again. - -Run the built Tutorial executable. Which function gives better results now, -Step1’s sqrt or Step5’s mysqrt? - -Exercise: Why is it important that we configure TutorialConfig.h.in after the -checks for HAVE_LOG and HAVE_EXP? What would happen if we inverted the two? - -Exercise: Is there a better place for us to save the HAVE_LOG and HAVE_EXP -values other than in TutorialConfig.h? diff --git a/Tests/Tutorial/Step6/TutorialConfig.h.in b/Tests/Tutorial/Step6/TutorialConfig.h.in deleted file mode 100644 index a091265..0000000 --- a/Tests/Tutorial/Step6/TutorialConfig.h.in +++ /dev/null @@ -1,9 +0,0 @@ -// the configured options and settings for Tutorial -#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ -#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ -#cmakedefine USE_MYMATH - -// does the platform provide exp and log functions? -#cmakedefine HAVE_LOG -#cmakedefine HAVE_EXP - diff --git a/Tests/Tutorial/Step6/directions.txt b/Tests/Tutorial/Step6/directions.txt deleted file mode 100644 index 42b9f06..0000000 --- a/Tests/Tutorial/Step6/directions.txt +++ /dev/null @@ -1,104 +0,0 @@ -# Adding a Custom Command and Generated File # - -In this section we will show how you can add a generated source file into the -build process of an application. For this example, we will create a table of -precomputed square roots as part of the build process, and then compile that -table into our application. - -To accomplish this, we first need a program that will generate the table. In the -MathFunctions subdirectory a new source file named MakeTable.cxx will do just that. - - // A simple program that builds a sqrt table - #include <iostream> - #include <fstream> - #include <cmath> - - int main (int argc, char *argv[]) - { - // make sure we have enough arguments - if (argc < 2) { - return 1; - } - - std::ofstream fout(argv[1],std::ios_base::out); - const bool fileOpen = fout.is_open(); - if(fileOpen) { - fout << "double sqrtTable[] = {" << std::endl; - for (int i = 0; i < 10; ++i) { - fout << sqrt(static_cast<double>(i)) << "," << std::endl; - } - // close the table with a zero - fout << "0};" << std::endl; - fout.close(); - } - return fileOpen ? 0 : 1; // return 0 if wrote the file - } - -Note that the table is produced as valid C++ code and that the output filename -is passed in as an argument. - -The next step is to add the appropriate commands to MathFunctions’ CMakeLists -file to build the MakeTable executable and then run it as part of the build -process. A few commands are needed to accomplish this, as shown below: - - # first we add the executable that generates the table - add_executable(MakeTable MakeTable.cxx) - - # add the command to generate the source code - add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h - COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h - DEPENDS MakeTable - ) - - # add the main library - add_library(MathFunctions - mysqrt.cxx - ${CMAKE_CURRENT_BINARY_DIR}/Table.h - ) - - target_include_directories(MathFunctions - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} - PUBLIC ${Tutorial_BINARY_DIR} - # add the binary tree directory to the search path for include files - ${CMAKE_CURRENT_BINARY_DIR} - ) - - install(TARGETS MathFunctions DESTINATION lib) - install(FILES MathFunctions.h DESTINATION include) - -First, the executable for MakeTable is added as any other executable would be -added. Then we add a custom command that specifies how to produce Table.h by -running MakeTable. Next we have to let CMake know that mysqrt.cxx depends on -the generated file Table.h. This is done by adding the generated Table.h to the -list of sources for the library MathFunctions. We also have to add the current -binary directory to the list of include directories so that Table.h can be -found and included by mysqrt.cxx. - -Now let's use the generated table. First, modify mysqrt.cxx to include Table.h. -Next, we can rewrite the mysqrt function to use the table: - - if (x <= 0) { - return 0; - } - - // use the table to help find an initial value - double result = x; - if (x >= 1 && x < 10) { - result = sqrtTable[static_cast<int>(x)]; - } - - // do ten iterations - for (int i = 0; i < 10; ++i) { - if (result <= 0) { - result = 0.1; - } - double delta = x - (result*result); - result = result + 0.5*delta/result; - std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; - } - -Run cmake or cmake-gui to configure the project and then build it with your -chosen build tool. When this project is built it will first build the MakeTable -executable. It will then run MakeTable to produce Table.h. Finally, it will -compile mysqrt.cxx which includes Table.h to produce the MathFunctions library. diff --git a/Tests/Tutorial/Step7/TutorialConfig.h.in b/Tests/Tutorial/Step7/TutorialConfig.h.in deleted file mode 100644 index a091265..0000000 --- a/Tests/Tutorial/Step7/TutorialConfig.h.in +++ /dev/null @@ -1,9 +0,0 @@ -// the configured options and settings for Tutorial -#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ -#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ -#cmakedefine USE_MYMATH - -// does the platform provide exp and log functions? -#cmakedefine HAVE_LOG -#cmakedefine HAVE_EXP - diff --git a/Tests/Tutorial/Step7/build1.cmake b/Tests/Tutorial/Step7/build1.cmake deleted file mode 100644 index baa475f..0000000 --- a/Tests/Tutorial/Step7/build1.cmake +++ /dev/null @@ -1,5 +0,0 @@ -set(CTEST_SOURCE_DIRECTORY "$ENV{HOME}/Dashboards/My Tests/CMake/Tests/Tutorial/Step7") -set(CTEST_BINARY_DIRECTORY "${CTEST_SOURCE_DIRECTORY}-build1") - -set(CTEST_CMAKE_COMMAND "cmake") -set(CTEST_COMMAND "ctest -D Experimental") diff --git a/Tests/Tutorial/Step7/directions.txt b/Tests/Tutorial/Step7/directions.txt deleted file mode 100644 index 7d7c2ea..0000000 --- a/Tests/Tutorial/Step7/directions.txt +++ /dev/null @@ -1,40 +0,0 @@ -# Building an Installer # - -Next suppose that we want to distribute our project to other people so that they -can use it. We want to provide both binary and source distributions on a variety -of platforms. This is a little different from the install we did previously in -the Installing and Testing section (Step 4), where we were installing the -binaries that we had built from the source code. In this example we will be -building installation packages that support binary installations and package -management features. To accomplish this we will use CPack to create platform -specific installers. Specifically we need to add a few lines to the bottom of -our top-level CMakeLists.txt file. - - include(InstallRequiredSystemLibraries) - set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") - set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}") - set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}") - include(CPack) - -That is all there is to it. We start by including InstallRequiredSystemLibraries. -This module will include any runtime libraries that are needed by the project -for the current platform. Next we set some CPack variables to where we have -stored the license and version information for this project. The version -information makes use of the variables we set earlier in this tutorial. Finally -we include the CPack module which will use these variables and some other -properties of the system you are on to setup an installer. - -The next step is to build the project in the usual manner and then run CPack -on it. To build a binary distribution you would run: - - cpack - -To create a source distribution you would type: - - cpack -C CPackSourceConfig.cmake - -Alternatively, run “make package” or right click the Package target and -“Build Project” from an IDE. - -Run the installer executable found in the binary directory. Then run the -installed executable and verify that it works. diff --git a/Tests/Tutorial/Step7/tutorial.cxx b/Tests/Tutorial/Step7/tutorial.cxx deleted file mode 100644 index 1d5742d..0000000 --- a/Tests/Tutorial/Step7/tutorial.cxx +++ /dev/null @@ -1,32 +0,0 @@ -// A simple program that computes the square root of a number -#include <cmath> -#include <iostream> -#include <string> - -#include "TutorialConfig.h" - -#ifdef USE_MYMATH -# include "MathFunctions.h" -#endif - -int main(int argc, char* argv[]) -{ - if (argc < 2) { - std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." - << Tutorial_VERSION_MAJOR << std::endl; - std::cout << "Usage: " << argv[0] << " number" << std::endl; - return 1; - } - - double inputValue = std::stod(argv[1]); - -#ifdef USE_MYMATH - double outputValue = mysqrt(inputValue); -#else - double outputValue = sqrt(inputValue); -#endif - - std::cout << "The square root of " << inputValue << " is " << outputValue - << std::endl; - return 0; -} diff --git a/Tests/Tutorial/Step8/TutorialConfig.h.in b/Tests/Tutorial/Step8/TutorialConfig.h.in deleted file mode 100644 index e97ce24..0000000 --- a/Tests/Tutorial/Step8/TutorialConfig.h.in +++ /dev/null @@ -1,8 +0,0 @@ -// the configured options and settings for Tutorial -#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ -#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ -#cmakedefine USE_MYMATH - -// does the platform provide exp and log functions? -#cmakedefine HAVE_LOG -#cmakedefine HAVE_EXP diff --git a/Tests/Tutorial/Step8/directions.txt b/Tests/Tutorial/Step8/directions.txt deleted file mode 100644 index 588d9c6..0000000 --- a/Tests/Tutorial/Step8/directions.txt +++ /dev/null @@ -1,38 +0,0 @@ -# Adding Support for a Dashboard # - -Adding support for submitting our test results to a dashboard is very easy. We -already defined a number of tests for our project in the earlier steps of this -tutorial. We just have to run those tests and submit them to a dashboard. To -include support for dashboards we include the CTest module in our top-level -CMakeLists.txt. - -Replace: - # enable testing - enable_testing() - -With: - # enable dashboard scripting - include(CTest) - -The CTest module will automatically call enable_testing(), so -we can remove it from our CMake files. - -We will also need to create a CTestConfig.cmake file where we can specify the -name of the project and where to submit the dashboard. - - set(CTEST_PROJECT_NAME "CMakeTutorial") - set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC") - - set(CTEST_DROP_METHOD "http") - set(CTEST_DROP_SITE "my.cdash.org/") - set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial") - set(CTEST_DROP_SITE_CDASH TRUE) - -CTest will read in this file when it runs. To create a simple dashboard you can -run cmake or cmake-gui to configure the project, but do not build it yet. -Instead, change directory to the binary tree, and then run: - 'ctest [-VV] –D Experimental'. On Windows, build the EXPERIMENTAL target. - -Ctest will build and test the project and submit results to the Kitware public -dashboard. The results of your dashboard will be uploaded to Kitware's public -dashboard here: https://my.cdash.org/index.php?project=CMakeTutorial. diff --git a/Tests/Tutorial/Step8/tutorial.cxx b/Tests/Tutorial/Step8/tutorial.cxx deleted file mode 100644 index 1d5742d..0000000 --- a/Tests/Tutorial/Step8/tutorial.cxx +++ /dev/null @@ -1,32 +0,0 @@ -// A simple program that computes the square root of a number -#include <cmath> -#include <iostream> -#include <string> - -#include "TutorialConfig.h" - -#ifdef USE_MYMATH -# include "MathFunctions.h" -#endif - -int main(int argc, char* argv[]) -{ - if (argc < 2) { - std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." - << Tutorial_VERSION_MAJOR << std::endl; - std::cout << "Usage: " << argv[0] << " number" << std::endl; - return 1; - } - - double inputValue = std::stod(argv[1]); - -#ifdef USE_MYMATH - double outputValue = mysqrt(inputValue); -#else - double outputValue = sqrt(inputValue); -#endif - - std::cout << "The square root of " << inputValue << " is " << outputValue - << std::endl; - return 0; -} diff --git a/Tests/Tutorial/Step9/CTestConfig.cmake b/Tests/Tutorial/Step9/CTestConfig.cmake deleted file mode 100644 index 7a927ac..0000000 --- a/Tests/Tutorial/Step9/CTestConfig.cmake +++ /dev/null @@ -1,15 +0,0 @@ -## This file should be placed in the root directory of your project. -## Then modify the CMakeLists.txt file in the root directory of your -## project to incorporate the testing dashboard. -## -## # The following are required to submit to the CDash dashboard: -## ENABLE_TESTING() -## INCLUDE(CTest) - -set(CTEST_PROJECT_NAME "CMakeTutorial") -set(CTEST_NIGHTLY_START_TIME "00:00:00 EST") - -set(CTEST_DROP_METHOD "http") -set(CTEST_DROP_SITE "my.cdash.org") -set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial") -set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Tests/Tutorial/Step9/directions.txt b/Tests/Tutorial/Step9/directions.txt deleted file mode 100644 index 8771637..0000000 --- a/Tests/Tutorial/Step9/directions.txt +++ /dev/null @@ -1,166 +0,0 @@ -# Mixing Static and Shared # - -In this section we will show how by using the BUILD_SHARED_LIBS variable we can -control the default behavior of add_library, and allow control over how -libraries without an explicit type ( STATIC/SHARED/MODULE/OBJECT ) are built. - -To accomplish this we need to add BUILD_SHARED_LIBS to the top level -CMakeLists.txt. We use the option command as it allows users to optionally -select if the value should be On or Off. - -Next we are going to refactor MathFunctions to become a real library that -encapsulates using mysqrt or sqrt, instead of requiring the calling code -to do this logic. This will also mean that USE_MYMATH will not control building -MathFuctions, but instead will control the behavior of this library. - -The first step is to update the starting section of the top level CMakeLists.txt -to look like: - - cmake_minimum_required(VERSION 3.3) - project(Tutorial) - - # control where the static and shared libraries are built so that on windows - # we don't need to tinker with the path to run the executable - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") - - set(CMAKE_CXX_STANDARD 11) - set(CMAKE_CXX_STANDARD_REQUIRED True) - - option(BUILD_SHARED_LIBS "Build using shared libraries" ON) - - # the version number. - set(Tutorial_VERSION_MAJOR 1) - set(Tutorial_VERSION_MINOR 0) - - # configure a header file to pass the version number only - configure_file( - "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in" - "${PROJECT_BINARY_DIR}/TutorialConfig.h" - ) - - # add the MathFunctions library - add_subdirectory(MathFunctions) - - # add the executable - add_executable(Tutorial tutorial.cxx) - target_link_libraries(Tutorial PUBLIC MathFunctions) - -Now that we have made MathFunctions always be used, we will need to update -the logic of that library. So, in MathFunctions/CMakeLists.txt we need to -create a SqrtLibrary that will conditionally be built when USE_MYMATH is -enabled. Now, since this is a tutorial, we are going to explicitly require -that SqrtLibrary is built statically. - -The end result is that MathFunctions/CMakeLists.txt should look like: - - # add the library that runs - add_library(MathFunctions MathFunctions.cxx) - - # state that anybody linking to us needs to include the current source dir - # to find MathFunctions.h, while we don't. - target_include_directories(MathFunctions - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} - ) - - # should we use our own math functions - option(USE_MYMATH "Use tutorial provided math implementation" ON) - if(USE_MYMATH) - - # does this system provide the log and exp functions? - include(CheckSymbolExists) - set(CMAKE_REQUIRED_LIBRARIES "m") - check_symbol_exists(log "math.h" HAVE_LOG) - check_symbol_exists(exp "math.h" HAVE_EXP) - - # first we add the executable that generates the table - add_executable(MakeTable MakeTable.cxx) - - # add the command to generate the source code - add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h - COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h - DEPENDS MakeTable - ) - - # library that just does sqrt - add_library(SqrtLibrary STATIC - mysqrt.cxx - ${CMAKE_CURRENT_BINARY_DIR}/Table.h - ) - - # state that we depend on our binary dir to find Table.h - target_include_directories(SqrtLibrary PRIVATE - ${CMAKE_CURRENT_BINARY_DIR} - ) - - target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") - if(HAVE_LOG AND HAVE_EXP) - target_compile_definitions(SqrtLibrary - PRIVATE "HAVE_LOG" "HAVE_EXP") - endif() - - target_link_libraries(MathFunctions PRIVATE SqrtLibrary) - endif() - - # define the symbol stating we are using the declspec(dllexport) when - # building on windows - target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH") - - install(TARGETS MathFunctions DESTINATION lib) - install(FILES MathFunctions.h DESTINATION include) - -Next, update MathFunctions/mysqrt.cxx to use the mathfunctions and detail namespaces: - - #include <iostream> - #include "MathFunctions.h" - - // include the generated table - #include "Table.h" - - #include <cmath> - - namespace mathfunctions { - namespace detail { - // a hack square root calculation using simple operations - double mysqrt(double x) - { - ... - - return result; - } - } - } - -We also need to make some changes in tutorial.cxx, so that it no longer uses USE_MYMATH: -1. Always include MathFunctions.h -2. Always use mathfunctions::sqrt - -Finally, update MathFunctions/MathFunctions.h to use dll export defines: - - #if defined(_WIN32) - #if defined(EXPORTING_MYMATH) - #define DECLSPEC __declspec(dllexport) - #else - #define DECLSPEC __declspec(dllimport) - #endif - #else //non windows - #define DECLSPEC - #endif - - namespace mathfunctions - { - double DECLSPEC sqrt(double x); - } - -At this point, if you build everything, you will notice that linking fails -as we are combining a static library without position enabled code with a -library that has position enabled code. This solution to this is to explicitly -set the POSITION_INDEPENDENT_CODE target property of SqrtLibrary to be True no -matter the build type. - -Exercise: We modified MathFunctions.h to use dll export defines. Using CMake -documentation can you find a helper module to simplify this? - -Exercise: Determine what command is enabling PIC for SqrtLibrary. -What happens if we remove said command? diff --git a/Tests/Tutorial/Step9/tutorial.cxx b/Tests/Tutorial/Step9/tutorial.cxx deleted file mode 100644 index 73e67a9..0000000 --- a/Tests/Tutorial/Step9/tutorial.cxx +++ /dev/null @@ -1,33 +0,0 @@ -// A simple program that computes the square root of a number -#include <cmath> -#include <iostream> -#include <sstream> -#include <string> - -#include "TutorialConfig.h" - -#ifdef USE_MYMATH -# include "MathFunctions.h" -#endif - -int main(int argc, char* argv[]) -{ - if (argc < 2) { - std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." - << Tutorial_VERSION_MAJOR << std::endl; - std::cout << "Usage: " << argv[0] << " number" << std::endl; - return 1; - } - - double inputValue = std::stod(argv[1]); - -#ifdef USE_MYMATH - double outputValue = mysqrt(inputValue); -#else - double outputValue = sqrt(inputValue); -#endif - - std::cout << "The square root of " << inputValue << " is " << outputValue - << std::endl; - return 0; -} diff --git a/Utilities/Doxygen/CMakeLists.txt b/Utilities/Doxygen/CMakeLists.txt index ce4cfaf..5bf13f3 100644 --- a/Utilities/Doxygen/CMakeLists.txt +++ b/Utilities/Doxygen/CMakeLists.txt @@ -3,11 +3,11 @@ if(NOT CMake_SOURCE_DIR) set(CMakeDeveloperReference_STANDALONE 1) - cmake_minimum_required(VERSION 3.1...3.14 FATAL_ERROR) + cmake_minimum_required(VERSION 3.1...3.15 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) - include(${CMake_SOURCE_DIR}/Source/CMakeVersionCompute.cmake) + include(${CMake_SOURCE_DIR}/Source/CMakeVersion.cmake) include(${CMake_SOURCE_DIR}/Source/CMakeInstallDestinations.cmake) unset(CMAKE_DATA_DIR) unset(CMAKE_DATA_DIR CACHE) diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp index 0393ff1..9fff442 100644 --- a/Utilities/IWYU/mapping.imp +++ b/Utilities/IWYU/mapping.imp @@ -42,10 +42,19 @@ { symbol: [ "std::istringstream", private, "<sstream>", public ] }, { symbol: [ "std::ostringstream", private, "<sstream>", public ] }, - # HACK: iwyu suggests those two files each time vector[] is used. + # HACK: iwyu suggests <ext/alloc_traits.h> and <memory> each time vector[] is used. # https://github.com/include-what-you-use/include-what-you-use/issues/166 { include: [ "<ext/alloc_traits.h>", private, "<vector>", public ] }, - { include: [ "<memory>", public, "<vector>", public ] }, + { symbol: [ "std::allocator_traits<std::allocator<cmComputeComponentGraph::TarjanEntry> >::value_type", private, "<vector>", public ] }, + { symbol: [ "std::allocator_traits<std::allocator<cmFortranFile> >::value_type", private, "<vector>", public ] }, + { symbol: [ "std::allocator_traits<std::allocator<cmGraphEdgeList> >::value_type", private, "<vector>", public ] }, + { symbol: [ "std::allocator_traits<std::allocator<cmOrderDirectories::ConflictList> >::value_type", private, "<vector>", public ] }, + { symbol: [ "std::allocator_traits<std::allocator<cmStateSnapshot> >::value_type", private, "<vector>", public ] }, + { symbol: [ "std::allocator_traits<std::allocator<std::basic_string<char> > >::value_type", private, "<vector>", public ] }, + { symbol: [ "std::allocator_traits<std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::value_type", private, "<vector>", public ] }, + { symbol: [ "std::allocator_traits<std::allocator<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > > > >::value_type", private, "<vector>", public ] }, + { symbol: [ "std::allocator_traits<std::allocator<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >::value_type", private, "<vector>", public ] }, + { symbol: [ "std::allocator_traits<std::allocator<uv_stdio_container_s> >::value_type", private, "<vector>", public ] }, # TODO: enable this block and remove some <utility> includes? #{ symbol: [ "std::pair", private, "<utility>", public ] }, diff --git a/Utilities/Release/WiX/CustomAction/CMakeLists.txt b/Utilities/Release/WiX/CustomAction/CMakeLists.txt index 7efd01e..9d89dd8 100644 --- a/Utilities/Release/WiX/CustomAction/CMakeLists.txt +++ b/Utilities/Release/WiX/CustomAction/CMakeLists.txt @@ -1,9 +1,15 @@ -foreach(CONFIG DEBUG MINSIZEREL RELEASE RELWITHDEBINFO) - string(REPLACE "/MD" "/MT" - "CMAKE_CXX_FLAGS_${CONFIG}" - "${CMAKE_CXX_FLAGS_${CONFIG}}" - ) -endforeach() +if(MSVC) + if(NOT CMAKE_VERSION VERSION_LESS 3.15) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") + else() + foreach(CONFIG DEBUG MINSIZEREL RELEASE RELWITHDEBINFO) + string(REPLACE "/MD" "/MT" + "CMAKE_CXX_FLAGS_${CONFIG}" + "${CMAKE_CXX_FLAGS_${CONFIG}}" + ) + endforeach() + endif() +endif() add_library(CMakeWiXCustomActions MODULE detect_nsis_overwrite.cpp diff --git a/Utilities/Release/create-cmake-release.cmake b/Utilities/Release/create-cmake-release.cmake index b3cc352..0622ad8 100644 --- a/Utilities/Release/create-cmake-release.cmake +++ b/Utilities/Release/create-cmake-release.cmake @@ -5,30 +5,10 @@ endif() file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/logs) -set(RELEASE_SCRIPTS_BATCH_1 - win32_release.cmake # Windows x86 - osx_release.cmake # OS X x86_64 - linux64_release.cmake # Linux x86_64 -) - -set(RELEASE_SCRIPTS_BATCH_2 - win64_release.cmake # Windows x64 -) - -function(write_batch_shell_script filename) - set(scripts ${ARGN}) - set(i 0) - file(WRITE ${filename} "#!/bin/bash") - foreach(f ${scripts}) - math(EXPR x "420*(${i}/4)") - math(EXPR y "160*(${i}%4)") - file(APPEND ${filename} - " -\"${CMAKE_COMMAND}\" -DCMAKE_CREATE_VERSION=${CMAKE_CREATE_VERSION} -DCMAKE_DOC_TARBALL=\"${CMAKE_DOC_TARBALL}\" -P \"${CMAKE_ROOT}/Utilities/Release/${f}\" < /dev/null >& \"${CMAKE_CURRENT_SOURCE_DIR}/logs/${f}-${CMAKE_CREATE_VERSION}.log\" & -xterm -geometry 64x6+${x}+${y} -sb -sl 2000 -T ${f}-${CMAKE_CREATE_VERSION}.log -e tail -f \"${CMAKE_CURRENT_SOURCE_DIR}/logs/${f}-${CMAKE_CREATE_VERSION}.log\" & +function(write_rel_shell_script filename script) + file(WRITE ${filename} "#!/usr/bin/env bash +\"${CMAKE_COMMAND}\" -DCMAKE_CREATE_VERSION=${CMAKE_CREATE_VERSION} -DCMAKE_DOC_TARBALL=\"${CMAKE_DOC_TARBALL}\" -P \"${CMAKE_CURRENT_LIST_DIR}/${script}.cmake\" < /dev/null 2>&1 | tee \"${CMAKE_CURRENT_SOURCE_DIR}/logs/${script}-${CMAKE_CREATE_VERSION}.log\" ") - math(EXPR i "${i}+1") - endforeach() execute_process(COMMAND chmod a+x ${filename}) endfunction() @@ -65,12 +45,16 @@ echo 'Failed to create \${name}.tar.gz' endfunction() write_docs_shell_script("create-${CMAKE_CREATE_VERSION}-docs.sh") -write_batch_shell_script("create-${CMAKE_CREATE_VERSION}-batch1.sh" ${RELEASE_SCRIPTS_BATCH_1}) -write_batch_shell_script("create-${CMAKE_CREATE_VERSION}-batch2.sh" ${RELEASE_SCRIPTS_BATCH_2}) - -message("Run one at a time: - ./create-${CMAKE_CREATE_VERSION}-docs.sh && - ./create-${CMAKE_CREATE_VERSION}-batch1.sh && - ./create-${CMAKE_CREATE_VERSION}-batch2.sh && +write_rel_shell_script("create-${CMAKE_CREATE_VERSION}-linux64.sh" linux64_release) # Linux x86_64 +write_rel_shell_script("create-${CMAKE_CREATE_VERSION}-macos.sh" osx_release ) # macOS x86_64 +write_rel_shell_script("create-${CMAKE_CREATE_VERSION}-win64.sh" win64_release ) # Windows x64 +write_rel_shell_script("create-${CMAKE_CREATE_VERSION}-win32.sh" win32_release ) # Windows x86 + +message("Build docs first and then build for each platform: + ./create-${CMAKE_CREATE_VERSION}-docs.sh && + ./create-${CMAKE_CREATE_VERSION}-linux64.sh && + ./create-${CMAKE_CREATE_VERSION}-macos.sh && + ./create-${CMAKE_CREATE_VERSION}-win64.sh && + ./create-${CMAKE_CREATE_VERSION}-win32.sh && echo done ") diff --git a/Utilities/Release/win32_release.cmake b/Utilities/Release/win32_release.cmake index 468e5f4..f0f51b8 100644 --- a/Utilities/Release/win32_release.cmake +++ b/Utilities/Release/win32_release.cmake @@ -28,8 +28,7 @@ CMAKE_Fortran_COMPILER:FILEPATH=FALSE CMAKE_GENERATOR:INTERNAL=Ninja BUILD_QtDialog:BOOL=TRUE CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3 -CMAKE_C_FLAGS_RELEASE:STRING=-MT -O2 -Ob2 -DNDEBUG -CMAKE_CXX_FLAGS_RELEASE:STRING=-MT -O2 -Ob2 -DNDEBUG +CMAKE_MSVC_RUNTIME_LIBRARY:STRING=MultiThreaded$<$<CONFIG:Debug>:Debug> CMAKE_EXE_LINKER_FLAGS:STRING=-machine:x86 -subsystem:console,6.01 CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES:STRING=${qt_win_libs} CMAKE_PREFIX_PATH:STRING=${qt_prefix} diff --git a/Utilities/Release/win64_release.cmake b/Utilities/Release/win64_release.cmake index 5a93ce6..149d378 100644 --- a/Utilities/Release/win64_release.cmake +++ b/Utilities/Release/win64_release.cmake @@ -28,8 +28,7 @@ CMAKE_Fortran_COMPILER:FILEPATH=FALSE CMAKE_GENERATOR:INTERNAL=Ninja BUILD_QtDialog:BOOL=TRUE CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3 -CMAKE_C_FLAGS_RELEASE:STRING=-MT -O2 -Ob2 -DNDEBUG -CMAKE_CXX_FLAGS_RELEASE:STRING=-MT -O2 -Ob2 -DNDEBUG +CMAKE_MSVC_RUNTIME_LIBRARY:STRING=MultiThreaded$<$<CONFIG:Debug>:Debug> CMAKE_EXE_LINKER_FLAGS:STRING=-machine:x64 -subsystem:console,6.01 CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES:STRING=${qt_win_libs} CMAKE_PREFIX_PATH:STRING=${qt_prefix} diff --git a/Utilities/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt index c5b2bfe..17c5018 100644 --- a/Utilities/Sphinx/CMakeLists.txt +++ b/Utilities/Sphinx/CMakeLists.txt @@ -3,11 +3,11 @@ if(NOT CMake_SOURCE_DIR) set(CMakeHelp_STANDALONE 1) - cmake_minimum_required(VERSION 3.1...3.14 FATAL_ERROR) + cmake_minimum_required(VERSION 3.1...3.15 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) - include(${CMake_SOURCE_DIR}/Source/CMakeVersionCompute.cmake) + include(${CMake_SOURCE_DIR}/Source/CMakeVersion.cmake) include(${CMake_SOURCE_DIR}/Source/CMakeInstallDestinations.cmake) unset(CMAKE_DATA_DIR) unset(CMAKE_DATA_DIR CACHE) @@ -105,7 +105,6 @@ if(SPHINX_QTHELP) # Workaround sphinx configurability: # https://bitbucket.org/birkenfeld/sphinx/issue/1448/make-qthelp-more-configurable COMMAND ${CMAKE_COMMAND} "-DQTHELP_DIR=${CMAKE_CURRENT_BINARY_DIR}/qthelp/" - "-DCMake_VERSION=${CMake_VERSION_MAJOR}${CMake_VERSION_MINOR}${CMake_VERSION_PATCH}" -P "${CMAKE_CURRENT_SOURCE_DIR}/fixup_qthelp_names.cmake" # Create proper identifiers. Workaround for @@ -216,7 +215,7 @@ endif() if(SPHINX_QTHELP) CMake_OPTIONAL_COMPONENT(sphinx-qthelp) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qthelp/CMake-${CMake_VERSION_MAJOR}${CMake_VERSION_MINOR}${CMake_VERSION_PATCH}.qch + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qthelp/CMake.qch DESTINATION ${CMAKE_DOC_DIR} ${COMPONENT} ) endif() diff --git a/Utilities/Sphinx/conf.py.in b/Utilities/Sphinx/conf.py.in index 70ba080..e50c4f9 100644 --- a/Utilities/Sphinx/conf.py.in +++ b/Utilities/Sphinx/conf.py.in @@ -82,4 +82,4 @@ html_favicon = '@conf_path@/static/cmake-favicon.ico' # Not supported yet by sphinx: # https://bitbucket.org/birkenfeld/sphinx/issue/1448/make-qthelp-more-configurable # qthelp_namespace = "org.cmake" -# qthelp_qch_name = "CMake-300.qch" +# qthelp_qch_name = "CMake.qch" diff --git a/Utilities/Sphinx/fixup_qthelp_names.cmake b/Utilities/Sphinx/fixup_qthelp_names.cmake index e35ef25..179e846 100644 --- a/Utilities/Sphinx/fixup_qthelp_names.cmake +++ b/Utilities/Sphinx/fixup_qthelp_names.cmake @@ -10,15 +10,6 @@ string(REPLACE QHCP_CONTENT "${QHCP_CONTENT}" ) -string(REPLACE - "<output>CMake.qch" "<output>CMake-${CMake_VERSION}.qch" - QHCP_CONTENT "${QHCP_CONTENT}" -) -string(REPLACE - "<file>CMake.qch" "<file>CMake-${CMake_VERSION}.qch" - QHCP_CONTENT "${QHCP_CONTENT}" -) - file(WRITE "${QTHELP_DIR}/CMake.qhcp" "${QHCP_CONTENT}") diff --git a/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake b/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake index 15ba46e..60ee8e6 100644 --- a/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake +++ b/Utilities/cmcurl/CMake/CurlSymbolHiding.cmake @@ -53,7 +53,7 @@ elseif(MSVC) message(WARNING "Hiding private symbols regardless CURL_HIDDEN_SYMBOLS being disabled.") set(HIDES_CURL_PRIVATE_SYMBOLS TRUE) endif() -elseif() +else() set(HIDES_CURL_PRIVATE_SYMBOLS FALSE) endif() diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt index 37522fc..bc8a7dc 100644 --- a/Utilities/cmcurl/CMakeLists.txt +++ b/Utilities/cmcurl/CMakeLists.txt @@ -449,7 +449,12 @@ if(CMAKE_USE_SECTRANSP) endif() if(CMAKE_USE_OPENSSL) - find_package(OpenSSL REQUIRED) + find_package(OpenSSL) + if(NOT OpenSSL_FOUND) + message(FATAL_ERROR + "Could not find OpenSSL. Install an OpenSSL development package or " + "configure CMake with -DCMAKE_USE_OPENSSL=OFF to build without OpenSSL.") + endif() set(SSL_ENABLED ON) set(USE_OPENSSL ON) set(HAVE_LIBCRYPTO ON) diff --git a/Utilities/cmlibuv/include/uv.h b/Utilities/cmlibuv/include/uv.h index e6dc736..eb80bfb 100644 --- a/Utilities/cmlibuv/include/uv.h +++ b/Utilities/cmlibuv/include/uv.h @@ -206,6 +206,7 @@ typedef enum { /* Handle types. */ typedef struct uv_loop_s uv_loop_t; typedef struct uv_handle_s uv_handle_t; +typedef struct uv_dir_s uv_dir_t; typedef struct uv_stream_s uv_stream_t; typedef struct uv_tcp_s uv_tcp_t; typedef struct uv_udp_s uv_udp_t; @@ -634,7 +635,11 @@ UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock); UV_EXTERN int uv_udp_bind(uv_udp_t* handle, const struct sockaddr* addr, unsigned int flags); +UV_EXTERN int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr); +UV_EXTERN int uv_udp_getpeername(const uv_udp_t* handle, + struct sockaddr* name, + int* namelen); UV_EXTERN int uv_udp_getsockname(const uv_udp_t* handle, struct sockaddr* name, int* namelen); @@ -1112,6 +1117,11 @@ typedef struct { } uv_timeval_t; typedef struct { + int64_t tv_sec; + int32_t tv_usec; +} uv_timeval64_t; + +typedef struct { uv_timeval_t ru_utime; /* user CPU time used */ uv_timeval_t ru_stime; /* system CPU time used */ uint64_t ru_maxrss; /* maximum resident set size */ @@ -1162,6 +1172,17 @@ UV_EXTERN int uv_os_getenv(const char* name, char* buffer, size_t* size); UV_EXTERN int uv_os_setenv(const char* name, const char* value); UV_EXTERN int uv_os_unsetenv(const char* name); +#ifdef MAXHOSTNAMELEN +# define UV_MAXHOSTNAMESIZE (MAXHOSTNAMELEN + 1) +#else + /* + Fallback for the maximum hostname size, including the null terminator. The + Windows gethostname() documentation states that 256 bytes will always be + large enough to hold the null-terminated hostname. + */ +# define UV_MAXHOSTNAMESIZE 256 +#endif + UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size); UV_EXTERN int uv_os_uname(uv_utsname_t* buffer); @@ -1199,9 +1220,19 @@ typedef enum { UV_FS_FCHOWN, UV_FS_REALPATH, UV_FS_COPYFILE, - UV_FS_LCHOWN + UV_FS_LCHOWN, + UV_FS_OPENDIR, + UV_FS_READDIR, + UV_FS_CLOSEDIR } uv_fs_type; +struct uv_dir_s { + uv_dirent_t* dirents; + size_t nentries; + void* reserved[4]; + UV_DIR_PRIVATE_FIELDS +}; + /* uv_fs_t is a subclass of uv_req_t. */ struct uv_fs_s { UV_REQ_FIELDS @@ -1294,6 +1325,18 @@ UV_EXTERN int uv_fs_scandir(uv_loop_t* loop, uv_fs_cb cb); UV_EXTERN int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent); +UV_EXTERN int uv_fs_opendir(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_fs_cb cb); +UV_EXTERN int uv_fs_readdir(uv_loop_t* loop, + uv_fs_t* req, + uv_dir_t* dir, + uv_fs_cb cb); +UV_EXTERN int uv_fs_closedir(uv_loop_t* loop, + uv_fs_t* req, + uv_dir_t* dir, + uv_fs_cb cb); UV_EXTERN int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, @@ -1536,6 +1579,7 @@ UV_EXTERN int uv_chdir(const char* dir); UV_EXTERN uint64_t uv_get_free_memory(void); UV_EXTERN uint64_t uv_get_total_memory(void); +UV_EXTERN uint64_t uv_get_constrained_memory(void); UV_EXTERN uint64_t uv_hrtime(void); @@ -1589,9 +1633,29 @@ UV_EXTERN void uv_key_delete(uv_key_t* key); UV_EXTERN void* uv_key_get(uv_key_t* key); UV_EXTERN void uv_key_set(uv_key_t* key, void* value); +UV_EXTERN int uv_gettimeofday(uv_timeval64_t* tv); + typedef void (*uv_thread_cb)(void* arg); UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg); + +typedef enum { + UV_THREAD_NO_FLAGS = 0x00, + UV_THREAD_HAS_STACK_SIZE = 0x01 +} uv_thread_create_flags; + +struct uv_thread_options_s { + unsigned int flags; + size_t stack_size; + /* More fields may be added at any time. */ +}; + +typedef struct uv_thread_options_s uv_thread_options_t; + +UV_EXTERN int uv_thread_create_ex(uv_thread_t* tid, + const uv_thread_options_t* params, + uv_thread_cb entry, + void* arg); UV_EXTERN uv_thread_t uv_thread_self(void); UV_EXTERN int uv_thread_join(uv_thread_t *tid); UV_EXTERN int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2); diff --git a/Utilities/cmlibuv/include/uv/unix.h b/Utilities/cmlibuv/include/uv/unix.h index 3c1b363..011abcf 100644 --- a/Utilities/cmlibuv/include/uv/unix.h +++ b/Utilities/cmlibuv/include/uv/unix.h @@ -31,13 +31,14 @@ #include <netinet/in.h> #include <netinet/tcp.h> #include <arpa/inet.h> -#include <netdb.h> +#include <netdb.h> /* MAXHOSTNAMELEN on Solaris */ #include <termios.h> #include <pwd.h> #if !defined(__MVS__) #include <semaphore.h> +#include <sys/param.h> /* MAXHOSTNAMELEN on Linux and the BSDs */ #endif #include <pthread.h> #include <signal.h> @@ -50,8 +51,6 @@ # include "linux.h" #elif defined (__MVS__) # include "os390.h" -#elif defined(__PASE__) -# include "posix.h" #elif defined(_AIX) # include "aix.h" #elif defined(__sun) @@ -64,9 +63,12 @@ defined(__OpenBSD__) || \ defined(__NetBSD__) # include "bsd.h" -#elif defined(__CYGWIN__) || defined(__MSYS__) +#elif defined(__PASE__) || \ + defined(__CYGWIN__) || \ + defined(__MSYS__) || \ + defined(__GNU__) # include "posix.h" -#elif defined(__GNU__) +#elif defined(__HAIKU__) # include "posix.h" #endif @@ -149,7 +151,9 @@ typedef pthread_cond_t uv_cond_t; typedef pthread_key_t uv_key_t; /* Note: guard clauses should match uv_barrier_init's in src/unix/thread.c. */ -#if defined(_AIX) || !defined(PTHREAD_BARRIER_SERIAL_THREAD) +#if defined(_AIX) || \ + defined(__OpenBSD__) || \ + !defined(PTHREAD_BARRIER_SERIAL_THREAD) /* TODO(bnoordhuis) Merge into uv_barrier_t in v2. */ struct _uv_barrier { uv_mutex_t mutex; @@ -178,6 +182,9 @@ typedef uid_t uv_uid_t; typedef struct dirent uv__dirent_t; +#define UV_DIR_PRIVATE_FIELDS \ + DIR* dir; + #if defined(DT_UNKNOWN) # define HAVE_DIRENT_TYPES # if defined(DT_REG) diff --git a/Utilities/cmlibuv/include/uv/version.h b/Utilities/cmlibuv/include/uv/version.h index abc140a..97f0bc2 100644 --- a/Utilities/cmlibuv/include/uv/version.h +++ b/Utilities/cmlibuv/include/uv/version.h @@ -31,7 +31,7 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 24 +#define UV_VERSION_MINOR 29 #define UV_VERSION_PATCH 2 #define UV_VERSION_IS_RELEASE 0 #define UV_VERSION_SUFFIX "dev" diff --git a/Utilities/cmlibuv/include/uv/win.h b/Utilities/cmlibuv/include/uv/win.h index f3d3809..7f77cc2 100644 --- a/Utilities/cmlibuv/include/uv/win.h +++ b/Utilities/cmlibuv/include/uv/win.h @@ -312,6 +312,11 @@ typedef struct uv__dirent_s { char d_name[1]; } uv__dirent_t; +#define UV_DIR_PRIVATE_FIELDS \ + HANDLE dir_handle; \ + WIN32_FIND_DATAW find_data; \ + BOOL need_find_call; + #define HAVE_DIRENT_TYPES #define UV__DT_DIR UV_DIRENT_DIR #define UV__DT_FILE UV_DIRENT_FILE diff --git a/Utilities/cmlibuv/src/fs-poll.c b/Utilities/cmlibuv/src/fs-poll.c index 6c82dfc..89864e2 100644 --- a/Utilities/cmlibuv/src/fs-poll.c +++ b/Utilities/cmlibuv/src/fs-poll.c @@ -22,12 +22,20 @@ #include "uv.h" #include "uv-common.h" +#ifdef _WIN32 +#include "win/internal.h" +#include "win/handle-inl.h" +#define uv__make_close_pending(h) uv_want_endgame((h)->loop, (h)) +#else +#include "unix/internal.h" +#endif + #include <assert.h> #include <stdlib.h> #include <string.h> struct poll_ctx { - uv_fs_poll_t* parent_handle; /* NULL if parent has been stopped or closed */ + uv_fs_poll_t* parent_handle; int busy_polling; unsigned int interval; uint64_t start_time; @@ -36,6 +44,7 @@ struct poll_ctx { uv_timer_t timer_handle; uv_fs_t fs_req; /* TODO(bnoordhuis) mark fs_req internal */ uv_stat_t statbuf; + struct poll_ctx* previous; /* context from previous start()..stop() period */ char path[1]; /* variable length */ }; @@ -49,6 +58,7 @@ static uv_stat_t zero_statbuf; int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle) { uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_POLL); + handle->poll_ctx = NULL; return 0; } @@ -62,7 +72,7 @@ int uv_fs_poll_start(uv_fs_poll_t* handle, size_t len; int err; - if (uv__is_active(handle)) + if (uv_is_active((uv_handle_t*)handle)) return 0; loop = handle->loop; @@ -90,6 +100,8 @@ int uv_fs_poll_start(uv_fs_poll_t* handle, if (err < 0) goto error; + if (handle->poll_ctx != NULL) + ctx->previous = handle->poll_ctx; handle->poll_ctx = ctx; uv__handle_start(handle); @@ -104,19 +116,17 @@ error: int uv_fs_poll_stop(uv_fs_poll_t* handle) { struct poll_ctx* ctx; - if (!uv__is_active(handle)) + if (!uv_is_active((uv_handle_t*)handle)) return 0; ctx = handle->poll_ctx; assert(ctx != NULL); - assert(ctx->parent_handle != NULL); - ctx->parent_handle = NULL; - handle->poll_ctx = NULL; + assert(ctx->parent_handle == handle); /* Close the timer if it's active. If it's inactive, there's a stat request * in progress and poll_cb will take care of the cleanup. */ - if (uv__is_active(&ctx->timer_handle)) + if (uv_is_active((uv_handle_t*)&ctx->timer_handle)) uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb); uv__handle_stop(handle); @@ -129,7 +139,7 @@ int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) { struct poll_ctx* ctx; size_t required_len; - if (!uv__is_active(handle)) { + if (!uv_is_active((uv_handle_t*)handle)) { *size = 0; return UV_EINVAL; } @@ -153,6 +163,9 @@ int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size) { void uv__fs_poll_close(uv_fs_poll_t* handle) { uv_fs_poll_stop(handle); + + if (handle->poll_ctx == NULL) + uv__make_close_pending((uv_handle_t*)handle); } @@ -173,14 +186,13 @@ static void poll_cb(uv_fs_t* req) { uv_stat_t* statbuf; struct poll_ctx* ctx; uint64_t interval; + uv_fs_poll_t* handle; ctx = container_of(req, struct poll_ctx, fs_req); + handle = ctx->parent_handle; - if (ctx->parent_handle == NULL) { /* handle has been stopped or closed */ - uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb); - uv_fs_req_cleanup(req); - return; - } + if (!uv_is_active((uv_handle_t*)handle) || uv__is_closing(handle)) + goto out; if (req->result != 0) { if (ctx->busy_polling != req->result) { @@ -205,7 +217,7 @@ static void poll_cb(uv_fs_t* req) { out: uv_fs_req_cleanup(req); - if (ctx->parent_handle == NULL) { /* handle has been stopped by callback */ + if (!uv_is_active((uv_handle_t*)handle) || uv__is_closing(handle)) { uv_close((uv_handle_t*)&ctx->timer_handle, timer_close_cb); return; } @@ -219,8 +231,27 @@ out: } -static void timer_close_cb(uv_handle_t* handle) { - uv__free(container_of(handle, struct poll_ctx, timer_handle)); +static void timer_close_cb(uv_handle_t* timer) { + struct poll_ctx* ctx; + struct poll_ctx* it; + struct poll_ctx* last; + uv_fs_poll_t* handle; + + ctx = container_of(timer, struct poll_ctx, timer_handle); + handle = ctx->parent_handle; + if (ctx == handle->poll_ctx) { + handle->poll_ctx = ctx->previous; + if (handle->poll_ctx == NULL && uv__is_closing(handle)) + uv__make_close_pending((uv_handle_t*)handle); + } else { + for (last = handle->poll_ctx, it = last->previous; + it != ctx; + last = it, it = it->previous) { + assert(last->previous != NULL); + } + last->previous = ctx->previous; + } + uv__free(ctx); } diff --git a/Utilities/cmlibuv/src/threadpool.c b/Utilities/cmlibuv/src/threadpool.c index 4258933..7aa5755 100644 --- a/Utilities/cmlibuv/src/threadpool.c +++ b/Utilities/cmlibuv/src/threadpool.c @@ -27,7 +27,7 @@ #include <stdlib.h> -#define MAX_THREADPOOL_SIZE 128 +#define MAX_THREADPOOL_SIZE 1024 static uv_once_t once = UV_ONCE_INIT; static uv_cond_t cond; diff --git a/Utilities/cmlibuv/src/unix/aix.c b/Utilities/cmlibuv/src/unix/aix.c index 337e58e..1f36926 100644 --- a/Utilities/cmlibuv/src/unix/aix.c +++ b/Utilities/cmlibuv/src/unix/aix.c @@ -344,6 +344,11 @@ uint64_t uv_get_total_memory(void) { } +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + void uv_loadavg(double avg[3]) { perfstat_cpu_total_t ps_total; int result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1); @@ -1041,6 +1046,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { struct poll_ctl pc; assert(loop->watchers != NULL); + assert(fd >= 0); events = (struct pollfd*) loop->watchers[loop->nwatchers]; nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; diff --git a/Utilities/cmlibuv/src/unix/async.c b/Utilities/cmlibuv/src/unix/async.c index 0b450ae..a5c47bc 100644 --- a/Utilities/cmlibuv/src/unix/async.c +++ b/Utilities/cmlibuv/src/unix/async.c @@ -61,14 +61,43 @@ int uv_async_send(uv_async_t* handle) { if (ACCESS_ONCE(int, handle->pending) != 0) return 0; - if (cmpxchgi(&handle->pending, 0, 1) == 0) - uv__async_send(handle->loop); + /* Tell the other thread we're busy with the handle. */ + if (cmpxchgi(&handle->pending, 0, 1) != 0) + return 0; + + /* Wake up the other thread's event loop. */ + uv__async_send(handle->loop); + + /* Tell the other thread we're done. */ + if (cmpxchgi(&handle->pending, 1, 2) != 1) + abort(); return 0; } +/* Only call this from the event loop thread. */ +static int uv__async_spin(uv_async_t* handle) { + int rc; + + for (;;) { + /* rc=0 -- handle is not pending. + * rc=1 -- handle is pending, other thread is still working with it. + * rc=2 -- handle is pending, other thread is done. + */ + rc = cmpxchgi(&handle->pending, 2, 0); + + if (rc != 1) + return rc; + + /* Other thread is busy with this handle, spin until it's done. */ + cpu_relax(); + } +} + + void uv__async_close(uv_async_t* handle) { + uv__async_spin(handle); QUEUE_REMOVE(&handle->queue); uv__handle_stop(handle); } @@ -109,8 +138,8 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { QUEUE_REMOVE(q); QUEUE_INSERT_TAIL(&loop->async_handles, q); - if (cmpxchgi(&h->pending, 1, 0) == 0) - continue; + if (0 == uv__async_spin(h)) + continue; /* Not pending. */ if (h->async_cb == NULL) continue; diff --git a/Utilities/cmlibuv/src/unix/atomic-ops.h b/Utilities/cmlibuv/src/unix/atomic-ops.h index be741dc..995aca6 100644 --- a/Utilities/cmlibuv/src/unix/atomic-ops.h +++ b/Utilities/cmlibuv/src/unix/atomic-ops.h @@ -23,7 +23,6 @@ #endif UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)); -UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)); UV_UNUSED(static void cpu_relax(void)); /* Prefer hand-rolled assembly over the gcc builtins because the latter also @@ -49,43 +48,7 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) { else return op4; #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) - return atomic_cas_uint(ptr, oldval, newval); -#else - return __sync_val_compare_and_swap(ptr, oldval, newval); -#endif -} - -UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) { -#if defined(__i386__) || defined(__x86_64__) - long out; - __asm__ __volatile__ ("lock; cmpxchg %2, %1;" - : "=a" (out), "+m" (*(volatile long*) ptr) - : "r" (newval), "0" (oldval) - : "memory"); - return out; -#elif defined(_AIX) && (defined(__xlC__) || defined(__ibmxl__)) - const long out = (*(volatile int*) ptr); -# if defined(__64BIT__) - __compare_and_swaplp(ptr, &oldval, newval); -# else - __compare_and_swap(ptr, &oldval, newval); -# endif /* if defined(__64BIT__) */ - return out; -#elif defined (__MVS__) -#ifdef _LP64 - unsigned long long op4; - if (__plo_CSSTGR(ptr, (unsigned long long*) &oldval, newval, - (unsigned long long*) ptr, *ptr, &op4)) -#else - unsigned long op4; - if (__plo_CSST(ptr, (unsigned int*) &oldval, newval, - (unsigned int*) ptr, *ptr, &op4)) -#endif - return oldval; - else - return op4; -#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) - return atomic_cas_ulong(ptr, oldval, newval); + return atomic_cas_uint((uint_t *)ptr, (uint_t)oldval, (uint_t)newval); #else return __sync_val_compare_and_swap(ptr, oldval, newval); #endif diff --git a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c index 3c2253f..0d7bbe6 100644 --- a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c +++ b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c @@ -31,6 +31,10 @@ #include <net/if_dl.h> #endif +#if defined(__HAIKU__) +#define IFF_RUNNING IFF_LINK +#endif + static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) return 1; @@ -45,7 +49,8 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { if (exclude_type == UV__EXCLUDE_IFPHYS) return (ent->ifa_addr->sa_family != AF_LINK); #endif -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) || \ + defined(__HAIKU__) /* * On BSD getifaddrs returns information related to the raw underlying * devices. We're not interested in this information. @@ -84,7 +89,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { return 0; } - *addresses = uv__malloc(*count * sizeof(**addresses)); + /* Make sure the memory is initiallized to zero using calloc() */ + *addresses = uv__calloc(*count, sizeof(**addresses)); if (*addresses == NULL) { freeifaddrs(addrs); @@ -116,6 +122,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { address++; } +#if !(defined(__CYGWIN__) || defined(__MSYS__)) /* Fill in physical addresses for each interface */ for (ent = addrs; ent != NULL; ent = ent->ifa_next) { if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS)) @@ -124,20 +131,15 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { address = *addresses; for (i = 0; i < *count; i++) { -#if defined(__CYGWIN__) || defined(__MSYS__) - memset(address->phys_addr, 0, sizeof(address->phys_addr)); -#else if (strcmp(address->name, ent->ifa_name) == 0) { struct sockaddr_dl* sa_addr; sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } else { - memset(address->phys_addr, 0, sizeof(address->phys_addr)); } -#endif address++; } } +#endif freeifaddrs(addrs); diff --git a/Utilities/cmlibuv/src/unix/cmake-bootstrap.c b/Utilities/cmlibuv/src/unix/cmake-bootstrap.c index 309ec79..d42ff05 100644 --- a/Utilities/cmlibuv/src/unix/cmake-bootstrap.c +++ b/Utilities/cmlibuv/src/unix/cmake-bootstrap.c @@ -137,4 +137,13 @@ int uv__utimesat(int dirfd, const char* path, const struct timespec times[2], errno = ENOSYS; return -1; } + +int uv__statx(int dirfd, + const char* path, + int flags, + unsigned int mask, + struct uv__statx* statxbuf) { + errno = ENOSYS; + return -1; +} #endif diff --git a/Utilities/cmlibuv/src/unix/core.c b/Utilities/cmlibuv/src/unix/core.c index a8d6adb..93df7af 100644 --- a/Utilities/cmlibuv/src/unix/core.c +++ b/Utilities/cmlibuv/src/unix/core.c @@ -42,9 +42,9 @@ #include <pwd.h> #include <sched.h> #include <sys/utsname.h> +#include <sys/time.h> #ifdef __sun -# include <netdb.h> /* MAXHOSTNAMELEN on Solaris */ # include <sys/filio.h> # include <sys/types.h> # include <sys/wait.h> @@ -91,13 +91,8 @@ #include <sys/ioctl.h> #endif -#if !defined(__MVS__) -#include <sys/param.h> /* MAXHOSTNAMELEN on Linux and the BSDs */ -#endif - -/* Fallback for the maximum hostname length */ -#ifndef MAXHOSTNAMELEN -# define MAXHOSTNAMELEN 256 +#if defined(__linux__) +#include <sys/syscall.h> #endif static int uv__run_pending(uv_loop_t* loop); @@ -174,7 +169,9 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { case UV_FS_POLL: uv__fs_poll_close((uv_fs_poll_t*)handle); - break; + /* Poll handles use file system requests, and one of them may still be + * running. The poll code will call uv__make_close_pending() for us. */ + return; case UV_SIGNAL: uv__signal_close((uv_signal_t*) handle); @@ -520,6 +517,34 @@ skip: } +/* close() on macos has the "interesting" quirk that it fails with EINTR + * without closing the file descriptor when a thread is in the cancel state. + * That's why libuv calls close$NOCANCEL() instead. + * + * glibc on linux has a similar issue: close() is a cancellation point and + * will unwind the thread when it's in the cancel state. Work around that + * by making the system call directly. Musl libc is unaffected. + */ +int uv__close_nocancel(int fd) { +#if defined(__APPLE__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension" +#if defined(__LP64__) + extern int close$NOCANCEL(int); + return close$NOCANCEL(fd); +#else + extern int close$NOCANCEL$UNIX2003(int); + return close$NOCANCEL$UNIX2003(fd); +#endif +#pragma GCC diagnostic pop +#elif defined(__linux__) + return syscall(SYS_close, fd); +#else + return close(fd); +#endif +} + + int uv__close_nocheckstdio(int fd) { int saved_errno; int rc; @@ -527,7 +552,7 @@ int uv__close_nocheckstdio(int fd) { assert(fd > -1); /* Catch uninitialized io_watcher.fd bugs. */ saved_errno = errno; - rc = close(fd); + rc = uv__close_nocancel(fd); if (rc == -1) { rc = UV__ERR(errno); if (rc == UV_EINTR || rc == UV__ERR(EINPROGRESS)) @@ -562,7 +587,7 @@ int uv__nonblock_ioctl(int fd, int set) { } -#if !defined(__CYGWIN__) && !defined(__MSYS__) +#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__HAIKU__) int uv__cloexec_ioctl(int fd, int set) { int r; @@ -895,7 +920,8 @@ void uv__io_close(uv_loop_t* loop, uv__io_t* w) { QUEUE_REMOVE(&w->pending_queue); /* Remove stale events for this file descriptor */ - uv__platform_invalidate_fd(loop, w->fd); + if (w->fd != -1) + uv__platform_invalidate_fd(loop, w->fd); } @@ -929,7 +955,7 @@ int uv_getrusage(uv_rusage_t* rusage) { rusage->ru_stime.tv_sec = usage.ru_stime.tv_sec; rusage->ru_stime.tv_usec = usage.ru_stime.tv_usec; -#if !defined(__MVS__) +#if !defined(__MVS__) && !defined(__HAIKU__) rusage->ru_maxrss = usage.ru_maxrss; rusage->ru_ixrss = usage.ru_ixrss; rusage->ru_idrss = usage.ru_idrss; @@ -1294,7 +1320,7 @@ int uv_os_gethostname(char* buffer, size_t* size) { instead by creating a large enough buffer and comparing the hostname length to the size input. */ - char buf[MAXHOSTNAMELEN + 1]; + char buf[UV_MAXHOSTNAMESIZE]; size_t len; if (buffer == NULL || size == NULL || *size == 0) @@ -1426,3 +1452,39 @@ error: buffer->machine[0] = '\0'; return r; } + +int uv__getsockpeername(const uv_handle_t* handle, + uv__peersockfunc func, + struct sockaddr* name, + int* namelen) { + socklen_t socklen; + uv_os_fd_t fd; + int r; + + r = uv_fileno(handle, &fd); + if (r < 0) + return r; + + /* sizeof(socklen_t) != sizeof(int) on some systems. */ + socklen = (socklen_t) *namelen; + + if (func(fd, name, &socklen)) + return UV__ERR(errno); + + *namelen = (int) socklen; + return 0; +} + +int uv_gettimeofday(uv_timeval64_t* tv) { + struct timeval time; + + if (tv == NULL) + return UV_EINVAL; + + if (gettimeofday(&time, NULL) != 0) + return UV__ERR(errno); + + tv->tv_sec = (int64_t) time.tv_sec; + tv->tv_usec = (int32_t) time.tv_usec; + return 0; +} diff --git a/Utilities/cmlibuv/src/unix/darwin.c b/Utilities/cmlibuv/src/unix/darwin.c index 31ad8a9..e4cd8ff 100644 --- a/Utilities/cmlibuv/src/unix/darwin.c +++ b/Utilities/cmlibuv/src/unix/darwin.c @@ -117,6 +117,11 @@ uint64_t uv_get_total_memory(void) { } +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + void uv_loadavg(double avg[3]) { struct loadavg info; size_t size = sizeof(info); diff --git a/Utilities/cmlibuv/src/unix/freebsd.c b/Utilities/cmlibuv/src/unix/freebsd.c index 0f729cf..7de88d6 100644 --- a/Utilities/cmlibuv/src/unix/freebsd.c +++ b/Utilities/cmlibuv/src/unix/freebsd.c @@ -137,6 +137,11 @@ uint64_t uv_get_total_memory(void) { } +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + void uv_loadavg(double avg[3]) { struct loadavg info; size_t size = sizeof(info); diff --git a/Utilities/cmlibuv/src/unix/fs.c b/Utilities/cmlibuv/src/unix/fs.c index bffc956..3023b1e 100644 --- a/Utilities/cmlibuv/src/unix/fs.c +++ b/Utilities/cmlibuv/src/unix/fs.c @@ -47,7 +47,7 @@ #if defined(__DragonFly__) || \ defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel_) || \ + defined(__FreeBSD_kernel__) || \ defined(__OpenBSD__) || \ defined(__NetBSD__) # define HAVE_PREADV 1 @@ -60,7 +60,6 @@ #endif #if defined(__APPLE__) -# include <copyfile.h> # include <sys/sysctl.h> #elif defined(__linux__) && !defined(FICLONE) # include <sys/ioctl.h> @@ -143,19 +142,34 @@ extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */ while (0) +static int uv__fs_close(int fd) { + int rc; + + rc = uv__close_nocancel(fd); + if (rc == -1) + if (errno == EINTR || errno == EINPROGRESS) + rc = 0; /* The close is in progress, not an error. */ + + return rc; +} + + static ssize_t uv__fs_fsync(uv_fs_t* req) { #if defined(__APPLE__) /* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache * to the drive platters. This is in contrast to Linux's fdatasync and fsync * which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent * for flushing buffered data to permanent storage. If F_FULLFSYNC is not - * supported by the file system we should fall back to fsync(). This is the - * same approach taken by sqlite. + * supported by the file system we fall back to F_BARRIERFSYNC or fsync(). + * This is the same approach taken by sqlite, except sqlite does not issue + * an F_BARRIERFSYNC call. */ int r; r = fcntl(req->file, F_FULLFSYNC); if (r != 0) + r = fcntl(req->file, 85 /* F_BARRIERFSYNC */); /* fsync + barrier */ + if (r != 0) r = fsync(req->file); return r; #else @@ -178,7 +192,8 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) { static ssize_t uv__fs_futime(uv_fs_t* req) { #if defined(__linux__) \ - || defined(_AIX71) + || defined(_AIX71) \ + || defined(__HAIKU__) /* utimesat() has nanosecond resolution but we stick to microseconds * for the sake of consistency with other platforms. */ @@ -327,6 +342,18 @@ done: req->bufs = NULL; req->nbufs = 0; +#ifdef __PASE__ + /* PASE returns EOPNOTSUPP when reading a directory, convert to EISDIR */ + if (result == -1 && errno == EOPNOTSUPP) { + struct stat buf; + ssize_t rc; + rc = fstat(req->file, &buf); + if (rc == 0 && S_ISDIR(buf.st_mode)) { + errno = EISDIR; + } + } +#endif + return result; } @@ -349,7 +376,7 @@ static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) { static ssize_t uv__fs_scandir(uv_fs_t* req) { - uv__dirent_t **dents; + uv__dirent_t** dents; int n; dents = NULL; @@ -373,6 +400,87 @@ static ssize_t uv__fs_scandir(uv_fs_t* req) { return n; } +static int uv__fs_opendir(uv_fs_t* req) { + uv_dir_t* dir; + + dir = uv__malloc(sizeof(*dir)); + if (dir == NULL) + goto error; + + dir->dir = opendir(req->path); + if (dir->dir == NULL) + goto error; + + req->ptr = dir; + return 0; + +error: + uv__free(dir); + req->ptr = NULL; + return -1; +} + +static int uv__fs_readdir(uv_fs_t* req) { + uv_dir_t* dir; + uv_dirent_t* dirent; + struct dirent* res; + unsigned int dirent_idx; + unsigned int i; + + dir = req->ptr; + dirent_idx = 0; + + while (dirent_idx < dir->nentries) { + /* readdir() returns NULL on end of directory, as well as on error. errno + is used to differentiate between the two conditions. */ + errno = 0; + res = readdir(dir->dir); + + if (res == NULL) { + if (errno != 0) + goto error; + break; + } + + if (strcmp(res->d_name, ".") == 0 || strcmp(res->d_name, "..") == 0) + continue; + + dirent = &dir->dirents[dirent_idx]; + dirent->name = uv__strdup(res->d_name); + + if (dirent->name == NULL) + goto error; + + dirent->type = uv__fs_get_dirent_type(res); + ++dirent_idx; + } + + return dirent_idx; + +error: + for (i = 0; i < dirent_idx; ++i) { + uv__free((char*) dir->dirents[i].name); + dir->dirents[i].name = NULL; + } + + return -1; +} + +static int uv__fs_closedir(uv_fs_t* req) { + uv_dir_t* dir; + + dir = req->ptr; + + if (dir->dir != NULL) { + closedir(dir->dir); + dir->dir = NULL; + } + + uv__free(req->ptr); + req->ptr = NULL; + return 0; +} + #if defined(_POSIX_PATH_MAX) # define UV__FS_PATH_MAX _POSIX_PATH_MAX #elif defined(PATH_MAX) @@ -702,7 +810,8 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) { static ssize_t uv__fs_utime(uv_fs_t* req) { #if defined(__linux__) \ || defined(_AIX71) \ - || defined(__sun) + || defined(__sun) \ + || defined(__HAIKU__) /* utimesat() has nanosecond resolution but we stick to microseconds * for the sake of consistency with other platforms. */ @@ -806,45 +915,6 @@ done: } static ssize_t uv__fs_copyfile(uv_fs_t* req) { -#if defined(__APPLE__) && !TARGET_OS_IPHONE - /* On macOS, use the native copyfile(3). */ - static int can_clone; - copyfile_flags_t flags; - char buf[64]; - size_t len; - int major; - - flags = COPYFILE_ALL; - - if (req->flags & UV_FS_COPYFILE_EXCL) - flags |= COPYFILE_EXCL; - - /* Check OS version. Cloning is only supported on macOS >= 10.12. */ - if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { - if (can_clone == 0) { - len = sizeof(buf); - if (sysctlbyname("kern.osrelease", buf, &len, NULL, 0)) - return UV__ERR(errno); - - if (1 != sscanf(buf, "%d", &major)) - abort(); - - can_clone = -1 + 2 * (major >= 16); /* macOS >= 10.12 */ - } - - if (can_clone < 0) - return UV_ENOSYS; - } - - /* copyfile() simply ignores COPYFILE_CLONE if it's not supported. */ - if (req->flags & UV_FS_COPYFILE_FICLONE) - flags |= 1 << 24; /* COPYFILE_CLONE */ - - if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) - flags |= 1 << 25; /* COPYFILE_CLONE_FORCE */ - - return copyfile(req->path, req->new_path, NULL, flags); -#else uv_fs_t fs_req; uv_file srcfd; uv_file dstfd; @@ -971,7 +1041,6 @@ out: errno = UV__ERR(result); return -1; -#endif } static void uv__to_stat(struct stat* src, uv_stat_t* dst) { @@ -1051,10 +1120,84 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) { } +static int uv__fs_statx(int fd, + const char* path, + int is_fstat, + int is_lstat, + uv_stat_t* buf) { + STATIC_ASSERT(UV_ENOSYS != -1); +#ifdef __linux__ + static int no_statx; + struct uv__statx statxbuf; + int dirfd; + int flags; + int mode; + int rc; + + if (no_statx) + return UV_ENOSYS; + + dirfd = AT_FDCWD; + flags = 0; /* AT_STATX_SYNC_AS_STAT */ + mode = 0xFFF; /* STATX_BASIC_STATS + STATX_BTIME */ + + if (is_fstat) { + dirfd = fd; + flags |= 0x1000; /* AT_EMPTY_PATH */ + } + + if (is_lstat) + flags |= AT_SYMLINK_NOFOLLOW; + + rc = uv__statx(dirfd, path, flags, mode, &statxbuf); + + if (rc == -1) { + /* EPERM happens when a seccomp filter rejects the system call. + * Has been observed with libseccomp < 2.3.3 and docker < 18.04. + */ + if (errno != EINVAL && errno != EPERM && errno != ENOSYS) + return -1; + + no_statx = 1; + return UV_ENOSYS; + } + + buf->st_dev = 256 * statxbuf.stx_dev_major + statxbuf.stx_dev_minor; + buf->st_mode = statxbuf.stx_mode; + buf->st_nlink = statxbuf.stx_nlink; + buf->st_uid = statxbuf.stx_uid; + buf->st_gid = statxbuf.stx_gid; + buf->st_rdev = statxbuf.stx_rdev_major; + buf->st_ino = statxbuf.stx_ino; + buf->st_size = statxbuf.stx_size; + buf->st_blksize = statxbuf.stx_blksize; + buf->st_blocks = statxbuf.stx_blocks; + buf->st_atim.tv_sec = statxbuf.stx_atime.tv_sec; + buf->st_atim.tv_nsec = statxbuf.stx_atime.tv_nsec; + buf->st_mtim.tv_sec = statxbuf.stx_mtime.tv_sec; + buf->st_mtim.tv_nsec = statxbuf.stx_mtime.tv_nsec; + buf->st_ctim.tv_sec = statxbuf.stx_ctime.tv_sec; + buf->st_ctim.tv_nsec = statxbuf.stx_ctime.tv_nsec; + buf->st_birthtim.tv_sec = statxbuf.stx_btime.tv_sec; + buf->st_birthtim.tv_nsec = statxbuf.stx_btime.tv_nsec; + buf->st_flags = 0; + buf->st_gen = 0; + + return 0; +#else + return UV_ENOSYS; +#endif /* __linux__ */ +} + + static int uv__fs_stat(const char *path, uv_stat_t *buf) { struct stat pbuf; int ret; + ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 0, buf); + if (ret != UV_ENOSYS) + return ret; + ret = stat(path, &pbuf); if (ret == 0) uv__to_stat(&pbuf, buf); @@ -1067,6 +1210,10 @@ static int uv__fs_lstat(const char *path, uv_stat_t *buf) { struct stat pbuf; int ret; + ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 1, buf); + if (ret != UV_ENOSYS) + return ret; + ret = lstat(path, &pbuf); if (ret == 0) uv__to_stat(&pbuf, buf); @@ -1079,6 +1226,10 @@ static int uv__fs_fstat(int fd, uv_stat_t *buf) { struct stat pbuf; int ret; + ret = uv__fs_statx(fd, "", /* is_fstat */ 1, /* is_lstat */ 0, buf); + if (ret != UV_ENOSYS) + return ret; + ret = fstat(fd, &pbuf); if (ret == 0) uv__to_stat(&pbuf, buf); @@ -1167,7 +1318,7 @@ static void uv__fs_work(struct uv__work* w) { X(ACCESS, access(req->path, req->flags)); X(CHMOD, chmod(req->path, req->mode)); X(CHOWN, chown(req->path, req->uid, req->gid)); - X(CLOSE, close(req->file)); + X(CLOSE, uv__fs_close(req->file)); X(COPYFILE, uv__fs_copyfile(req)); X(FCHMOD, fchmod(req->file, req->mode)); X(FCHOWN, fchown(req->file, req->uid, req->gid)); @@ -1184,6 +1335,9 @@ static void uv__fs_work(struct uv__work* w) { X(OPEN, uv__fs_open(req)); X(READ, uv__fs_read(req)); X(SCANDIR, uv__fs_scandir(req)); + X(OPENDIR, uv__fs_opendir(req)); + X(READDIR, uv__fs_readdir(req)); + X(CLOSEDIR, uv__fs_closedir(req)); X(READLINK, uv__fs_readlink(req)); X(REALPATH, uv__fs_realpath(req)); X(RENAME, rename(req->path, req->new_path)); @@ -1454,6 +1608,40 @@ int uv_fs_scandir(uv_loop_t* loop, POST; } +int uv_fs_opendir(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_fs_cb cb) { + INIT(OPENDIR); + PATH; + POST; +} + +int uv_fs_readdir(uv_loop_t* loop, + uv_fs_t* req, + uv_dir_t* dir, + uv_fs_cb cb) { + INIT(READDIR); + + if (dir == NULL || dir->dir == NULL || dir->dirents == NULL) + return UV_EINVAL; + + req->ptr = dir; + POST; +} + +int uv_fs_closedir(uv_loop_t* loop, + uv_fs_t* req, + uv_dir_t* dir, + uv_fs_cb cb) { + INIT(CLOSEDIR); + + if (dir == NULL) + return UV_EINVAL; + + req->ptr = dir; + POST; +} int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, @@ -1594,6 +1782,9 @@ void uv_fs_req_cleanup(uv_fs_t* req) { req->path = NULL; req->new_path = NULL; + if (req->fs_type == UV_FS_READDIR && req->ptr != NULL) + uv__fs_readdir_cleanup(req); + if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL) uv__fs_scandir_cleanup(req); @@ -1601,7 +1792,7 @@ void uv_fs_req_cleanup(uv_fs_t* req) { uv__free(req->bufs); req->bufs = NULL; - if (req->ptr != &req->statbuf) + if (req->fs_type != UV_FS_OPENDIR && req->ptr != &req->statbuf) uv__free(req->ptr); req->ptr = NULL; } diff --git a/Utilities/cmlibuv/src/unix/fsevents.c b/Utilities/cmlibuv/src/unix/fsevents.c index c430562..ddacda3 100644 --- a/Utilities/cmlibuv/src/unix/fsevents.c +++ b/Utilities/cmlibuv/src/unix/fsevents.c @@ -21,9 +21,10 @@ #include "uv.h" #include "internal.h" -#if TARGET_OS_IPHONE +#if TARGET_OS_IPHONE || MAC_OS_X_VERSION_MAX_ALLOWED < 1070 /* iOS (currently) doesn't provide the FSEvents-API (nor CoreServices) */ +/* macOS prior to 10.7 doesn't provide the full FSEvents API so use kqueue */ int uv__fsevents_init(uv_fs_event_t* handle) { return 0; diff --git a/Utilities/cmlibuv/src/unix/getaddrinfo.c b/Utilities/cmlibuv/src/unix/getaddrinfo.c index 6d23fbe..d7ca7d1 100644 --- a/Utilities/cmlibuv/src/unix/getaddrinfo.c +++ b/Utilities/cmlibuv/src/unix/getaddrinfo.c @@ -92,7 +92,9 @@ int uv__getaddrinfo_translate_error(int sys_err) { } assert(!"unknown EAI_* error code"); abort(); +#ifndef __SUNPRO_C return 0; /* Pacify compiler. */ +#endif } diff --git a/Utilities/cmlibuv/src/unix/haiku.c b/Utilities/cmlibuv/src/unix/haiku.c new file mode 100644 index 0000000..7708851 --- /dev/null +++ b/Utilities/cmlibuv/src/unix/haiku.c @@ -0,0 +1,176 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include <FindDirectory.h> /* find_path() */ +#include <OS.h> + + +void uv_loadavg(double avg[3]) { + avg[0] = 0; + avg[1] = 0; + avg[2] = 0; +} + + +int uv_exepath(char* buffer, size_t* size) { + char abspath[B_PATH_NAME_LENGTH]; + status_t status; + ssize_t abspath_len; + + if (buffer == NULL || size == NULL || *size == 0) + return UV_EINVAL; + + status = find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH, NULL, abspath, + sizeof(abspath)); + if (status != B_OK) + return UV__ERR(status); + + abspath_len = uv__strscpy(buffer, abspath, *size); + *size -= 1; + if (abspath_len >= 0 && *size > (size_t)abspath_len) + *size = (size_t)abspath_len; + + return 0; +} + + +uint64_t uv_get_free_memory(void) { + status_t status; + system_info sinfo; + + status = get_system_info(&sinfo); + if (status != B_OK) + return 0; + + return (sinfo.max_pages - sinfo.used_pages) * B_PAGE_SIZE; +} + + +uint64_t uv_get_total_memory(void) { + status_t status; + system_info sinfo; + + status = get_system_info(&sinfo); + if (status != B_OK) + return 0; + + return sinfo.max_pages * B_PAGE_SIZE; +} + + +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + +int uv_resident_set_memory(size_t* rss) { + area_info area; + ssize_t cookie; + status_t status; + thread_info thread; + + status = get_thread_info(find_thread(NULL), &thread); + if (status != B_OK) + return UV__ERR(status); + + cookie = 0; + *rss = 0; + while (get_next_area_info(thread.team, &cookie, &area) == B_OK) + *rss += area.ram_size; + + return 0; +} + + +int uv_uptime(double* uptime) { + /* system_time() returns time since booting in microseconds */ + *uptime = (double)system_time() / 1000000; + return 0; +} + + +int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { + cpu_topology_node_info* topology_infos; + int i; + status_t status; + system_info system; + uint32_t topology_count; + uint64_t cpuspeed; + uv_cpu_info_t* cpu_info; + + if (cpu_infos == NULL || count == NULL) + return UV_EINVAL; + + status = get_cpu_topology_info(NULL, &topology_count); + if (status != B_OK) + return UV__ERR(status); + + topology_infos = uv__malloc(topology_count * sizeof(*topology_infos)); + if (topology_infos == NULL) + return UV_ENOMEM; + + status = get_cpu_topology_info(topology_infos, &topology_count); + if (status != B_OK) { + uv__free(topology_infos); + return UV__ERR(status); + } + + cpuspeed = 0; + for (i = 0; i < (int)topology_count; i++) { + if (topology_infos[i].type == B_TOPOLOGY_CORE) { + cpuspeed = topology_infos[i].data.core.default_frequency; + break; + } + } + + uv__free(topology_infos); + + status = get_system_info(&system); + if (status != B_OK) + return UV__ERR(status); + + *cpu_infos = uv__calloc(system.cpu_count, sizeof(**cpu_infos)); + if (*cpu_infos == NULL) + return UV_ENOMEM; + + /* CPU time and model are not exposed by Haiku. */ + cpu_info = *cpu_infos; + for (i = 0; i < (int)system.cpu_count; i++) { + cpu_info->model = uv__strdup("unknown"); + cpu_info->speed = (int)(cpuspeed / 1000000); + cpu_info++; + } + *count = system.cpu_count; + + return 0; +} + +void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { + int i; + + for (i = 0; i < count; i++) + uv__free(cpu_infos[i].model); + + uv__free(cpu_infos); +} diff --git a/Utilities/cmlibuv/src/unix/ibmi.c b/Utilities/cmlibuv/src/unix/ibmi.c index 13fed6c..c7e1051 100644 --- a/Utilities/cmlibuv/src/unix/ibmi.c +++ b/Utilities/cmlibuv/src/unix/ibmi.c @@ -55,19 +55,155 @@ #include <strings.h> #include <sys/vnode.h> +#include <as400_protos.h> + + +typedef struct { + int bytes_available; + int bytes_returned; + char current_date_and_time[8]; + char system_name[8]; + char elapsed_time[6]; + char restricted_state_flag; + char reserved; + int percent_processing_unit_used; + int jobs_in_system; + int percent_permanent_addresses; + int percent_temporary_addresses; + int system_asp; + int percent_system_asp_used; + int total_auxiliary_storage; + int current_unprotected_storage_used; + int maximum_unprotected_storage_used; + int percent_db_capability; + int main_storage_size; + int number_of_partitions; + int partition_identifier; + int reserved1; + int current_processing_capacity; + char processor_sharing_attribute; + char reserved2[3]; + int number_of_processors; + int active_jobs_in_system; + int active_threads_in_system; + int maximum_jobs_in_system; + int percent_temporary_256mb_segments_used; + int percent_temporary_4gb_segments_used; + int percent_permanent_256mb_segments_used; + int percent_permanent_4gb_segments_used; + int percent_current_interactive_performance; + int percent_uncapped_cpu_capacity_used; + int percent_shared_processor_pool_used; + long main_storage_size_long; +} SSTS0200; + + +static int get_ibmi_system_status(SSTS0200* rcvr) { + /* rcvrlen is input parameter 2 to QWCRSSTS */ + unsigned int rcvrlen = sizeof(*rcvr); + + /* format is input parameter 3 to QWCRSSTS ("SSTS0200" in EBCDIC) */ + unsigned char format[] = {0xE2, 0xE2, 0xE3, 0xE2, 0xF0, 0xF2, 0xF0, 0xF0}; + + /* reset_status is input parameter 4 to QWCRSSTS ("*NO " in EBCDIC) */ + unsigned char reset_status[] = { + 0x5C, 0xD5, 0xD6, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 + }; + + /* errcode is input parameter 5 to QWCRSSTS */ + struct _errcode { + int bytes_provided; + int bytes_available; + char msgid[7]; + } errcode; + + /* qwcrssts_pointer is the 16-byte tagged system pointer to QWCRSSTS */ + ILEpointer __attribute__((aligned(16))) qwcrssts_pointer; + + /* qwcrssts_argv is the array of argument pointers to QWCRSSTS */ + void* qwcrssts_argv[6]; + + /* Set the IBM i pointer to the QSYS/QWCRSSTS *PGM object */ + int rc = _RSLOBJ2(&qwcrssts_pointer, RSLOBJ_TS_PGM, "QWCRSSTS", "QSYS"); + + if (rc != 0) + return rc; + + /* initialize the QWCRSSTS returned info structure */ + memset(rcvr, 0, sizeof(*rcvr)); + + /* initialize the QWCRSSTS error code structure */ + memset(&errcode, 0, sizeof(errcode)); + errcode.bytes_provided = sizeof(errcode); + + /* initialize the array of argument pointers for the QWCRSSTS API */ + qwcrssts_argv[0] = rcvr; + qwcrssts_argv[1] = &rcvrlen; + qwcrssts_argv[2] = &format; + qwcrssts_argv[3] = &reset_status; + qwcrssts_argv[4] = &errcode; + qwcrssts_argv[5] = NULL; + + /* Call the IBM i QWCRSSTS API from PASE */ + rc = _PGMCALL(&qwcrssts_pointer, (void**)&qwcrssts_argv, 0); + + return rc; +} + + uint64_t uv_get_free_memory(void) { - return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES); + SSTS0200 rcvr; + + if (get_ibmi_system_status(&rcvr)) + return 0; + + /* The amount of main storage, in kilobytes, in the system. */ + uint64_t main_storage_size = rcvr.main_storage_size; + + /* The current amount of storage in use for temporary objects. + * in millions (M) of bytes. + */ + uint64_t current_unprotected_storage_used = + rcvr.current_unprotected_storage_used * 1024ULL; + + uint64_t free_storage_size = + (main_storage_size - current_unprotected_storage_used) * 1024ULL; + + return free_storage_size < 0 ? 0 : free_storage_size; } uint64_t uv_get_total_memory(void) { - return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES); + SSTS0200 rcvr; + + if (get_ibmi_system_status(&rcvr)) + return 0; + + return (uint64_t)rcvr.main_storage_size * 1024ULL; +} + + +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ } void uv_loadavg(double avg[3]) { + SSTS0200 rcvr; + + if (get_ibmi_system_status(&rcvr)) { avg[0] = avg[1] = avg[2] = 0; return; + } + + /* The average (in tenths) of the elapsed time during which the processing + * units were in use. For example, a value of 411 in binary would be 41.1%. + * This percentage could be greater than 100% for an uncapped partition. + */ + double processing_unit_used_percent = + rcvr.percent_processing_unit_used / 1000.0; + + avg[0] = avg[1] = avg[2] = processing_unit_used_percent; } @@ -111,3 +247,4 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { return 0; } + diff --git a/Utilities/cmlibuv/src/unix/internal.h b/Utilities/cmlibuv/src/unix/internal.h index 48fe6e8..b43c0b1 100644 --- a/Utilities/cmlibuv/src/unix/internal.h +++ b/Utilities/cmlibuv/src/unix/internal.h @@ -105,8 +105,7 @@ int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset); */ #if defined(__clang__) || \ defined(__GNUC__) || \ - defined(__INTEL_COMPILER) || \ - defined(__SUNPRO_C) + defined(__INTEL_COMPILER) # define UV_DESTRUCTOR(declaration) __attribute__((destructor)) declaration # define UV_UNUSED(declaration) __attribute__((unused)) declaration #else @@ -194,6 +193,7 @@ int uv__nonblock_ioctl(int fd, int set); int uv__nonblock_fcntl(int fd, int set); int uv__close(int fd); /* preserves errno */ int uv__close_nocheckstdio(int fd); +int uv__close_nocancel(int fd); int uv__socket(int domain, int type, int protocol); ssize_t uv__recvmsg(int fd, struct msghdr *msg, int flags); void uv__make_close_pending(uv_handle_t* handle); @@ -316,4 +316,11 @@ UV_UNUSED(static char* uv__basename_r(const char* path)) { int uv__inotify_fork(uv_loop_t* loop, void* old_watchers); #endif +typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*); + +int uv__getsockpeername(const uv_handle_t* handle, + uv__peersockfunc func, + struct sockaddr* name, + int* namelen); + #endif /* UV_UNIX_INTERNAL_H_ */ diff --git a/Utilities/cmlibuv/src/unix/kqueue.c b/Utilities/cmlibuv/src/unix/kqueue.c index c24f96e..c04e7a4 100644 --- a/Utilities/cmlibuv/src/unix/kqueue.c +++ b/Utilities/cmlibuv/src/unix/kqueue.c @@ -59,7 +59,7 @@ int uv__kqueue_init(uv_loop_t* loop) { } -#if defined(__APPLE__) +#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 static int uv__has_forked_with_cfrunloop; #endif @@ -70,7 +70,7 @@ int uv__io_fork(uv_loop_t* loop) { if (err) return err; -#if defined(__APPLE__) +#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 if (loop->cf_state != NULL) { /* We cannot start another CFRunloop and/or thread in the child process; CF aborts if you try or if you try to touch the thread @@ -86,7 +86,7 @@ int uv__io_fork(uv_loop_t* loop) { uv__free(loop->cf_state); loop->cf_state = NULL; } -#endif +#endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */ return err; } @@ -387,6 +387,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { uintptr_t nfds; assert(loop->watchers != NULL); + assert(fd >= 0); events = (struct kevent*) loop->watchers[loop->nwatchers]; nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; @@ -457,7 +458,7 @@ int uv_fs_event_start(uv_fs_event_t* handle, if (uv__is_active(handle)) return UV_EINVAL; -#if defined(__APPLE__) +#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 /* Nullify field to perform checks later */ handle->cf_cb = NULL; handle->realpath = NULL; @@ -481,7 +482,7 @@ int uv_fs_event_start(uv_fs_event_t* handle, } return r; } -#endif /* defined(__APPLE__) */ +#endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */ /* TODO open asynchronously - but how do we report back errors? */ fd = open(path, O_RDONLY); @@ -489,8 +490,11 @@ int uv_fs_event_start(uv_fs_event_t* handle, return UV__ERR(errno); handle->path = uv__strdup(path); - if (handle->path == NULL) + if (handle->path == NULL) { + uv__close_nocheckstdio(fd); return UV_ENOMEM; + } + handle->cb = cb; uv__handle_start(handle); uv__io_init(&handle->event_watcher, uv__fs_event, fd); @@ -509,7 +513,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { uv__handle_stop(handle); -#if defined(__APPLE__) +#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 if (!uv__has_forked_with_cfrunloop) r = uv__fsevents_close(handle); #endif diff --git a/Utilities/cmlibuv/src/unix/linux-core.c b/Utilities/cmlibuv/src/unix/linux-core.c index 3341b94..b539beb 100644 --- a/Utilities/cmlibuv/src/unix/linux-core.c +++ b/Utilities/cmlibuv/src/unix/linux-core.c @@ -26,6 +26,7 @@ #include "uv.h" #include "internal.h" +#include <inttypes.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -79,16 +80,20 @@ static int read_times(FILE* statfile_fp, unsigned int numcpus, uv_cpu_info_t* ci); static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci); -static unsigned long read_cpufreq(unsigned int cpunum); +static uint64_t read_cpufreq(unsigned int cpunum); int uv__platform_loop_init(uv_loop_t* loop) { int fd; - fd = epoll_create1(EPOLL_CLOEXEC); + /* It was reported that EPOLL_CLOEXEC is not defined on Android API < 21, + * a.k.a. Lollipop. Since EPOLL_CLOEXEC is an alias for O_CLOEXEC on all + * architectures, we just use that instead. + */ + fd = epoll_create1(O_CLOEXEC); /* epoll_create1() can fail either because it's not implemented (old kernel) - * or because it doesn't understand the EPOLL_CLOEXEC flag. + * or because it doesn't understand the O_CLOEXEC flag. */ if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) { fd = epoll_create(256); @@ -141,6 +146,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { uintptr_t nfds; assert(loop->watchers != NULL); + assert(fd >= 0); events = (struct epoll_event*) loop->watchers[loop->nwatchers]; nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; @@ -714,20 +720,20 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) { static int read_times(FILE* statfile_fp, unsigned int numcpus, uv_cpu_info_t* ci) { - unsigned long clock_ticks; struct uv_cpu_times_s ts; - unsigned long user; - unsigned long nice; - unsigned long sys; - unsigned long idle; - unsigned long dummy; - unsigned long irq; - unsigned int num; - unsigned int len; + uint64_t clock_ticks; + uint64_t user; + uint64_t nice; + uint64_t sys; + uint64_t idle; + uint64_t dummy; + uint64_t irq; + uint64_t num; + uint64_t len; char buf[1024]; clock_ticks = sysconf(_SC_CLK_TCK); - assert(clock_ticks != (unsigned long) -1); + assert(clock_ticks != (uint64_t) -1); assert(clock_ticks != 0); rewind(statfile_fp); @@ -760,7 +766,8 @@ static int read_times(FILE* statfile_fp, * fields, they're not allowed in C89 mode. */ if (6 != sscanf(buf + len, - "%lu %lu %lu %lu %lu %lu", + "%" PRIu64 " %" PRIu64 " %" PRIu64 + "%" PRIu64 " %" PRIu64 " %" PRIu64, &user, &nice, &sys, @@ -782,8 +789,8 @@ static int read_times(FILE* statfile_fp, } -static unsigned long read_cpufreq(unsigned int cpunum) { - unsigned long val; +static uint64_t read_cpufreq(unsigned int cpunum) { + uint64_t val; char buf[1024]; FILE* fp; @@ -796,7 +803,7 @@ static unsigned long read_cpufreq(unsigned int cpunum) { if (fp == NULL) return 0; - if (fscanf(fp, "%lu", &val) != 1) + if (fscanf(fp, "%" PRIu64, &val) != 1) val = 0; fclose(fp); @@ -859,7 +866,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { return 0; } - *addresses = uv__malloc(*count * sizeof(**addresses)); + /* Make sure the memory is initiallized to zero using calloc() */ + *addresses = uv__calloc(*count, sizeof(**addresses)); if (!(*addresses)) { freeifaddrs(addrs); return UV_ENOMEM; @@ -898,11 +906,12 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { address = *addresses; for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { + size_t namelen = strlen(ent->ifa_name); + /* Alias interface share the same physical address */ + if (strncmp(address->name, ent->ifa_name, namelen) == 0 && + (address->name[namelen] == 0 || address->name[namelen] == ':')) { sll = (struct sockaddr_ll*)ent->ifa_addr; memcpy(address->phys_addr, sll->sll_addr, sizeof(address->phys_addr)); - } else { - memset(address->phys_addr, 0, sizeof(address->phys_addr)); } address++; } @@ -932,3 +941,114 @@ void uv__set_process_title(const char* title) { prctl(PR_SET_NAME, title); /* Only copies first 16 characters. */ #endif } + + +static uint64_t uv__read_proc_meminfo(const char* what) { + uint64_t rc; + ssize_t n; + char* p; + int fd; + char buf[4096]; /* Large enough to hold all of /proc/meminfo. */ + + rc = 0; + fd = uv__open_cloexec("/proc/meminfo", O_RDONLY); + + if (fd == -1) + return 0; + + n = read(fd, buf, sizeof(buf) - 1); + + if (n <= 0) + goto out; + + buf[n] = '\0'; + p = strstr(buf, what); + + if (p == NULL) + goto out; + + p += strlen(what); + + if (1 != sscanf(p, "%" PRIu64 " kB", &rc)) + goto out; + + rc *= 1024; + +out: + + if (uv__close_nocheckstdio(fd)) + abort(); + + return rc; +} + + +uint64_t uv_get_free_memory(void) { + struct sysinfo info; + uint64_t rc; + + rc = uv__read_proc_meminfo("MemFree:"); + + if (rc != 0) + return rc; + + if (0 == sysinfo(&info)) + return (uint64_t) info.freeram * info.mem_unit; + + return 0; +} + + +uint64_t uv_get_total_memory(void) { + struct sysinfo info; + uint64_t rc; + + rc = uv__read_proc_meminfo("MemTotal:"); + + if (rc != 0) + return rc; + + if (0 == sysinfo(&info)) + return (uint64_t) info.totalram * info.mem_unit; + + return 0; +} + + +static uint64_t uv__read_cgroups_uint64(const char* cgroup, const char* param) { + char filename[256]; + uint64_t rc; + int fd; + ssize_t n; + char buf[32]; /* Large enough to hold an encoded uint64_t. */ + + snprintf(filename, 256, "/sys/fs/cgroup/%s/%s", cgroup, param); + + rc = 0; + fd = uv__open_cloexec(filename, O_RDONLY); + + if (fd < 0) + return 0; + + n = read(fd, buf, sizeof(buf) - 1); + + if (n > 0) { + buf[n] = '\0'; + sscanf(buf, "%" PRIu64, &rc); + } + + if (uv__close_nocheckstdio(fd)) + abort(); + + return rc; +} + + +uint64_t uv_get_constrained_memory(void) { + /* + * This might return 0 if there was a problem getting the memory limit from + * cgroups. This is OK because a return value of 0 signifies that the memory + * limit is unknown. + */ + return uv__read_cgroups_uint64("memory", "memory.limit_in_bytes"); +} diff --git a/Utilities/cmlibuv/src/unix/linux-syscalls.c b/Utilities/cmlibuv/src/unix/linux-syscalls.c index bfd7544..5637cf9 100644 --- a/Utilities/cmlibuv/src/unix/linux-syscalls.c +++ b/Utilities/cmlibuv/src/unix/linux-syscalls.c @@ -187,6 +187,21 @@ # endif #endif /* __NR_pwritev */ +#ifndef __NR_statx +# if defined(__x86_64__) +# define __NR_statx 332 +# elif defined(__i386__) +# define __NR_statx 383 +# elif defined(__aarch64__) +# define __NR_statx 397 +# elif defined(__arm__) +# define __NR_statx (UV_SYSCALL_BASE + 397) +# elif defined(__ppc__) +# define __NR_statx 383 +# elif defined(__s390__) +# define __NR_statx 379 +# endif +#endif /* __NR_statx */ int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) { #if defined(__i386__) @@ -336,3 +351,19 @@ int uv__dup3(int oldfd, int newfd, int flags) { return errno = ENOSYS, -1; #endif } + + +int uv__statx(int dirfd, + const char* path, + int flags, + unsigned int mask, + struct uv__statx* statxbuf) { + /* __NR_statx make Android box killed by SIGSYS. + * That looks like a seccomp2 sandbox filter rejecting the system call. + */ +#if defined(__NR_statx) && !defined(__ANDROID__) + return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf); +#else + return errno = ENOSYS, -1; +#endif +} diff --git a/Utilities/cmlibuv/src/unix/linux-syscalls.h b/Utilities/cmlibuv/src/unix/linux-syscalls.h index 3dfd329..7e58bfa 100644 --- a/Utilities/cmlibuv/src/unix/linux-syscalls.h +++ b/Utilities/cmlibuv/src/unix/linux-syscalls.h @@ -80,6 +80,36 @@ #define UV__IN_DELETE_SELF 0x400 #define UV__IN_MOVE_SELF 0x800 +struct uv__statx_timestamp { + int64_t tv_sec; + uint32_t tv_nsec; + int32_t unused0; +}; + +struct uv__statx { + uint32_t stx_mask; + uint32_t stx_blksize; + uint64_t stx_attributes; + uint32_t stx_nlink; + uint32_t stx_uid; + uint32_t stx_gid; + uint16_t stx_mode; + uint16_t unused0; + uint64_t stx_ino; + uint64_t stx_size; + uint64_t stx_blocks; + uint64_t stx_attributes_mask; + struct uv__statx_timestamp stx_atime; + struct uv__statx_timestamp stx_btime; + struct uv__statx_timestamp stx_ctime; + struct uv__statx_timestamp stx_mtime; + uint32_t stx_rdev_major; + uint32_t stx_rdev_minor; + uint32_t stx_dev_major; + uint32_t stx_dev_minor; + uint64_t unused1[14]; +}; + struct uv__inotify_event { int32_t wd; uint32_t mask; @@ -113,5 +143,10 @@ int uv__sendmmsg(int fd, ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset); ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset); int uv__dup3(int oldfd, int newfd, int flags); +int uv__statx(int dirfd, + const char* path, + int flags, + unsigned int mask, + struct uv__statx* statxbuf); #endif /* UV_LINUX_SYSCALL_H_ */ diff --git a/Utilities/cmlibuv/src/unix/netbsd.c b/Utilities/cmlibuv/src/unix/netbsd.c index a2a4e52..c649bb3 100644 --- a/Utilities/cmlibuv/src/unix/netbsd.c +++ b/Utilities/cmlibuv/src/unix/netbsd.c @@ -126,6 +126,11 @@ uint64_t uv_get_total_memory(void) { } +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + int uv_resident_set_memory(size_t* rss) { kvm_t *kd = NULL; struct kinfo_proc2 *kinfo = NULL; diff --git a/Utilities/cmlibuv/src/unix/openbsd.c b/Utilities/cmlibuv/src/unix/openbsd.c index bffb58b..ffae768 100644 --- a/Utilities/cmlibuv/src/unix/openbsd.c +++ b/Utilities/cmlibuv/src/unix/openbsd.c @@ -136,6 +136,11 @@ uint64_t uv_get_total_memory(void) { } +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + int uv_resident_set_memory(size_t* rss) { struct kinfo_proc kinfo; size_t page_size = getpagesize(); diff --git a/Utilities/cmlibuv/src/unix/os390.c b/Utilities/cmlibuv/src/unix/os390.c index dc146e3..273ded7 100644 --- a/Utilities/cmlibuv/src/unix/os390.c +++ b/Utilities/cmlibuv/src/unix/os390.c @@ -356,6 +356,11 @@ uint64_t uv_get_total_memory(void) { } +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + int uv_resident_set_memory(size_t* rss) { char* ascb; char* rax; @@ -657,6 +662,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { uintptr_t nfds; assert(loop->watchers != NULL); + assert(fd >= 0); events = (struct epoll_event*) loop->watchers[loop->nwatchers]; nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; diff --git a/Utilities/cmlibuv/src/unix/pipe.c b/Utilities/cmlibuv/src/unix/pipe.c index 9657bc9..7d97550 100644 --- a/Utilities/cmlibuv/src/unix/pipe.c +++ b/Utilities/cmlibuv/src/unix/pipe.c @@ -213,7 +213,7 @@ void uv_pipe_connect(uv_connect_t* req, } if (err == 0) - uv__io_start(handle->loop, &handle->io_watcher, POLLIN | POLLOUT); + uv__io_start(handle->loop, &handle->io_watcher, POLLOUT); out: handle->delayed_error = err; @@ -231,9 +231,6 @@ out: } -typedef int (*uv__peersockfunc)(int, struct sockaddr*, socklen_t*); - - static int uv__pipe_getsockpeername(const uv_pipe_t* handle, uv__peersockfunc func, char* buffer, @@ -244,10 +241,13 @@ static int uv__pipe_getsockpeername(const uv_pipe_t* handle, addrlen = sizeof(sa); memset(&sa, 0, addrlen); - err = func(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen); + err = uv__getsockpeername((const uv_handle_t*) handle, + func, + (struct sockaddr*) &sa, + (int*) &addrlen); if (err < 0) { *size = 0; - return UV__ERR(errno); + return err; } #if defined(__linux__) diff --git a/Utilities/cmlibuv/src/unix/posix-poll.c b/Utilities/cmlibuv/src/unix/posix-poll.c index f3181f9..a3b9f21 100644 --- a/Utilities/cmlibuv/src/unix/posix-poll.c +++ b/Utilities/cmlibuv/src/unix/posix-poll.c @@ -298,6 +298,8 @@ update_timeout: void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { size_t i; + assert(fd >= 0); + if (loop->poll_fds_iterating) { /* uv__io_poll is currently iterating. Just invalidate fd. */ for (i = 0; i < loop->poll_fds_used; i++) diff --git a/Utilities/cmlibuv/src/unix/process.c b/Utilities/cmlibuv/src/unix/process.c index e9579f5..f4826bf 100644 --- a/Utilities/cmlibuv/src/unix/process.c +++ b/Utilities/cmlibuv/src/unix/process.c @@ -426,6 +426,11 @@ static void uv__process_child_init(const uv_process_options_t* options, if (n == SIGKILL || n == SIGSTOP) continue; /* Can't be changed. */ +#if defined(__HAIKU__) + if (n == SIGKILLTHR) + continue; /* Can't be changed. */ +#endif + if (SIG_ERR != signal(n, SIG_DFL)) continue; @@ -486,6 +491,8 @@ int uv_spawn(uv_loop_t* loop, UV_PROCESS_SETGID | UV_PROCESS_SETUID | UV_PROCESS_WINDOWS_HIDE | + UV_PROCESS_WINDOWS_HIDE_CONSOLE | + UV_PROCESS_WINDOWS_HIDE_GUI | UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS))); uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS); diff --git a/Utilities/cmlibuv/src/unix/stream.c b/Utilities/cmlibuv/src/unix/stream.c index 4b9123f..8121f64 100644 --- a/Utilities/cmlibuv/src/unix/stream.c +++ b/Utilities/cmlibuv/src/unix/stream.c @@ -745,13 +745,13 @@ static int uv__write_req_update(uv_stream_t* stream, buf = req->bufs + req->write_index; - while (n > 0) { + do { len = n < buf->len ? n : buf->len; buf->base += len; buf->len -= len; buf += (buf->len == 0); /* Advance to next buffer if this one is empty. */ n -= len; - } + } while (n > 0); req->write_index = buf - req->bufs; @@ -897,7 +897,7 @@ start: goto error; } - if (n > 0 && uv__write_req_update(stream, req, n)) { + if (n >= 0 && uv__write_req_update(stream, req, n)) { uv__write_req_finish(req); return; /* TODO(bnoordhuis) Start trying to write the next request. */ } @@ -1541,7 +1541,7 @@ int uv_try_write(uv_stream_t* stream, } if (written == 0 && req_size != 0) - return UV_EAGAIN; + return req.error < 0 ? req.error : UV_EAGAIN; else return written; } diff --git a/Utilities/cmlibuv/src/unix/sunos.c b/Utilities/cmlibuv/src/unix/sunos.c index aac6504..0cd25c1 100644 --- a/Utilities/cmlibuv/src/unix/sunos.c +++ b/Utilities/cmlibuv/src/unix/sunos.c @@ -121,6 +121,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { uintptr_t nfds; assert(loop->watchers != NULL); + assert(fd >= 0); events = (struct port_event*) loop->watchers[loop->nwatchers]; nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; @@ -138,8 +139,10 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) { if (port_associate(loop->backend_fd, PORT_SOURCE_FD, fd, POLLIN, 0)) return UV__ERR(errno); - if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd)) + if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd)) { + perror("(libuv) port_dissociate()"); abort(); + } return 0; } @@ -177,8 +180,14 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { w = QUEUE_DATA(q, uv__io_t, watcher_queue); assert(w->pevents != 0); - if (port_associate(loop->backend_fd, PORT_SOURCE_FD, w->fd, w->pevents, 0)) + if (port_associate(loop->backend_fd, + PORT_SOURCE_FD, + w->fd, + w->pevents, + 0)) { + perror("(libuv) port_associate()"); abort(); + } w->events = w->pevents; } @@ -222,10 +231,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { /* Work around another kernel bug: port_getn() may return events even * on error. */ - if (errno == EINTR || errno == ETIME) + if (errno == EINTR || errno == ETIME) { saved_errno = errno; - else + } else { + perror("(libuv) port_getn()"); abort(); + } } /* Update loop->time unconditionally. It's tempting to skip the update when @@ -373,6 +384,11 @@ uint64_t uv_get_total_memory(void) { } +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + void uv_loadavg(double avg[3]) { (void) getloadavg(avg, 3); } diff --git a/Utilities/cmlibuv/src/unix/tcp.c b/Utilities/cmlibuv/src/unix/tcp.c index 2982851..8cedcd6 100644 --- a/Utilities/cmlibuv/src/unix/tcp.c +++ b/Utilities/cmlibuv/src/unix/tcp.c @@ -82,7 +82,7 @@ static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) { handle->flags |= flags; return 0; } - + /* Query to see if tcp socket is bound. */ slen = sizeof(saddr); memset(&saddr, 0, sizeof(saddr)); @@ -235,12 +235,16 @@ int uv__tcp_connect(uv_connect_t* req, if (r == -1 && errno != 0) { if (errno == EINPROGRESS) ; /* not an error */ - else if (errno == ECONNREFUSED) - /* If we get a ECONNREFUSED wait until the next tick to report the - * error. Solaris wants to report immediately--other unixes want to - * wait. + else if (errno == ECONNREFUSED +#if defined(__OpenBSD__) + || errno == EINVAL +#endif + ) + /* If we get ECONNREFUSED (Solaris) or EINVAL (OpenBSD) wait until the + * next tick to report the error. Solaris and OpenBSD wants to report + * immediately -- other unixes want to wait. */ - handle->delayed_error = UV__ERR(errno); + handle->delayed_error = UV__ERR(ECONNREFUSED); else return UV__ERR(errno); } @@ -279,44 +283,28 @@ int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { int uv_tcp_getsockname(const uv_tcp_t* handle, struct sockaddr* name, int* namelen) { - socklen_t socklen; if (handle->delayed_error) return handle->delayed_error; - if (uv__stream_fd(handle) < 0) - return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */ - - /* sizeof(socklen_t) != sizeof(int) on some systems. */ - socklen = (socklen_t) *namelen; - - if (getsockname(uv__stream_fd(handle), name, &socklen)) - return UV__ERR(errno); - - *namelen = (int) socklen; - return 0; + return uv__getsockpeername((const uv_handle_t*) handle, + getsockname, + name, + namelen); } int uv_tcp_getpeername(const uv_tcp_t* handle, struct sockaddr* name, int* namelen) { - socklen_t socklen; if (handle->delayed_error) return handle->delayed_error; - if (uv__stream_fd(handle) < 0) - return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */ - - /* sizeof(socklen_t) != sizeof(int) on some systems. */ - socklen = (socklen_t) *namelen; - - if (getpeername(uv__stream_fd(handle), name, &socklen)) - return UV__ERR(errno); - - *namelen = (int) socklen; - return 0; + return uv__getsockpeername((const uv_handle_t*) handle, + getpeername, + name, + namelen); } diff --git a/Utilities/cmlibuv/src/unix/thread.c b/Utilities/cmlibuv/src/unix/thread.c index 2900470..cd0b7aa 100644 --- a/Utilities/cmlibuv/src/unix/thread.c +++ b/Utilities/cmlibuv/src/unix/thread.c @@ -48,8 +48,10 @@ STATIC_ASSERT(sizeof(uv_barrier_t) == sizeof(pthread_barrier_t)); #endif -/* Note: guard clauses should match uv_barrier_t's in include/uv/uv-unix.h. */ -#if defined(_AIX) || !defined(PTHREAD_BARRIER_SERIAL_THREAD) +/* Note: guard clauses should match uv_barrier_t's in include/uv/unix.h. */ +#if defined(_AIX) || \ + defined(__OpenBSD__) || \ + !defined(PTHREAD_BARRIER_SERIAL_THREAD) int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { struct _uv_barrier* b; int rc; @@ -176,8 +178,21 @@ static size_t thread_stack_size(void) { if (lim.rlim_cur != RLIM_INFINITY) { /* pthread_attr_setstacksize() expects page-aligned values. */ lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize(); - if (lim.rlim_cur >= PTHREAD_STACK_MIN) - return lim.rlim_cur; + + /* Musl's PTHREAD_STACK_MIN is 2 KB on all architectures, which is + * too small to safely receive signals on. + * + * Musl's PTHREAD_STACK_MIN + MINSIGSTKSZ == 8192 on arm64 (which has + * the largest MINSIGSTKSZ of the architectures that musl supports) so + * let's use that as a lower bound. + * + * We use a hardcoded value because PTHREAD_STACK_MIN + MINSIGSTKSZ + * is between 28 and 133 KB when compiling against glibc, depending + * on the architecture. + */ + if (lim.rlim_cur >= 8192) + if (lim.rlim_cur >= PTHREAD_STACK_MIN) + return lim.rlim_cur; } #endif @@ -192,13 +207,36 @@ static size_t thread_stack_size(void) { int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { + uv_thread_options_t params; + params.flags = UV_THREAD_NO_FLAGS; + return uv_thread_create_ex(tid, ¶ms, entry, arg); +} + +int uv_thread_create_ex(uv_thread_t* tid, + const uv_thread_options_t* params, + void (*entry)(void *arg), + void *arg) { int err; - size_t stack_size; pthread_attr_t* attr; pthread_attr_t attr_storage; + size_t pagesize; + size_t stack_size; + + stack_size = + params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0; attr = NULL; - stack_size = thread_stack_size(); + if (stack_size == 0) { + stack_size = thread_stack_size(); + } else { + pagesize = (size_t)getpagesize(); + /* Round up to the nearest page boundary. */ + stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1); +#ifdef PTHREAD_STACK_MIN + if (stack_size < PTHREAD_STACK_MIN) + stack_size = PTHREAD_STACK_MIN; +#endif + } if (stack_size > 0) { attr = &attr_storage; @@ -778,7 +816,9 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { return UV_ETIMEDOUT; abort(); +#ifndef __SUNPRO_C return UV_EINVAL; /* Satisfy the compiler. */ +#endif } diff --git a/Utilities/cmlibuv/src/unix/udp.c b/Utilities/cmlibuv/src/unix/udp.c index ec337ec..b578e7b 100644 --- a/Utilities/cmlibuv/src/unix/udp.c +++ b/Utilities/cmlibuv/src/unix/udp.c @@ -30,6 +30,7 @@ #if defined(__MVS__) #include <xti.h> #endif +#include <sys/un.h> #if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP) # define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP @@ -227,9 +228,22 @@ static void uv__udp_sendmsg(uv_udp_t* handle) { assert(req != NULL); memset(&h, 0, sizeof h); - h.msg_name = &req->addr; - h.msg_namelen = (req->addr.ss_family == AF_INET6 ? - sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); + if (req->addr.ss_family == AF_UNSPEC) { + h.msg_name = NULL; + h.msg_namelen = 0; + } else { + h.msg_name = &req->addr; + if (req->addr.ss_family == AF_INET6) + h.msg_namelen = sizeof(struct sockaddr_in6); + else if (req->addr.ss_family == AF_INET) + h.msg_namelen = sizeof(struct sockaddr_in); + else if (req->addr.ss_family == AF_UNIX) + h.msg_namelen = sizeof(struct sockaddr_un); + else { + assert(0 && "unsupported address family"); + abort(); + } + } h.msg_iov = (struct iovec*) req->bufs; h.msg_iovlen = req->nbufs; @@ -263,16 +277,30 @@ static void uv__udp_sendmsg(uv_udp_t* handle) { * are different from the BSDs: it _shares_ the port rather than steal it * from the current listener. While useful, it's not something we can emulate * on other platforms so we don't enable it. + * + * zOS does not support getsockname with SO_REUSEPORT option when using + * AF_UNIX. */ static int uv__set_reuse(int fd) { int yes; - -#if defined(SO_REUSEPORT) && !defined(__linux__) yes = 1; + +#if defined(SO_REUSEPORT) && defined(__MVS__) + struct sockaddr_in sockfd; + unsigned int sockfd_len = sizeof(sockfd); + if (getsockname(fd, (struct sockaddr*) &sockfd, &sockfd_len) == -1) + return UV__ERR(errno); + if (sockfd.sin_family == AF_UNIX) { + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes))) + return UV__ERR(errno); + } else { + if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes))) + return UV__ERR(errno); + } +#elif defined(SO_REUSEPORT) && !defined(__linux__) if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes))) return UV__ERR(errno); #else - yes = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes))) return UV__ERR(errno); #endif @@ -383,6 +411,50 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, } +int uv__udp_connect(uv_udp_t* handle, + const struct sockaddr* addr, + unsigned int addrlen) { + int err; + + err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0); + if (err) + return err; + + do { + errno = 0; + err = connect(handle->io_watcher.fd, addr, addrlen); + } while (err == -1 && errno == EINTR); + + if (err) + return UV__ERR(errno); + + handle->flags |= UV_HANDLE_UDP_CONNECTED; + + return 0; +} + + +int uv__udp_disconnect(uv_udp_t* handle) { + int r; + struct sockaddr addr; + + memset(&addr, 0, sizeof(addr)); + + addr.sa_family = AF_UNSPEC; + + do { + errno = 0; + r = connect(handle->io_watcher.fd, &addr, sizeof(addr)); + } while (r == -1 && errno == EINTR); + + if (r == -1 && errno != EAFNOSUPPORT) + return UV__ERR(errno); + + handle->flags &= ~UV_HANDLE_UDP_CONNECTED; + return 0; +} + + int uv__udp_send(uv_udp_send_t* req, uv_udp_t* handle, const uv_buf_t bufs[], @@ -395,9 +467,11 @@ int uv__udp_send(uv_udp_send_t* req, assert(nbufs > 0); - err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0); - if (err) - return err; + if (addr) { + err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0); + if (err) + return err; + } /* It's legal for send_queue_count > 0 even when the write_queue is empty; * it means there are error-state requests in the write_completed_queue that @@ -407,7 +481,10 @@ int uv__udp_send(uv_udp_send_t* req, uv__req_init(handle->loop, req, UV_UDP_SEND); assert(addrlen <= sizeof(req->addr)); - memcpy(&req->addr, addr, addrlen); + if (addr == NULL) + req->addr.ss_family = AF_UNSPEC; + else + memcpy(&req->addr, addr, addrlen); req->send_cb = send_cb; req->handle = handle; req->nbufs = nbufs; @@ -459,9 +536,13 @@ int uv__udp_try_send(uv_udp_t* handle, if (handle->send_queue_count != 0) return UV_EAGAIN; - err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0); - if (err) - return err; + if (addr) { + err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0); + if (err) + return err; + } else { + assert(handle->flags & UV_HANDLE_UDP_CONNECTED); + } memset(&h, 0, sizeof h); h.msg_name = (struct sockaddr*) addr; @@ -608,6 +689,7 @@ int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) { uv__io_init(&handle->io_watcher, uv__udp_io, fd); QUEUE_INIT(&handle->write_queue); QUEUE_INIT(&handle->write_completed_queue); + return 0; } @@ -636,6 +718,9 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { return err; handle->io_watcher.fd = sock; + if (uv__udp_is_connected(handle)) + handle->flags |= UV_HANDLE_UDP_CONNECTED; + return 0; } @@ -743,13 +828,17 @@ int uv_udp_set_ttl(uv_udp_t* handle, int ttl) { IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)); -#endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) || - defined(__MVS__) */ + +#else /* !(defined(__sun) || defined(_AIX) || defined (__OpenBSD__) || + defined(__MVS__)) */ return uv__setsockopt_maybe_char(handle, IP_TTL, IPV6_UNICAST_HOPS, ttl); + +#endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) || + defined(__MVS__) */ } @@ -851,23 +940,24 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) return 0; } - -int uv_udp_getsockname(const uv_udp_t* handle, +int uv_udp_getpeername(const uv_udp_t* handle, struct sockaddr* name, int* namelen) { - socklen_t socklen; - - if (handle->io_watcher.fd == -1) - return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */ - /* sizeof(socklen_t) != sizeof(int) on some systems. */ - socklen = (socklen_t) *namelen; + return uv__getsockpeername((const uv_handle_t*) handle, + getpeername, + name, + namelen); +} - if (getsockname(handle->io_watcher.fd, name, &socklen)) - return UV__ERR(errno); +int uv_udp_getsockname(const uv_udp_t* handle, + struct sockaddr* name, + int* namelen) { - *namelen = (int) socklen; - return 0; + return uv__getsockpeername((const uv_handle_t*) handle, + getsockname, + name, + namelen); } diff --git a/Utilities/cmlibuv/src/uv-common.c b/Utilities/cmlibuv/src/uv-common.c index 907ebf2..f4853d6 100644 --- a/Utilities/cmlibuv/src/uv-common.c +++ b/Utilities/cmlibuv/src/uv-common.c @@ -34,6 +34,7 @@ # include <malloc.h> /* malloc */ #else # include <net/if.h> /* if_nametoindex */ +# include <sys/un.h> /* AF_UNIX, sockaddr_un */ #endif @@ -223,6 +224,9 @@ int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr) { memset(addr, 0, sizeof(*addr)); addr->sin6_family = AF_INET6; addr->sin6_port = htons(port); +#ifdef SIN6_LEN + addr->sin6_len = sizeof(*addr); +#endif zone_index = strchr(ip, '%'); if (zone_index != NULL) { @@ -315,17 +319,20 @@ int uv_tcp_connect(uv_connect_t* req, } -int uv_udp_send(uv_udp_send_t* req, - uv_udp_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - const struct sockaddr* addr, - uv_udp_send_cb send_cb) { +int uv_udp_connect(uv_udp_t* handle, const struct sockaddr* addr) { unsigned int addrlen; if (handle->type != UV_UDP) return UV_EINVAL; + /* Disconnect the handle */ + if (addr == NULL) { + if (!(handle->flags & UV_HANDLE_UDP_CONNECTED)) + return UV_ENOTCONN; + + return uv__udp_disconnect(handle); + } + if (addr->sa_family == AF_INET) addrlen = sizeof(struct sockaddr_in); else if (addr->sa_family == AF_INET6) @@ -333,6 +340,70 @@ int uv_udp_send(uv_udp_send_t* req, else return UV_EINVAL; + if (handle->flags & UV_HANDLE_UDP_CONNECTED) + return UV_EISCONN; + + return uv__udp_connect(handle, addr, addrlen); +} + + +int uv__udp_is_connected(uv_udp_t* handle) { + struct sockaddr_storage addr; + int addrlen; + if (handle->type != UV_UDP) + return 0; + + addrlen = sizeof(addr); + if (uv_udp_getpeername(handle, (struct sockaddr*) &addr, &addrlen) != 0) + return 0; + + return addrlen > 0; +} + + +int uv__udp_check_before_send(uv_udp_t* handle, const struct sockaddr* addr) { + unsigned int addrlen; + + if (handle->type != UV_UDP) + return UV_EINVAL; + + if (addr != NULL && (handle->flags & UV_HANDLE_UDP_CONNECTED)) + return UV_EISCONN; + + if (addr == NULL && !(handle->flags & UV_HANDLE_UDP_CONNECTED)) + return UV_EDESTADDRREQ; + + if (addr != NULL) { + if (addr->sa_family == AF_INET) + addrlen = sizeof(struct sockaddr_in); + else if (addr->sa_family == AF_INET6) + addrlen = sizeof(struct sockaddr_in6); +#if defined(AF_UNIX) && !defined(_WIN32) + else if (addr->sa_family == AF_UNIX) + addrlen = sizeof(struct sockaddr_un); +#endif + else + return UV_EINVAL; + } else { + addrlen = 0; + } + + return addrlen; +} + + +int uv_udp_send(uv_udp_send_t* req, + uv_udp_t* handle, + const uv_buf_t bufs[], + unsigned int nbufs, + const struct sockaddr* addr, + uv_udp_send_cb send_cb) { + int addrlen; + + addrlen = uv__udp_check_before_send(handle, addr); + if (addrlen < 0) + return addrlen; + return uv__udp_send(req, handle, bufs, nbufs, addr, addrlen, send_cb); } @@ -341,17 +412,11 @@ int uv_udp_try_send(uv_udp_t* handle, const uv_buf_t bufs[], unsigned int nbufs, const struct sockaddr* addr) { - unsigned int addrlen; - - if (handle->type != UV_UDP) - return UV_EINVAL; + int addrlen; - if (addr->sa_family == AF_INET) - addrlen = sizeof(struct sockaddr_in); - else if (addr->sa_family == AF_INET6) - addrlen = sizeof(struct sockaddr_in6); - else - return UV_EINVAL; + addrlen = uv__udp_check_before_send(handle, addr); + if (addrlen < 0) + return addrlen; return uv__udp_try_send(handle, bufs, nbufs, addr, addrlen); } @@ -573,37 +638,66 @@ int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) { dent = dents[(*nbufs)++]; ent->name = dent->d_name; + ent->type = uv__fs_get_dirent_type(dent); + + return 0; +} + +uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent) { + uv_dirent_type_t type; + #ifdef HAVE_DIRENT_TYPES switch (dent->d_type) { case UV__DT_DIR: - ent->type = UV_DIRENT_DIR; + type = UV_DIRENT_DIR; break; case UV__DT_FILE: - ent->type = UV_DIRENT_FILE; + type = UV_DIRENT_FILE; break; case UV__DT_LINK: - ent->type = UV_DIRENT_LINK; + type = UV_DIRENT_LINK; break; case UV__DT_FIFO: - ent->type = UV_DIRENT_FIFO; + type = UV_DIRENT_FIFO; break; case UV__DT_SOCKET: - ent->type = UV_DIRENT_SOCKET; + type = UV_DIRENT_SOCKET; break; case UV__DT_CHAR: - ent->type = UV_DIRENT_CHAR; + type = UV_DIRENT_CHAR; break; case UV__DT_BLOCK: - ent->type = UV_DIRENT_BLOCK; + type = UV_DIRENT_BLOCK; break; default: - ent->type = UV_DIRENT_UNKNOWN; + type = UV_DIRENT_UNKNOWN; } #else - ent->type = UV_DIRENT_UNKNOWN; + type = UV_DIRENT_UNKNOWN; #endif - return 0; + return type; +} + +void uv__fs_readdir_cleanup(uv_fs_t* req) { + uv_dir_t* dir; + uv_dirent_t* dirents; + int i; + + if (req->ptr == NULL) + return; + + dir = req->ptr; + dirents = dir->dirents; + req->ptr = NULL; + + if (dirents == NULL) + return; + + for (i = 0; i < req->result; ++i) { + uv__free((char*) dirents[i].name); + dirents[i].name = NULL; + } } diff --git a/Utilities/cmlibuv/src/uv-common.h b/Utilities/cmlibuv/src/uv-common.h index 15ac4d0..f788161 100644 --- a/Utilities/cmlibuv/src/uv-common.h +++ b/Utilities/cmlibuv/src/uv-common.h @@ -103,6 +103,7 @@ enum { /* Only used by uv_udp_t handles. */ UV_HANDLE_UDP_PROCESSING = 0x01000000, + UV_HANDLE_UDP_CONNECTED = 0x02000000, /* Only used by uv_pipe_t handles. */ UV_HANDLE_NON_OVERLAPPED_PIPE = 0x01000000, @@ -142,6 +143,14 @@ int uv__udp_bind(uv_udp_t* handle, unsigned int addrlen, unsigned int flags); +int uv__udp_connect(uv_udp_t* handle, + const struct sockaddr* addr, + unsigned int addrlen); + +int uv__udp_disconnect(uv_udp_t* handle); + +int uv__udp_is_connected(uv_udp_t* handle); + int uv__udp_send(uv_udp_send_t* req, uv_udp_t* handle, const uv_buf_t bufs[], @@ -184,6 +193,8 @@ size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs); int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value); void uv__fs_scandir_cleanup(uv_fs_t* req); +void uv__fs_readdir_cleanup(uv_fs_t* req); +uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent); int uv__next_timeout(const uv_loop_t* loop); void uv__run_timers(uv_loop_t* loop); diff --git a/Utilities/cmlibuv/src/uv-data-getter-setters.c b/Utilities/cmlibuv/src/uv-data-getter-setters.c index b7fcd4a..c302566 100644 --- a/Utilities/cmlibuv/src/uv-data-getter-setters.c +++ b/Utilities/cmlibuv/src/uv-data-getter-setters.c @@ -36,7 +36,7 @@ const char* uv_req_type_name(uv_req_type type) { case UV_REQ_TYPE_MAX: case UV_UNKNOWN_REQ: default: /* UV_REQ_TYPE_PRIVATE */ - return NULL; + break; } return NULL; } diff --git a/Utilities/cmlibuv/src/win/core.c b/Utilities/cmlibuv/src/win/core.c index 58309c6..e9d0a58 100644 --- a/Utilities/cmlibuv/src/win/core.c +++ b/Utilities/cmlibuv/src/win/core.c @@ -627,3 +627,26 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) { int uv_cpumask_size(void) { return (int)(sizeof(DWORD_PTR) * 8); } + +int uv__getsockpeername(const uv_handle_t* handle, + uv__peersockfunc func, + struct sockaddr* name, + int* namelen, + int delayed_error) { + + int result; + uv_os_fd_t fd; + + result = uv_fileno(handle, &fd); + if (result != 0) + return result; + + if (delayed_error) + return uv_translate_sys_error(delayed_error); + + result = func((SOCKET) fd, name, namelen); + if (result != 0) + return uv_translate_sys_error(WSAGetLastError()); + + return 0; +} diff --git a/Utilities/cmlibuv/src/win/fs.c b/Utilities/cmlibuv/src/win/fs.c index 65d936b..9e2f084 100644 --- a/Utilities/cmlibuv/src/win/fs.c +++ b/Utilities/cmlibuv/src/win/fs.c @@ -1125,6 +1125,137 @@ cleanup: uv__free(dirents); } +void fs__opendir(uv_fs_t* req) { + WCHAR* pathw; + size_t len; + const WCHAR* fmt; + WCHAR* find_path; + uv_dir_t* dir; + + pathw = req->file.pathw; + dir = NULL; + find_path = NULL; + + /* Figure out whether path is a file or a directory. */ + if (!(GetFileAttributesW(pathw) & FILE_ATTRIBUTE_DIRECTORY)) { + SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY); + goto error; + } + + dir = uv__malloc(sizeof(*dir)); + if (dir == NULL) { + SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); + goto error; + } + + len = wcslen(pathw); + + if (len == 0) + fmt = L"./*"; + else if (IS_SLASH(pathw[len - 1])) + fmt = L"%s*"; + else + fmt = L"%s\\*"; + + find_path = uv__malloc(sizeof(WCHAR) * (len + 4)); + if (find_path == NULL) { + SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); + goto error; + } + + _snwprintf(find_path, len + 3, fmt, pathw); + dir->dir_handle = FindFirstFileW(find_path, &dir->find_data); + uv__free(find_path); + find_path = NULL; + if (dir->dir_handle == INVALID_HANDLE_VALUE && + GetLastError() != ERROR_FILE_NOT_FOUND) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + goto error; + } + + dir->need_find_call = FALSE; + req->ptr = dir; + SET_REQ_RESULT(req, 0); + return; + +error: + uv__free(dir); + uv__free(find_path); + req->ptr = NULL; +} + +void fs__readdir(uv_fs_t* req) { + uv_dir_t* dir; + uv_dirent_t* dirents; + uv__dirent_t dent; + unsigned int dirent_idx; + PWIN32_FIND_DATAW find_data; + unsigned int i; + int r; + + req->flags |= UV_FS_FREE_PTR; + dir = req->ptr; + dirents = dir->dirents; + memset(dirents, 0, dir->nentries * sizeof(*dir->dirents)); + find_data = &dir->find_data; + dirent_idx = 0; + + while (dirent_idx < dir->nentries) { + if (dir->need_find_call && FindNextFileW(dir->dir_handle, find_data) == 0) { + if (GetLastError() == ERROR_NO_MORE_FILES) + break; + goto error; + } + + /* Skip "." and ".." entries. */ + if (find_data->cFileName[0] == L'.' && + (find_data->cFileName[1] == L'\0' || + (find_data->cFileName[1] == L'.' && + find_data->cFileName[2] == L'\0'))) { + dir->need_find_call = TRUE; + continue; + } + + r = uv__convert_utf16_to_utf8((const WCHAR*) &find_data->cFileName, + -1, + (char**) &dirents[dirent_idx].name); + if (r != 0) + goto error; + + /* Copy file type. */ + if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) + dent.d_type = UV__DT_DIR; + else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) + dent.d_type = UV__DT_LINK; + else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DEVICE) != 0) + dent.d_type = UV__DT_CHAR; + else + dent.d_type = UV__DT_FILE; + + dirents[dirent_idx].type = uv__fs_get_dirent_type(&dent); + dir->need_find_call = TRUE; + ++dirent_idx; + } + + SET_REQ_RESULT(req, dirent_idx); + return; + +error: + SET_REQ_WIN32_ERROR(req, GetLastError()); + for (i = 0; i < dirent_idx; ++i) { + uv__free((char*) dirents[i].name); + dirents[i].name = NULL; + } +} + +void fs__closedir(uv_fs_t* req) { + uv_dir_t* dir; + + dir = req->ptr; + FindClose(dir->dir_handle); + uv__free(req->ptr); + SET_REQ_RESULT(req, 0); +} INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf, int do_lstat) { @@ -2039,6 +2170,9 @@ static void uv__fs_work(struct uv__work* w) { XX(MKDTEMP, mkdtemp) XX(RENAME, rename) XX(SCANDIR, scandir) + XX(READDIR, readdir) + XX(OPENDIR, opendir) + XX(CLOSEDIR, closedir) XX(LINK, link) XX(SYMLINK, symlink) XX(READLINK, readlink) @@ -2080,6 +2214,8 @@ void uv_fs_req_cleanup(uv_fs_t* req) { if (req->flags & UV_FS_FREE_PTR) { if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL) uv__fs_scandir_cleanup(req); + else if (req->fs_type == UV_FS_READDIR) + uv__fs_readdir_cleanup(req); else uv__free(req->ptr); } @@ -2247,6 +2383,45 @@ int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, POST; } +int uv_fs_opendir(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_fs_cb cb) { + int err; + + INIT(UV_FS_OPENDIR); + err = fs__capture_path(req, path, NULL, cb != NULL); + if (err) + return uv_translate_sys_error(err); + POST; +} + +int uv_fs_readdir(uv_loop_t* loop, + uv_fs_t* req, + uv_dir_t* dir, + uv_fs_cb cb) { + INIT(UV_FS_READDIR); + + if (dir == NULL || + dir->dirents == NULL || + dir->dir_handle == INVALID_HANDLE_VALUE) { + return UV_EINVAL; + } + + req->ptr = dir; + POST; +} + +int uv_fs_closedir(uv_loop_t* loop, + uv_fs_t* req, + uv_dir_t* dir, + uv_fs_cb cb) { + INIT(UV_FS_CLOSEDIR); + if (dir == NULL) + return UV_EINVAL; + req->ptr = dir; + POST; +} int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb) { diff --git a/Utilities/cmlibuv/src/win/handle.c b/Utilities/cmlibuv/src/win/handle.c index 9d76c3f..61e4df6 100644 --- a/Utilities/cmlibuv/src/win/handle.c +++ b/Utilities/cmlibuv/src/win/handle.c @@ -139,7 +139,6 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) { case UV_FS_POLL: uv__fs_poll_close((uv_fs_poll_t*) handle); uv__handle_closing(handle); - uv_want_endgame(loop, handle); return; default: diff --git a/Utilities/cmlibuv/src/win/internal.h b/Utilities/cmlibuv/src/win/internal.h index 206ab5f..f7d8ccf 100644 --- a/Utilities/cmlibuv/src/win/internal.h +++ b/Utilities/cmlibuv/src/win/internal.h @@ -276,6 +276,14 @@ int uv__getpwuid_r(uv_passwd_t* pwd); int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8); int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16); +typedef int (WINAPI *uv__peersockfunc)(SOCKET, struct sockaddr*, int*); + +int uv__getsockpeername(const uv_handle_t* handle, + uv__peersockfunc func, + struct sockaddr* name, + int* namelen, + int delayed_error); + /* * Process stdio handles. diff --git a/Utilities/cmlibuv/src/win/tcp.c b/Utilities/cmlibuv/src/win/tcp.c index 3ce5548..f2cb527 100644 --- a/Utilities/cmlibuv/src/win/tcp.c +++ b/Utilities/cmlibuv/src/win/tcp.c @@ -809,44 +809,24 @@ static int uv_tcp_try_connect(uv_connect_t* req, int uv_tcp_getsockname(const uv_tcp_t* handle, struct sockaddr* name, int* namelen) { - int result; - - if (handle->socket == INVALID_SOCKET) { - return UV_EINVAL; - } - - if (handle->delayed_error) { - return uv_translate_sys_error(handle->delayed_error); - } - - result = getsockname(handle->socket, name, namelen); - if (result != 0) { - return uv_translate_sys_error(WSAGetLastError()); - } - return 0; + return uv__getsockpeername((const uv_handle_t*) handle, + getsockname, + name, + namelen, + handle->delayed_error); } int uv_tcp_getpeername(const uv_tcp_t* handle, struct sockaddr* name, int* namelen) { - int result; - - if (handle->socket == INVALID_SOCKET) { - return UV_EINVAL; - } - - if (handle->delayed_error) { - return uv_translate_sys_error(handle->delayed_error); - } - - result = getpeername(handle->socket, name, namelen); - if (result != 0) { - return uv_translate_sys_error(WSAGetLastError()); - } - return 0; + return uv__getsockpeername((const uv_handle_t*) handle, + getpeername, + name, + namelen, + handle->delayed_error); } diff --git a/Utilities/cmlibuv/src/win/thread.c b/Utilities/cmlibuv/src/win/thread.c index fd4b7c9..89c53ad 100644 --- a/Utilities/cmlibuv/src/win/thread.c +++ b/Utilities/cmlibuv/src/win/thread.c @@ -112,9 +112,34 @@ static UINT __stdcall uv__thread_start(void* arg) { int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { + uv_thread_options_t params; + params.flags = UV_THREAD_NO_FLAGS; + return uv_thread_create_ex(tid, ¶ms, entry, arg); +} + +int uv_thread_create_ex(uv_thread_t* tid, + const uv_thread_options_t* params, + void (*entry)(void *arg), + void *arg) { struct thread_ctx* ctx; int err; HANDLE thread; + SYSTEM_INFO sysinfo; + size_t stack_size; + size_t pagesize; + + stack_size = + params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0; + + if (stack_size != 0) { + GetNativeSystemInfo(&sysinfo); + pagesize = (size_t)sysinfo.dwPageSize; + /* Round up to the nearest page boundary. */ + stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1); + + if ((unsigned)stack_size != stack_size) + return UV_EINVAL; + } ctx = uv__malloc(sizeof(*ctx)); if (ctx == NULL) @@ -126,7 +151,7 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { /* Create the thread in suspended state so we have a chance to pass * its own creation handle to it */ thread = (HANDLE) _beginthreadex(NULL, - 0, + (unsigned)stack_size, uv__thread_start, ctx, CREATE_SUSPENDED, diff --git a/Utilities/cmlibuv/src/win/tty.c b/Utilities/cmlibuv/src/win/tty.c index f38e9a8..a98fe26 100644 --- a/Utilities/cmlibuv/src/win/tty.c +++ b/Utilities/cmlibuv/src/win/tty.c @@ -736,8 +736,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, /* Ignore keyup events, unless the left alt key was held and a valid * unicode character was emitted. */ if (!KEV.bKeyDown && - KEV.wVirtualKeyCode != VK_MENU && - KEV.uChar.UnicodeChar != 0) { + (KEV.wVirtualKeyCode != VK_MENU || + KEV.uChar.UnicodeChar == 0)) { continue; } diff --git a/Utilities/cmlibuv/src/win/udp.c b/Utilities/cmlibuv/src/win/udp.c index 37df849..8aeeab3 100644 --- a/Utilities/cmlibuv/src/win/udp.c +++ b/Utilities/cmlibuv/src/win/udp.c @@ -36,22 +36,27 @@ const unsigned int uv_active_udp_streams_threshold = 0; /* A zero-size buffer for use by uv_udp_read */ static char uv_zero_[] = ""; - -int uv_udp_getsockname(const uv_udp_t* handle, +int uv_udp_getpeername(const uv_udp_t* handle, struct sockaddr* name, int* namelen) { - int result; - if (handle->socket == INVALID_SOCKET) { - return UV_EINVAL; - } + return uv__getsockpeername((const uv_handle_t*) handle, + getpeername, + name, + namelen, + 0); +} - result = getsockname(handle->socket, name, namelen); - if (result != 0) { - return uv_translate_sys_error(WSAGetLastError()); - } - return 0; +int uv_udp_getsockname(const uv_udp_t* handle, + struct sockaddr* name, + int* namelen) { + + return uv__getsockpeername((const uv_handle_t*) handle, + getsockname, + name, + namelen, + 0); } @@ -784,6 +789,18 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int value) { } +int uv__udp_is_bound(uv_udp_t* handle) { + struct sockaddr_storage addr; + int addrlen; + + addrlen = sizeof(addr); + if (uv_udp_getsockname(handle, (struct sockaddr*) &addr, &addrlen) != 0) + return 0; + + return addrlen > 0; +} + + int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { WSAPROTOCOL_INFOW protocol_info; int opt_len; @@ -803,7 +820,16 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { handle, sock, protocol_info.iAddressFamily); - return uv_translate_sys_error(err); + if (err) + return uv_translate_sys_error(err); + + if (uv__udp_is_bound(handle)) + handle->flags |= UV_HANDLE_BOUND; + + if (uv__udp_is_connected(handle)) + handle->flags |= UV_HANDLE_UDP_CONNECTED; + + return 0; } @@ -880,6 +906,50 @@ int uv__udp_bind(uv_udp_t* handle, } +int uv__udp_connect(uv_udp_t* handle, + const struct sockaddr* addr, + unsigned int addrlen) { + const struct sockaddr* bind_addr; + int err; + + if (!(handle->flags & UV_HANDLE_BOUND)) { + if (addrlen == sizeof(uv_addr_ip4_any_)) + bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_; + else if (addrlen == sizeof(uv_addr_ip6_any_)) + bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_; + else + return UV_EINVAL; + + err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0); + if (err) + return uv_translate_sys_error(err); + } + + err = connect(handle->socket, addr, addrlen); + if (err) + return uv_translate_sys_error(err); + + handle->flags |= UV_HANDLE_UDP_CONNECTED; + + return 0; +} + + +int uv__udp_disconnect(uv_udp_t* handle) { + int err; + struct sockaddr addr; + + memset(&addr, 0, sizeof(addr)); + + err = connect(handle->socket, &addr, sizeof(addr)); + if (err) + return uv_translate_sys_error(err); + + handle->flags &= ~UV_HANDLE_UDP_CONNECTED; + return 0; +} + + /* This function is an egress point, i.e. it returns libuv errors rather than * system errors. */ @@ -900,6 +970,7 @@ int uv__udp_send(uv_udp_send_t* req, bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_; else return UV_EINVAL; + err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0); if (err) return uv_translate_sys_error(err); @@ -925,9 +996,11 @@ int uv__udp_try_send(uv_udp_t* handle, assert(nbufs > 0); - err = uv__convert_to_localhost_if_unspecified(addr, &converted); - if (err) - return err; + if (addr != NULL) { + err = uv__convert_to_localhost_if_unspecified(addr, &converted); + if (err) + return err; + } /* Already sending a message.*/ if (handle->send_queue_count != 0) diff --git a/Utilities/cmlibuv/src/win/util.c b/Utilities/cmlibuv/src/win/util.c index 9237891..7ca8321 100644 --- a/Utilities/cmlibuv/src/win/util.c +++ b/Utilities/cmlibuv/src/win/util.c @@ -59,13 +59,6 @@ # define UNLEN 256 #endif -/* - Max hostname length. The Windows gethostname() documentation states that 256 - bytes will always be large enough to hold the null-terminated hostname. -*/ -#ifndef MAXHOSTNAMELEN -# define MAXHOSTNAMELEN 256 -#endif /* Maximum environment variable size, including the terminating null */ #define MAX_ENV_VAR_LENGTH 32767 @@ -327,6 +320,11 @@ uint64_t uv_get_total_memory(void) { } +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + uv_pid_t uv_os_getpid(void) { return GetCurrentProcessId(); } @@ -684,12 +682,9 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) { NULL, (BYTE*)&cpu_brand, &cpu_brand_size); - if (err != ERROR_SUCCESS) { - RegCloseKey(processor_key); - goto error; - } - RegCloseKey(processor_key); + if (err != ERROR_SUCCESS) + goto error; cpu_info = &cpu_infos[i]; cpu_info->speed = cpu_speed; @@ -713,9 +708,11 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) { return 0; error: - /* This is safe because the cpu_infos array is zeroed on allocation. */ - for (i = 0; i < cpu_count; i++) - uv__free(cpu_infos[i].model); + if (cpu_infos != NULL) { + /* This is safe because the cpu_infos array is zeroed on allocation. */ + for (i = 0; i < cpu_count; i++) + uv__free(cpu_infos[i].model); + } uv__free(cpu_infos); uv__free(sppi); @@ -1510,7 +1507,7 @@ int uv_os_unsetenv(const char* name) { int uv_os_gethostname(char* buffer, size_t* size) { - char buf[MAXHOSTNAMELEN + 1]; + char buf[UV_MAXHOSTNAMESIZE]; size_t len; if (buffer == NULL || size == NULL || *size == 0) @@ -1634,6 +1631,10 @@ int uv_os_uname(uv_utsname_t* buffer) { https://github.com/gagern/gnulib/blob/master/lib/uname.c */ OSVERSIONINFOW os_info; SYSTEM_INFO system_info; + HKEY registry_key; + WCHAR product_name_w[256]; + DWORD product_name_w_size; + int version_size; int processor_level; int r; @@ -1658,16 +1659,56 @@ int uv_os_uname(uv_utsname_t* buffer) { } /* Populate the version field. */ - if (WideCharToMultiByte(CP_UTF8, - 0, - os_info.szCSDVersion, - -1, - buffer->version, - sizeof(buffer->version), - NULL, - NULL) == 0) { - r = uv_translate_sys_error(GetLastError()); - goto error; + version_size = 0; + r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", + 0, + KEY_QUERY_VALUE, + ®istry_key); + + if (r == ERROR_SUCCESS) { + product_name_w_size = sizeof(product_name_w); + r = RegGetValueW(registry_key, + NULL, + L"ProductName", + RRF_RT_REG_SZ, + NULL, + (PVOID) product_name_w, + &product_name_w_size); + RegCloseKey(registry_key); + + if (r == ERROR_SUCCESS) { + version_size = WideCharToMultiByte(CP_UTF8, + 0, + product_name_w, + -1, + buffer->version, + sizeof(buffer->version), + NULL, + NULL); + if (version_size == 0) { + r = uv_translate_sys_error(GetLastError()); + goto error; + } + } + } + + /* Append service pack information to the version if present. */ + if (os_info.szCSDVersion[0] != L'\0') { + if (version_size > 0) + buffer->version[version_size - 1] = ' '; + + if (WideCharToMultiByte(CP_UTF8, + 0, + os_info.szCSDVersion, + -1, + buffer->version + version_size, + sizeof(buffer->version) - version_size, + NULL, + NULL) == 0) { + r = uv_translate_sys_error(GetLastError()); + goto error; + } } /* Populate the sysname field. */ @@ -1744,3 +1785,20 @@ error: buffer->machine[0] = '\0'; return r; } + +int uv_gettimeofday(uv_timeval64_t* tv) { + /* Based on https://doxygen.postgresql.org/gettimeofday_8c_source.html */ + const uint64_t epoch = (uint64_t) 116444736000000000ULL; + FILETIME file_time; + ULARGE_INTEGER ularge; + + if (tv == NULL) + return UV_EINVAL; + + GetSystemTimeAsFileTime(&file_time); + ularge.LowPart = file_time.dwLowDateTime; + ularge.HighPart = file_time.dwHighDateTime; + tv->tv_sec = (int64_t) ((ularge.QuadPart - epoch) / 10000000L); + tv->tv_usec = (int32_t) (((ularge.QuadPart - epoch) % 10000000L) / 10); + return 0; +} diff --git a/Utilities/cmlibuv/src/win/winsock.c b/Utilities/cmlibuv/src/win/winsock.c index 5e7da2a..5820ba9 100644 --- a/Utilities/cmlibuv/src/win/winsock.c +++ b/Utilities/cmlibuv/src/win/winsock.c @@ -87,12 +87,6 @@ void uv_winsock_init(void) { WSAPROTOCOL_INFOW protocol_info; int opt_len; - /* Initialize winsock */ - errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data); - if (errorno != 0) { - uv_fatal_error(errorno, "WSAStartup"); - } - /* Set implicit binding address used by connectEx */ if (uv_ip4_addr("0.0.0.0", 0, &uv_addr_ip4_any_)) { abort(); @@ -102,6 +96,15 @@ void uv_winsock_init(void) { abort(); } + /* Skip initialization in safe mode without network support */ + if (1 == GetSystemMetrics(SM_CLEANBOOT)) return; + + /* Initialize winsock */ + errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data); + if (errorno != 0) { + uv_fatal_error(errorno, "WSAStartup"); + } + /* Detect non-IFS LSPs */ dummy = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); @@ -261,6 +261,17 @@ CMAKE_CXX_SOURCES="\ cmAddSubDirectoryCommand \ cmAddTestCommand \ cmArgumentParser \ + cmBinUtilsLinker \ + cmBinUtilsLinuxELFGetRuntimeDependenciesTool \ + cmBinUtilsLinuxELFLinker \ + cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool \ + cmBinUtilsMacOSMachOGetRuntimeDependenciesTool \ + cmBinUtilsMacOSMachOLinker \ + cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool \ + cmBinUtilsWindowsPEGetRuntimeDependenciesTool \ + cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool \ + cmBinUtilsWindowsPELinker \ + cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool \ cmBreakCommand \ cmBuildCommand \ cmCMakeMinimumRequired \ @@ -315,6 +326,7 @@ CMAKE_CXX_SOURCES="\ cmFindPathCommand \ cmFindProgramCommand \ cmForEachCommand \ + cmFunctionBlocker \ cmFunctionCommand \ cmFSPermissions \ cmGeneratedFileStream \ @@ -357,6 +369,8 @@ CMAKE_CXX_SOURCES="\ cmInstallTargetGenerator \ cmInstallTargetsCommand \ cmInstalledFile \ + cmLDConfigLDConfigTool \ + cmLDConfigTool \ cmLinkDirectoriesCommand \ cmLinkItem \ cmLinkLineComputer \ @@ -388,12 +402,12 @@ CMAKE_CXX_SOURCES="\ cmPolicies \ cmProcessOutput \ cmProjectCommand \ - cmProperty \ cmPropertyDefinition \ cmPropertyDefinitionMap \ cmPropertyMap \ cmReturnCommand \ cmRulePlaceholderExpander \ + cmRuntimeDependencyArchive \ cmScriptGenerator \ cmSearchPath \ cmSeparateArgumentsCommand \ @@ -409,8 +423,11 @@ CMAKE_CXX_SOURCES="\ cmState \ cmStateDirectory \ cmStateSnapshot \ + cmString \ + cmStringAlgorithms \ cmStringReplaceHelper \ cmStringCommand \ + cmSubcommandTable \ cmSubdirCommand \ cmSystemTools \ cmTarget \ @@ -427,7 +444,6 @@ CMAKE_CXX_SOURCES="\ cmTimestamp \ cmTryCompileCommand \ cmTryRunCommand \ - cmUnexpectedCommand \ cmUnsetCommand \ cmUVHandlePtr \ cmUVProcessChain \ @@ -443,7 +459,9 @@ CMAKE_CXX_SOURCES="\ if ${cmake_system_mingw}; then CMAKE_CXX_SOURCES="${CMAKE_CXX_SOURCES}\ cmGlobalMSYSMakefileGenerator \ - cmGlobalMinGWMakefileGenerator" + cmGlobalMinGWMakefileGenerator \ + cmVSSetupHelper \ + " fi LexerParser_CXX_SOURCES="\ @@ -1110,6 +1128,39 @@ echo ' #error "SunPro <= 5.13 mode not supported due to bug in move semantics." #endif +#if __cplusplus > 201103L +#include <iterator> +int check_cxx14() +{ + int a[] = { 0, 1, 2 }; + auto ai = std::cbegin(a); + + int b[] = { 2, 1, 0 }; + auto bi = std::cend(b); + + return *ai + *(bi - 1); +} +#else +int check_cxx14() +{ + return 0; +} +#endif + +#if __cplusplus >= 201703L +#include <optional> +int check_cxx17() +{ + std::optional<int> oi = 0; + return oi.value(); +} +#else +int check_cxx17() +{ + return 0; +} +#endif + class Class { public: @@ -1120,7 +1171,7 @@ private: int main() { auto const c = std::unique_ptr<Class>(new Class); - std::cout << c->Get() << std::endl; + std::cout << c->Get() << check_cxx14() << check_cxx17() << std::endl; return 0; } ' > "${TMPFILE}.cxx" @@ -1326,9 +1377,14 @@ cmake_report cmConfigure.h${_tmp} "#define CMAKE_BOOTSTRAP_BINARY_DIR \"${CMAKE_ cmake_report cmConfigure.h${_tmp} "#define CMake_DEFAULT_RECURSION_LIMIT 400" cmake_report cmConfigure.h${_tmp} "#define CMAKE_BIN_DIR \"/bootstrap-not-insalled\"" cmake_report cmConfigure.h${_tmp} "#define CMAKE_DATA_DIR \"/bootstrap-not-insalled\"" -cmake_report cmConfigure.h${_tmp} "#define CMAKE_BOOTSTRAP" cmake_report cmConfigure.h${_tmp} "#define CM_FALLTHROUGH" +if ${cmake_system_mingw}; then + cmake_report cmConfigure.h${_tmp} "#if defined(_WIN32) && !defined(NOMINMAX)" + cmake_report cmConfigure.h${_tmp} "# define NOMINMAX" + cmake_report cmConfigure.h${_tmp} "#endif" +fi + # Regenerate configured headers for h in Configure VersionConfig; do if "${_diff}" cm${h}.h cm${h}.h${_tmp} > /dev/null 2> /dev/null; then @@ -1370,9 +1426,8 @@ libs="" uv_c_flags="" if ${cmake_system_mingw}; then uv_c_flags="${uv_c_flags} -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600" - libs="${libs} -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv" + libs="${libs} -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv -lole32 -loleaut32" else - uv_c_flags="${uv_c_flags} -DCMAKE_BOOTSTRAP" case "${cmake_system}" in *AIX*) uv_c_flags="${uv_c_flags} -D_ALL_SOURCE -D_XOPEN_SOURCE=500 -D_LINUX_SOURCE_COMPAT" @@ -1433,11 +1488,13 @@ cmake_cxx_flags_SystemTools=" -DKWSYS_CXX_HAS_UTIMES=${KWSYS_CXX_HAS_UTIMES} " cmake_c_flags="${cmake_c_flags} \ + -DCMAKE_BOOTSTRAP \ -I`cmake_escape \"${cmake_bootstrap_dir}\"` \ -I`cmake_escape \"${cmake_source_dir}/Source\"` \ -I`cmake_escape \"${cmake_source_dir}/Source/LexerParser\"` \ -I`cmake_escape \"${cmake_source_dir}/Utilities\"`" cmake_cxx_flags="${cmake_cxx_flags} \ + -DCMAKE_BOOTSTRAP \ -I`cmake_escape \"${cmake_bootstrap_dir}\"` \ -I`cmake_escape \"${cmake_source_dir}/Source\"` \ -I`cmake_escape \"${cmake_source_dir}/Source/LexerParser\"` \ |