diff options
158 files changed, 2032 insertions, 570 deletions
diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index 69d6e9a..9279748 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -68,6 +68,9 @@ The options are: order-only dependencies to ensure the byproducts will be available before their dependents build. + The :ref:`Makefile Generators` will remove ``BYPRODUCTS`` and other + :prop_sf:`GENERATED` files during ``make clean``. + ``COMMAND`` Specify the command-line(s) to execute at build time. If more than one ``COMMAND`` is specified they will be executed in order, diff --git a/Help/command/add_custom_target.rst b/Help/command/add_custom_target.rst index 2d5f5f0..56ab414 100644 --- a/Help/command/add_custom_target.rst +++ b/Help/command/add_custom_target.rst @@ -49,6 +49,9 @@ The options are: order-only dependencies to ensure the byproducts will be available before their dependents build. + The :ref:`Makefile Generators` will remove ``BYPRODUCTS`` and other + :prop_sf:`GENERATED` files during ``make clean``. + ``COMMAND`` Specify the command-line(s) to execute at build time. If more than one ``COMMAND`` is specified they will be executed in order, diff --git a/Help/command/file.rst b/Help/command/file.rst index 5a479d9..92cb2ed 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -42,6 +42,10 @@ Synopsis `Locking`_ file(`LOCK`_ <path> [...]) + `Archiving`_ + file(`ARCHIVE_CREATE`_ OUTPUT <archive> FILES <files> [...]) + file(`ARCHIVE_EXTRACT`_ INPUT <archive> DESTINATION <dir> [...]) + Reading ^^^^^^^ @@ -888,3 +892,62 @@ child directory or file. Trying to lock file twice is not allowed. Any intermediate directories and file itself will be created if they not exist. ``GUARD`` and ``TIMEOUT`` options ignored on ``RELEASE`` operation. + +Archiving +^^^^^^^^^ + +.. _ARCHIVE_CREATE: + +.. code-block:: cmake + + file(ARCHIVE_CREATE OUTPUT <archive> + [FILES <files>] + [DIRECTORY <dirs>] + [FORMAT <format>] + [TYPE <type>] + [MTIME <mtime>] + [VERBOSE]) + +Creates an archive specifed by ``OUTPUT`` with the content of ``FILES`` and +``DIRECTORY``. + +To specify the format of the archive set the ``FORMAT`` option. +Supported formats are: ``7zip``, ``gnutar``, ``pax``, ``paxr``, ``raw``, +(restricted pax, default), and ``zip``. + +To specify the type of compression set the ``TYPE`` option. +Supported compression types are: ``None``, ``BZip2``, ``GZip``, ``XZ``, +and ``Zstd``. + +.. note:: + With ``FORMAT`` set to ``raw`` only one file will be compressed with the + compression type specified by ``TYPE``. + +With ``VERBOSE`` the command will produce verbose output. + +To specify the modification time recorded in tarball entries use +the ``MTIME`` option. + +.. _ARCHIVE_EXTRACT: + +.. code-block:: cmake + + file(ARCHIVE_EXTRACT INPUT <archive> + [FILES <files>] + [DIRECTORY <dirs>] + [DESTINATION <dir>] + [LIST_ONLY] + [VERBOSE]) + +Extracts or lists the content of an archive specified by ``INPUT``. + +The directory where the content of the archive will be extracted can +be specified via ``DESTINATION``. If the directory does not exit, it +will be created. + +To select which files and directories will be extracted or listed +use ``FILES`` and ``DIRECTORY`` options. + +``LIST_ONLY`` will only list the files in the archive. + +With ``VERBOSE`` the command will produce verbose output. diff --git a/Help/dev/source.rst b/Help/dev/source.rst index 0f7488b..5371353 100644 --- a/Help/dev/source.rst +++ b/Help/dev/source.rst @@ -23,12 +23,142 @@ format only a subset of files, such as those that are locally modified. C++ Subset Permitted ==================== -CMake requires compiling as C++11 or above. However, in order to support -building on older toolchains some constructs need to be handled with care: +CMake requires compiling as C++11 in order to support building on older +toolchains. However, to facilitate development, some standard library +features from more recent C++ standards are supported through a compatibility +layer. These features are defined under the namespace ``cm`` and headers +are accessible under the ``cm/`` directory. The headers under ``cm/`` can +be used in place of the standard ones when extended features are needed. +For example ``<cm/memory>`` can be used in place of ``<memory>``. -* Do not use ``std::auto_ptr``. +Available features are: - The ``std::auto_ptr`` template is deprecated in C++11. Use ``std::unique_ptr``. +* From ``C++14``: + + * ``<cm/iterator>``: + ``cm::make_reverse_iterator``, ``cm::cbegin``, ``cm::cend``, + ``cm::rbegin``, ``cm::rend``, ``cm::crbegin``, ``cm::crend`` + + * ``<cm/memory>``: + ``cm::make_unique`` + + * ``<cm/shared_mutex>``: + ``cm::shared_lock`` + + * ``<cm/type_traits>``: + ``cm::enable_if_t`` + +* From ``C++17``: + + * ``<cm/algorithm>``: + ``cm::clamp`` + + * ``<cm/iterator>``: + ``cm::size``, ``cm::empty``, ``cm::data`` + + * ``<cm/optional>``: + ``cm::nullopt_t``, ``cm::nullopt``, ``cm::optional``, + ``cm::make_optional``, ``cm::bad_optional_access`` + + * ``<cm/shared_mutex>``: + ``cm::shared_mutex`` + + * ``<cm/string_view>``: + ``cm::string_view`` + + * ``<cm/type_traits>``: + ``cm::bool_constant``, ``cm::invoke_result_t``, ``cm::invoke_result``, + ``cm::void_t`` + + * ``<cm/utility>``: + ``cm::in_place_t``, ``cm::in_place`` + +* From ``C++20``: + + * ``<cm/deque>``: + ``cm::erase``, ``cm::erase_if`` + + * ``<cm/list>``: + ``cm::erase``, ``cm::erase_if`` + + * ``<cm/map>`` : + ``cm::erase_if`` + + * ``<cm/set>`` : + ``cm::erase_if`` + + * ``<cm/string>``: + ``cm::erase``, ``cm::erase_if`` + + * ``<cm/unordered_map>``: + ``cm::erase_if`` + + * ``<cm/unordered_set>``: + ``cm::erase_if`` + + * ``<cm/vector>``: + ``cm::erase``, ``cm::erase_if`` + +Additionally, some useful non-standard extensions to the C++ standard library +are available in headers under the directory ``cmext/`` in namespace ``cm``. +These are: + +* ``<cmext/algorithm>``: + + * ``cm::append``: + Append elements to a sequential container. + +* ``<cmext/iterator>``: + + * ``cm::is_terator``: + Checks if a type is an iterator type. + + * ``cm::is_input_iterator``: + Checks if a type is an input iterator type. + + * ``cm::is_range``: + Checks if a type is a range type: must have methods ``begin()`` and + ``end()`` returning an iterator. + + * ``cm::is_input_range``: + Checks if a type is an input range type: must have methods ``begin()`` and + ``end()`` returning an input iterator. + +* ``<cmext/memory>``: + + * ``cm::static_reference_cast``: + Apply a ``static_cast`` to a smart pointer. + + * ``cm::dynamic_reference_cast``: + Apply a ``dynamic_cast`` to a smart pointer. + +* ``<cmext/type_traits>``: + + * ``cm::is_container``: + Checks if a type is a container type. + + * ``cm::is_associative_container``: + Checks if a type is an associative container type. + + * ``cm::is_unordered_associative_container``: + Checks if a type is an unordered associative container type. + + * ``cm::is_sequence_container``: + Checks if a type is a sequence container type. + + * ``cm::is_unique_ptr``: + Checks if a type is a ``std::unique_ptr`` type. + +Dynamic Memory Management +========================= + +To ensure efficient memory management, i.e. no memory leaks, it is required +to use smart pointers. Any dynamic memory allocation must be handled by a +smart pointer such as ``std::unique_ptr`` or ``std::shared_ptr``. + +It is allowed to pass raw pointers between objects to enable objects sharing. +A raw pointer **must** not be deleted. Only the object(s) owning the smart +pointer are allowed to delete dynamically allocated memory. Source Tree Layout ================== @@ -69,6 +199,12 @@ The CMake source tree is organized as follows. * ``Utilities/``: Scripts, third-party source code. + * ``Utilities/std/cm``: + Support files for various C++ standards. + + * ``Utilities/std/cmext``: + Extensions to the C++ STL. + * ``Utilities/Sphinx/``: Sphinx configuration to build CMake user documentation. diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 15f0cfc..e552377 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -286,6 +286,8 @@ Properties on Targets /prop_tgt/LINK_WHAT_YOU_USE /prop_tgt/LOCATION_CONFIG /prop_tgt/LOCATION + /prop_tgt/MACHO_COMPATIBILITY_VERSION + /prop_tgt/MACHO_CURRENT_VERSION /prop_tgt/MACOSX_BUNDLE_INFO_PLIST /prop_tgt/MACOSX_BUNDLE /prop_tgt/MACOSX_FRAMEWORK_INFO_PLIST @@ -304,8 +306,6 @@ Properties on Targets /prop_tgt/OBJCXX_STANDARD_REQUIRED /prop_tgt/OSX_ARCHITECTURES_CONFIG /prop_tgt/OSX_ARCHITECTURES - /prop_tgt/OSX_CURRENT_VERSION - /prop_tgt/OSX_COMPATIBILITY_VERSION /prop_tgt/OUTPUT_NAME_CONFIG /prop_tgt/OUTPUT_NAME /prop_tgt/PDB_NAME_CONFIG @@ -391,7 +391,6 @@ Properties on Targets /prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER /prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN /prop_tgt/XCODE_SCHEME_ARGUMENTS - /prop_tgt/XCODE_SCHEME_WORKING_DIRECTORY /prop_tgt/XCODE_SCHEME_DEBUG_AS_ROOT /prop_tgt/XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING /prop_tgt/XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER @@ -408,6 +407,7 @@ Properties on Targets /prop_tgt/XCODE_SCHEME_THREAD_SANITIZER_STOP /prop_tgt/XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER /prop_tgt/XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP + /prop_tgt/XCODE_SCHEME_WORKING_DIRECTORY /prop_tgt/XCODE_SCHEME_ZOMBIE_OBJECTS /prop_tgt/XCTEST diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 7696fd9..c271024 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -247,7 +247,6 @@ Variables that Change Behavior /variable/CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY /variable/CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER /variable/CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN - /variable/CMAKE_XCODE_SCHEME_WORKING_DIRECTORY /variable/CMAKE_XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING /variable/CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER /variable/CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS @@ -262,6 +261,7 @@ Variables that Change Behavior /variable/CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP /variable/CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER /variable/CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP + /variable/CMAKE_XCODE_SCHEME_WORKING_DIRECTORY /variable/CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS /variable/PackageName_ROOT diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index 44b1f2f..429cba4 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -356,6 +356,20 @@ Options in :variable:`CMAKE_SOURCE_DIR` and :variable:`CMAKE_BINARY_DIR`. This flag tells CMake to warn about other files as well. +``--profiling-output=<path>`` + Used in conjuction with ``--profiling-format`` to output to a given path. + +``--profiling-format=<file>`` + Enable the output of profiling data of CMake script in the given format. + + This can aid performance analysis of CMake scripts executed. Third party + applications should be used to process the output into human readable format. + + Currently supported values are: + ``google-trace`` Outputs in Google Trace Format, which can be parsed by the + about:tracing tab of Google Chrome or using a plugin for a tool like Trace + Compass. + .. _`Build Tool Mode`: Build a Project diff --git a/Help/prop_sf/GENERATED.rst b/Help/prop_sf/GENERATED.rst index d430ee2..48ff70c 100644 --- a/Help/prop_sf/GENERATED.rst +++ b/Help/prop_sf/GENERATED.rst @@ -4,16 +4,29 @@ GENERATED Is this source file generated as part of the build or CMake process. Tells the internal CMake engine that a source file is generated by an outside -process such as another build step, or the execution of CMake itself. This -information is then used to exempt the file from any existence or validity -checks. Generated files are created by the execution of commands such as -:command:`add_custom_command` and :command:`file(GENERATE)`. - -When a generated file created by an :command:`add_custom_command` command -is explicitly listed as a source file for any target in the same -directory scope (which usually means the same ``CMakeLists.txt`` file), -CMake will automatically create a dependency to make sure the file is -generated before building that target. +process such as another build step, or the execution of CMake itself. +This information is then used to exempt the file from any existence or +validity checks. + +Any file that is + +- created by the execution of commands such as + :command:`add_custom_command` and :command:`file(GENERATE)` +- listed as one of the ``BYPRODUCTS`` of an :command:`add_custom_command` + or :command:`add_custom_target` command, or +- created by a CMake ``AUTOGEN`` operation such as :prop_tgt:`AUTOMOC`, + :prop_tgt:`AUTORCC`, or :prop_tgt:`AUTOUIC` + +will be marked with the ``GENERATED`` property. + +When a generated file created as the ``OUTPUT`` of an +:command:`add_custom_command` command is explicitly listed as a source file +for any target in the same directory scope (which usually means the same +``CMakeLists.txt`` file), CMake will automatically create a dependency to +make sure the file is generated before building that target. + +The :ref:`Makefile Generators` will remove ``GENERATED`` files during +``make clean``. Generated sources may be hidden in some IDE tools, while in others they might be shown. For the special case of sources generated by CMake's :prop_tgt:`AUTOMOC` diff --git a/Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst b/Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst index d5c5e14..92b52a3 100644 --- a/Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst +++ b/Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst @@ -33,4 +33,4 @@ If :prop_tgt:`AUTOMOC` or :prop_tgt:`AUTOUIC` depends on a file that is either :prop_sf:`SKIP_AUTOUIC`, :prop_sf:`SKIP_AUTOGEN` or :policy:`CMP0071` or - a file that isn't in the origin target's sources -it must added to :prop_tgt:`AUTOGEN_TARGET_DEPENDS`. +it must be added to :prop_tgt:`AUTOGEN_TARGET_DEPENDS`. diff --git a/Help/prop_tgt/MACHO_COMPATIBILITY_VERSION.rst b/Help/prop_tgt/MACHO_COMPATIBILITY_VERSION.rst new file mode 100644 index 0000000..f3fedba --- /dev/null +++ b/Help/prop_tgt/MACHO_COMPATIBILITY_VERSION.rst @@ -0,0 +1,14 @@ +MACHO_COMPATIBILITY_VERSION +--------------------------- + +What compatibility version number is this target for Mach-O binaries. + +For shared libraries on Mach-O systems (e.g. macOS, iOS) +the ``MACHO_COMPATIBILITY_VERSION`` property correspond to +``compatibility version`` and :prop_tgt:`MACHO_CURRENT_VERSION` to +``current version``. +See the :prop_tgt:`FRAMEWORK` target property for an example. + +Versions of Mach-O binaries may be checked with the ``otool -L <binary>`` +command. If ``MACHO_COMPATIBILITY_VERSION`` is not set, the value of +the :prop_tgt:`SOVERSION` property will be used. diff --git a/Help/prop_tgt/MACHO_CURRENT_VERSION.rst b/Help/prop_tgt/MACHO_CURRENT_VERSION.rst new file mode 100644 index 0000000..4a1d3f0 --- /dev/null +++ b/Help/prop_tgt/MACHO_CURRENT_VERSION.rst @@ -0,0 +1,13 @@ +MACHO_CURRENT_VERSION +--------------------- + +What current version number is this target for Mach-O binaries. + +For shared libraries on Mach-O systems (e.g. macOS, iOS) +the :prop_tgt:`MACHO_COMPATIBILITY_VERSION` property correspond to +``compatibility version`` and ``MACHO_CURRENT_VERSION`` to ``current version``. +See the :prop_tgt:`FRAMEWORK` target property for an example. + +Versions of Mach-O binaries may be checked with the ``otool -L <binary>`` +command. If ``MACHO_CURRENT_VERSION`` is not set, the value of +the :prop_tgt:`VERSION` property will be used. diff --git a/Help/prop_tgt/OSX_COMPATIBILITY_VERSION.rst b/Help/prop_tgt/OSX_COMPATIBILITY_VERSION.rst deleted file mode 100644 index 5432b9a7..0000000 --- a/Help/prop_tgt/OSX_COMPATIBILITY_VERSION.rst +++ /dev/null @@ -1,14 +0,0 @@ -OSX_COMPATIBILITY_VERSION -------------------------- - -What compatibility version number is this target for OSX. - -For shared libraries on Mach-O systems (e.g. macOS, iOS) -the ``OSX_COMPATIBILITY_VERSION`` property correspond to -``compatibility version`` and :prop_tgt:`OSX_CURRENT_VERSION` to -``current version``. -See the :prop_tgt:`FRAMEWORK` target property for an example. - -Versions of Mach-O binaries may be checked with the ``otool -L <binary>`` -command. If ``OSX_COMPATIBILITY_VERSION`` is not set, the value of -the :prop_tgt:``SOVERSION`` property will be used. diff --git a/Help/prop_tgt/OSX_CURRENT_VERSION.rst b/Help/prop_tgt/OSX_CURRENT_VERSION.rst deleted file mode 100644 index 609924d..0000000 --- a/Help/prop_tgt/OSX_CURRENT_VERSION.rst +++ /dev/null @@ -1,13 +0,0 @@ -OSX_CURRENT_VERSION -------------------- - -What current version number is this target for OSX. - -For shared libraries on Mach-O systems (e.g. macOS, iOS) -the :prop_tgt:`OSX_COMPATIBILITY_VERSION` property correspond to -``compatibility version`` and ``OSX_CURRENT_VERSION`` to ``current version``. -See the :prop_tgt:`FRAMEWORK` target property for an example. - -Versions of Mach-O binaries may be checked with the ``otool -L <binary>`` -command. If ``OSX_CURRENT_VERSION`` is not set, the value of -the :prop_tgt:``VERSION`` property will be used. diff --git a/Help/prop_tgt/SOVERSION.rst b/Help/prop_tgt/SOVERSION.rst index 1a66c8f..d6f8a94 100644 --- a/Help/prop_tgt/SOVERSION.rst +++ b/Help/prop_tgt/SOVERSION.rst @@ -22,8 +22,8 @@ Mach-O Versions For shared libraries and executables on Mach-O systems (e.g. macOS, iOS), the ``SOVERSION`` property is a fallback to -:prop_tgt:`OSX_COMPATIBILITY_VERSION` property which corresponds to +:prop_tgt:`MACHO_COMPATIBILITY_VERSION` property which corresponds to *compatiblity version* and :prop_tgt:`VERSION` is a fallback to -:prop_tgt:`OSX_CURRENT_VERSION` which corresponds to *current version*. +:prop_tgt:`MACHO_CURRENT_VERSION` which corresponds to *current version*. See the :prop_tgt:`FRAMEWORK` target property for an example. Versions of Mach-O binaries may be checked with the ``otool -L <binary>`` command. diff --git a/Help/prop_tgt/VERSION.rst b/Help/prop_tgt/VERSION.rst index a24b613..f592f4a 100644 --- a/Help/prop_tgt/VERSION.rst +++ b/Help/prop_tgt/VERSION.rst @@ -23,9 +23,9 @@ Mach-O Versions ^^^^^^^^^^^^^^^ For shared libraries and executables on Mach-O systems (e.g. macOS, iOS), -the ``VERSION`` property is a fallback to :prop_tgt:`OSX_CURRENT_VERSION` +the ``VERSION`` property is a fallback to :prop_tgt:`MACHO_CURRENT_VERSION` property which corresponds to *current version* and :prop_tgt:`SOVERSION` -is a fallback to :prop_tgt:`OSX_COMPATIBILITY_VERSION` which corresponds +is a fallback to :prop_tgt:`MACHO_COMPATIBILITY_VERSION` which corresponds to *compatiblity version*. See the :prop_tgt:`FRAMEWORK` target property for an example. Versions of Mach-O binaries may be checked with the ``otool -L <binary>`` command. diff --git a/Help/release/3.17.rst b/Help/release/3.17.rst index 23dec84..c2cfdf0 100644 --- a/Help/release/3.17.rst +++ b/Help/release/3.17.rst @@ -47,12 +47,12 @@ Command-Line ------------ * :manual:`cmake(1)` gained a ``--debug-find`` command-line option to - enable additional human-readable output on where find commands search. + enable additional human-readable output on where ``find_*`` commands search. * :manual:`cmake(1)` gained a ``--trace-format`` command-line option that can be used to set the ``--trace`` output format. Currently, the old human readable and the new JSON format are supported. The new JSON format - is easier to parse automatically, than the existing format. + is easier to parse automatically than the existing format. * :manual:`cmake(1)` gained a ``-E rm`` command-line tool that can be used to remove directories and files. This supersedes the existing @@ -65,7 +65,7 @@ Commands ``DEPENDS`` arguments that are specified relative to the current binary directory. -* The :command:`foreach` learned a new option ``ZIP_LISTS`` to iterate +* The :command:`foreach` command learned a new ``ZIP_LISTS`` option to iterate over multiple lists simultaneously. * The :command:`load_cache(READ_WITH_PREFIX)` command mode is now allowed @@ -79,7 +79,7 @@ Commands * The :command:`message` command gained new keywords ``CHECK_START``, ``CHECK_PASS`` and ``CHECK_FAIL``. -* :command:`target_compile_options` command now honors the ``BEFORE`` +* The :command:`target_compile_options` command now honors the ``BEFORE`` keyword more consistently. See policy :policy:`CMP0101`. Variables @@ -102,7 +102,7 @@ Variables use CUDA. * The :variable:`CMAKE_FIND_DEBUG_MODE` variable was introduced to - print extra find call information during the cmake run to standard + print extra ``find_*`` call information during the cmake run to standard error. Output is designed for human consumption and not for parsing. * The :variable:`CMAKE_EXPORT_COMPILE_COMMANDS` variable now takes its @@ -117,17 +117,20 @@ Variables to persist a log level between CMake runs, unlike the ``--log-level`` command line option which only applies to that particular run. -* The :variable:`CMAKE_XCODE_SCHEME_ENVIRONMENT` variable and - :prop_tgt:`XCODE_SCHEME_ENVIRONMENT` target property were added to - tell the :generator:`Xcode` generator to set the value of the - ``Custom Working Directory`` schema option. +* The :variable:`CMAKE_XCODE_SCHEME_ENVIRONMENT` variable was added + to initialize the :prop_tgt:`XCODE_SCHEME_ENVIRONMENT` target property. + +* The :variable:`CMAKE_XCODE_SCHEME_WORKING_DIRECTORY` variable and + associated :prop_tgt:`XCODE_SCHEME_WORKING_DIRECTORY` target property + were added to tell the :generator:`Xcode` generator to set the value of + the ``Custom Working Directory`` schema option. Properties ---------- * The :prop_tgt:`AIX_EXPORT_ALL_SYMBOLS` target property and associated :variable:`CMAKE_AIX_EXPORT_ALL_SYMBOLS` variable were created to - optionally explicitly disbale automatic export of symbols from shared + optionally explicitly disable automatic export of symbols from shared libraries on AIX. * The :prop_tgt:`DEPRECATION` target property was added to mark @@ -140,10 +143,10 @@ Properties In particular, the ``$<INSTALL_PREFIX>`` generator expression can be used to set the directory relative to the install-time prefix. -* Target properties :prop_tgt:`OSX_COMPATIBILITY_VERSION` and - :prop_tgt:`OSX_CURRENT_VERSION` were added to set the - ``compatibility_version`` and ``curent_version`` respectively - on macOS. For backwards compatibility, if these properties +* Target properties :prop_tgt:`MACHO_COMPATIBILITY_VERSION` and + :prop_tgt:`MACHO_CURRENT_VERSION` were added to set the + ``compatibility_version`` and ``curent_version``, respectively, + for Mach-O binaries. For backwards compatibility, if these properties are not set, :prop_tgt:`SOVERSION` and :prop_tgt:`VERSION` are used respectively as fallbacks. @@ -180,11 +183,11 @@ Modules * The :module:`FindPython3` and :module:`FindPython` modules gained, respectively, variable ``Python3_SOABI`` and ``Python_SOABI`` giving the standard extension suffix for modules. Moreover, commands - ``Python3_add_library`` and ``Python_add_library`` gained the option + ``Python3_add_library()`` and ``Python_add_library()`` gained the option ``WITH_SOABI`` to prefix the library suffix with the value of ``SOABI``. * The :module:`FindLibXml2` module now provides an imported target for the - ``xmllint`` executable + ``xmllint`` executable. Autogen ------- @@ -198,7 +201,7 @@ CTest * The :variable:`CTEST_CONFIGURATION_TYPE` variable is now set from the command line when :manual:`ctest(1)` is invoked with ``-C <cfg>``. -* The :manual:`ctest(1)` gained support for Dr. Memory to run +* The :manual:`ctest(1)` tool gained support for Dr. Memory to run memcheck runs. * The :manual:`ctest(1)` tool gained a ``--no-tests=<[error|ignore]>`` option @@ -246,9 +249,9 @@ CPack :variable:`CPACK_NSIS_FINISH_TITLE_3LINES`. These can be used to specify the finish page title and display it in 3 lines. -* The :cpack_gen:`CPack productbuild Generator` gained option - :variable:`CPACK_PRODUCTBUILD_BACKGROUND` to specify a background image - for the macOS installer. +* The :cpack_gen:`CPack productbuild Generator` gained support for a + :variable:`CPACK_PRODUCTBUILD_BACKGROUND` variable to specify a background + image for the macOS installer. Other ----- @@ -293,7 +296,7 @@ Other Changes See policy :policy:`CMP0099`. * When using MinGW tools, the :command:`find_library` command no longer - finds ``.dll`` files by default. Instead it expects ``.dll.a`` import + finds ``.dll`` files by default. Instead, it expects ``.dll.a`` import libraries to be available. * The :generator:`MinGW Makefiles` generator no longer issues an error if diff --git a/Help/release/dev/FindRuby-variable-case.rst b/Help/release/dev/FindRuby-variable-case.rst new file mode 100644 index 0000000..bd4a2f1 --- /dev/null +++ b/Help/release/dev/FindRuby-variable-case.rst @@ -0,0 +1,7 @@ +FindRuby-variable-case +---------------------- + +* The :module:`FindRuby` module input and output variables were all renamed + from ``RUBY_`` to ``Ruby_`` for consistency with other find modules. + Input variables of the old case will be honored if provided, and output + variables of the old case are always provided. diff --git a/Help/release/dev/GoogleTest-XML_OUTPUT_DIR.rst b/Help/release/dev/GoogleTest-XML_OUTPUT_DIR.rst new file mode 100644 index 0000000..ee29e60 --- /dev/null +++ b/Help/release/dev/GoogleTest-XML_OUTPUT_DIR.rst @@ -0,0 +1,6 @@ +GoogleTest-XML_OUTPUT_DIR +------------------------- + +* The :module:`GoogleTest` module ``gtest_discover_test`` command + gained a new optional parameter ``XML_OUTPUT_DIR``. When set the JUnit XML + test results are stored in that directory. diff --git a/Help/release/dev/file_archive.rst b/Help/release/dev/file_archive.rst new file mode 100644 index 0000000..e79529c --- /dev/null +++ b/Help/release/dev/file_archive.rst @@ -0,0 +1,7 @@ +file_archive +------------ + +* The :command:`file` command gained the ``ARCHIVE_{CREATE|EXTRACT}`` subcommands. + + These subcommands will replicate the :manual:`cmake(1)` ``-E tar`` functionality in + CMake scripting code. diff --git a/Help/release/dev/profiling.rst b/Help/release/dev/profiling.rst new file mode 100644 index 0000000..ab180f0 --- /dev/null +++ b/Help/release/dev/profiling.rst @@ -0,0 +1,9 @@ +cmake-profiling +--------------- + +* Add support for profiling of CMake scripts through the parameters + ``--profiling-output`` and ``--profiling-format``. These options can + be used by users to gain insight into the performance of their scripts. + + The first supported output format is ``google-trace`` which is a format + supported by Google Chrome's ``about:tracing`` tab. diff --git a/Modules/CMakeASMCompiler.cmake.in b/Modules/CMakeASMCompiler.cmake.in index b8e09fe..858c053 100644 --- a/Modules/CMakeASMCompiler.cmake.in +++ b/Modules/CMakeASMCompiler.cmake.in @@ -10,6 +10,7 @@ set(CMAKE_ASM@ASM_DIALECT@_COMPILER_LOADED 1) set(CMAKE_ASM@ASM_DIALECT@_COMPILER_ID "@_CMAKE_ASM_COMPILER_ID@") set(CMAKE_ASM@ASM_DIALECT@_COMPILER_VERSION "@_CMAKE_ASM_COMPILER_VERSION@") set(CMAKE_ASM@ASM_DIALECT@_COMPILER_ENV_VAR "@_CMAKE_ASM_COMPILER_ENV_VAR@") +@_SET_CMAKE_ASM_COMPILER_ID_VENDOR_MATCH@ @_SET_CMAKE_ASM_COMPILER_ARCHITECTURE_ID@ set(CMAKE_ASM@ASM_DIALECT@_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake index 974f5fa..f31713e 100644 --- a/Modules/CMakeCUDAInformation.cmake +++ b/Modules/CMakeCUDAInformation.cmake @@ -138,24 +138,24 @@ endif() #Specify how to compile when ptx has been requested if(NOT CMAKE_CUDA_COMPILE_PTX_COMPILATION) set(CMAKE_CUDA_COMPILE_PTX_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -ptx <SOURCE> -o <OBJECT>") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -ptx <SOURCE> -o <OBJECT>") endif() #Specify how to compile when separable compilation has been requested if(NOT CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION) set(CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -dc <SOURCE> -o <OBJECT>") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -dc <SOURCE> -o <OBJECT>") endif() #Specify how to compile when whole compilation has been requested if(NOT CMAKE_CUDA_COMPILE_WHOLE_COMPILATION) set(CMAKE_CUDA_COMPILE_WHOLE_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -c <SOURCE> -o <OBJECT>") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -c <SOURCE> -o <OBJECT>") endif() -if(CMAKE_GENERATOR STREQUAL "Ninja" AND NOT CMAKE_DEPFILE_FLAGS_CUDA ) +if(CMAKE_GENERATOR STREQUAL "Ninja" AND NOT CMAKE_DEPFILE_FLAGS_CUDA) set(CMAKE_CUDA_COMPILE_DEPENDENCY_DETECTION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -M <SOURCE> -MT <OBJECT> -o $DEP_FILE") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -M <SOURCE> -MT <OBJECT> -o $DEP_FILE") #The Ninja generator uses the make file dependency files to determine what #files need to be recompiled. Unfortunately, nvcc < 10.2 doesn't support building #a source file and generating the dependencies of said file in a single diff --git a/Modules/CMakeDetermineASMCompiler.cmake b/Modules/CMakeDetermineASMCompiler.cmake index e47f3a4..86fb057 100644 --- a/Modules/CMakeDetermineASMCompiler.cmake +++ b/Modules/CMakeDetermineASMCompiler.cmake @@ -211,6 +211,13 @@ foreach(_var set(_CMAKE_ASM_${_var} "${CMAKE_ASM${ASM_DIALECT}_${_var}}") endforeach() +if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_MATCH) + set(_SET_CMAKE_ASM_COMPILER_ID_VENDOR_MATCH + "set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_MATCH [==[${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_MATCH}]==])") +else() + set(_SET_CMAKE_ASM_COMPILER_ID_VENDOR_MATCH "") +endif() + if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID) set(_SET_CMAKE_ASM_COMPILER_ARCHITECTURE_ID "set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID ${CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID})") diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake index 7d7fb9a..62ea686 100644 --- a/Modules/CMakeDetermineCUDACompiler.cmake +++ b/Modules/CMakeDetermineCUDACompiler.cmake @@ -86,7 +86,7 @@ if(${CMAKE_GENERATOR} MATCHES "Visual Studio") set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "") set(CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES "") set(CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") -elseif(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA) +elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") set(_nvcc_log "") string(REPLACE "\r" "" _nvcc_output_orig "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") if(_nvcc_output_orig MATCHES "#\\\$ +PATH= *([^\n]*)\n") @@ -188,30 +188,33 @@ elseif(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA) endif() endif() -set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES ) -string(REPLACE "\r" "" _nvcc_output_orig "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") -if(_nvcc_output_orig MATCHES "#\\\$ +INCLUDES= *([^\n]*)\n") - set(_nvcc_includes "${CMAKE_MATCH_1}") - string(APPEND _nvcc_log " found 'INCLUDES=' string: [${_nvcc_includes}]\n") -else() - set(_nvcc_includes "") - string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}") - string(APPEND _nvcc_log " no 'INCLUDES=' string found in nvcc output:${_nvcc_output_log}\n") -endif() -if(_nvcc_includes) - # across all operating system each include directory is prefixed with -I - separate_arguments(_nvcc_output NATIVE_COMMAND "${_nvcc_includes}") - foreach(line IN LISTS _nvcc_output) - string(REGEX REPLACE "^-I" "" line "${line}") - get_filename_component(line "${line}" ABSOLUTE) - list(APPEND CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "${line}") - endforeach() - - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "Parsed CUDA nvcc include information from above output:\n${_nvcc_log}\n${log}\n\n") -else() - file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "Failed to detect CUDA nvcc include information:\n${_nvcc_log}\n\n") +# Determine CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES +if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") + set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES) + string(REPLACE "\r" "" _nvcc_output_orig "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") + if(_nvcc_output_orig MATCHES "#\\\$ +INCLUDES= *([^\n]*)\n") + set(_nvcc_includes "${CMAKE_MATCH_1}") + string(APPEND _nvcc_log " found 'INCLUDES=' string: [${_nvcc_includes}]\n") + else() + set(_nvcc_includes "") + string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}") + string(APPEND _nvcc_log " no 'INCLUDES=' string found in nvcc output:${_nvcc_output_log}\n") + endif() + if(_nvcc_includes) + # across all operating system each include directory is prefixed with -I + separate_arguments(_nvcc_output NATIVE_COMMAND "${_nvcc_includes}") + foreach(line IN LISTS _nvcc_output) + string(REGEX REPLACE "^-I" "" line "${line}") + get_filename_component(line "${line}" ABSOLUTE) + list(APPEND CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "${line}") + endforeach() + + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Parsed CUDA nvcc include information from above output:\n${_nvcc_log}\n${log}\n\n") + else() + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Failed to detect CUDA nvcc include information:\n${_nvcc_log}\n\n") + endif() endif() # configure all variables set in this file diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index d125791..812f032 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -868,6 +868,14 @@ function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang userflags) file(MAKE_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR}) endif() + # Save the current LC_ALL, LC_MESSAGES, and LANG environment variables + # and set them to "C" so we get the expected output to match. + set(_orig_lc_all $ENV{LC_ALL}) + set(_orig_lc_messages $ENV{LC_MESSAGES}) + set(_orig_lang $ENV{LANG}) + set(ENV{LC_ALL} C) + set(ENV{LC_MESSAGES} C) + set(ENV{LANG} C) foreach(vendor ${CMAKE_${lang}_COMPILER_ID_VENDORS}) set(flags ${CMAKE_${lang}_COMPILER_ID_VENDOR_FLAGS_${vendor}}) @@ -889,6 +897,7 @@ function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang userflags) "matched \"${regex}\":\n${output}") set(CMAKE_${lang}_COMPILER_ID "${vendor}" PARENT_SCOPE) set(CMAKE_${lang}_COMPILER_ID_OUTPUT "${output}" PARENT_SCOPE) + set(CMAKE_${lang}_COMPILER_ID_VENDOR_MATCH "${CMAKE_MATCH_1}" PARENT_SCOPE) break() else() if("${result}" MATCHES "timeout") @@ -902,6 +911,11 @@ function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang userflags) endif() endif() endforeach() + + # Restore original LC_ALL, LC_MESSAGES, and LANG + set(ENV{LC_ALL} ${_orig_lc_all}) + set(ENV{LC_MESSAGES} ${_orig_lc_messages}) + set(ENV{LANG} ${_orig_lang}) endfunction() function(CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX lang userflags) diff --git a/Modules/CMakeFindFrameworks.cmake b/Modules/CMakeFindFrameworks.cmake index 06c05fb..8906f48 100644 --- a/Modules/CMakeFindFrameworks.cmake +++ b/Modules/CMakeFindFrameworks.cmake @@ -17,13 +17,25 @@ if(NOT CMAKE_FIND_FRAMEWORKS_INCLUDED) macro(CMAKE_FIND_FRAMEWORKS fwk) set(${fwk}_FRAMEWORKS) if(APPLE) - foreach(dir - ~/Library/Frameworks/${fwk}.framework - /usr/local/Frameworks/${fwk}.framework - /Library/Frameworks/${fwk}.framework - /System/Library/Frameworks/${fwk}.framework - /Network/Library/Frameworks/${fwk}.framework - ${CMAKE_FIND_FRAMEWORK_EXTRA_LOCATIONS}) + file(TO_CMAKE_PATH "$ENV{CMAKE_FRAMEWORK_PATH}" _cmff_CMAKE_FRAMEWORK_PATH) + set(_cmff_search_paths + ${CMAKE_FRAMEWORK_PATH} + ${_cmff_CMAKE_FRAMEWORK_PATH} + ~/Library/Frameworks + /usr/local/Frameworks + /Library/Frameworks + /System/Library/Frameworks + /Network/Library/Frameworks + ${CMAKE_SYSTEM_FRAMEWORK_PATH}) + + # For backwards compatibility reasons, + # CMAKE_FIND_FRAMEWORK_EXTRA_LOCATIONS includes ${fwk}.framework + list(TRANSFORM _cmff_search_paths APPEND /${fwk}.framework) + list(APPEND _cmff_search_paths ${CMAKE_FIND_FRAMEWORK_EXTRA_LOCATIONS}) + + list(REMOVE_DUPLICATES _cmff_search_paths) + + foreach(dir IN LISTS _cmff_search_paths) if(EXISTS ${dir}) set(${fwk}_FRAMEWORKS ${${fwk}_FRAMEWORKS} ${dir}) endif() diff --git a/Modules/CMakeSwiftInformation.cmake b/Modules/CMakeSwiftInformation.cmake index ba242ec..8f0909c 100644 --- a/Modules/CMakeSwiftInformation.cmake +++ b/Modules/CMakeSwiftInformation.cmake @@ -27,12 +27,14 @@ elseif(NOT CMAKE_SYSTEM_NAME STREQUAL Windows) endif() if(NOT CMAKE_SYSTEM_NAME STREQUAL Windows) + set(CMAKE_EXECUTABLE_RUNTIME_Swift_FLAG "-Xlinker -rpath -Xlinker ") set(CMAKE_SHARED_LIBRARY_RUNTIME_Swift_FLAG "-Xlinker -rpath -Xlinker ") - set(CMAKE_SHARED_LIBRARY_RUNTIME_Swift_FLAG_SEP ":") - - if(NOT CMAKE_SYSTEM_NAME STREQUAL Darwin) - set(CMAKE_EXECUTABLE_RUNTIME_Swift_FLAG "-Xlinker -rpath -Xlinker ") + if(CMAKE_SYSTEM_NAME STREQUAL Darwin) + set(CMAKE_EXECUTABLE_RUNTIME_Swift_FLAG_SEP "") + set(CMAKE_SHARED_LIBRARY_RUNTIME_Swift_FLAG_SEP "") + else() set(CMAKE_EXECUTABLE_RUNTIME_Swift_FLAG_SEP ":") + set(CMAKE_SHARED_LIBRARY_RUNTIME_Swift_FLAG_SEP ":") endif() endif() diff --git a/Modules/Compiler/AppleClang-CXX.cmake b/Modules/Compiler/AppleClang-CXX.cmake index 3fa6990..15edc21 100644 --- a/Modules/Compiler/AppleClang-CXX.cmake +++ b/Modules/Compiler/AppleClang-CXX.cmake @@ -25,7 +25,10 @@ elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.1) set(CMAKE_CXX14_STANDARD__HAS_FULL_SUPPORT ON) endif() -if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.1) +if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0) + set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std=c++17") + set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++17") +elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.1) set(CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std=c++1z") set(CMAKE_CXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z") endif() diff --git a/Modules/Compiler/AppleClang-OBJCXX.cmake b/Modules/Compiler/AppleClang-OBJCXX.cmake index 2c084af..409bd4a 100644 --- a/Modules/Compiler/AppleClang-OBJCXX.cmake +++ b/Modules/Compiler/AppleClang-OBJCXX.cmake @@ -22,7 +22,10 @@ elseif(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 5.1) set(CMAKE_OBJCXX14_STANDARD__HAS_FULL_SUPPORT ON) endif() -if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 6.1) +if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 10.0) + set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std=c++17") + set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std=gnu++17") +elseif (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 6.1) set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std=c++1z") set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z") endif() diff --git a/Modules/Compiler/GNU-ASM.cmake b/Modules/Compiler/GNU-ASM.cmake index e07401d..4aa680f 100644 --- a/Modules/Compiler/GNU-ASM.cmake +++ b/Modules/Compiler/GNU-ASM.cmake @@ -4,3 +4,9 @@ include(Compiler/GNU) set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS s;S;asm) __compiler_gnu(ASM) + +if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_MATCH STREQUAL "GNU assembler") + set(CMAKE_DEPFILE_FLAGS_ASM${ASM_DIALECT} "--MD <DEPFILE>") + set(CMAKE_ASM${ASM_DIALECT}_LINK_EXECUTABLE + "<CMAKE_LINKER> <FLAGS> <CMAKE_ASM${ASM_DIALECT}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>") +endif() diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake index 1f4d54d..2a2564e 100644 --- a/Modules/Compiler/NVIDIA-CUDA.cmake +++ b/Modules/Compiler/NVIDIA-CUDA.cmake @@ -4,6 +4,8 @@ set(CMAKE_CUDA_COMPILER_HAS_DEVICE_LINK_PHASE True) set(CMAKE_CUDA_VERBOSE_FLAG "-v") set(CMAKE_CUDA_VERBOSE_COMPILE_FLAG "-Xcompiler=-v") +set(_CMAKE_COMPILE_AS_CUDA_FLAG "-x cu") + if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 10.2.89) # The -forward-unknown-to-host-compiler flag was only # added to nvcc in 10.2 so before that we had no good diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake index f251b41..4b14ddc 100644 --- a/Modules/FindCUDAToolkit.cmake +++ b/Modules/FindCUDAToolkit.cmake @@ -477,6 +477,7 @@ if(CMAKE_CUDA_COMPILER_LOADED AND NOT CUDAToolkit_BIN_DIR) get_filename_component(cuda_dir "${CMAKE_CUDA_COMPILER}" DIRECTORY) # use the already detected cuda compiler set(CUDAToolkit_BIN_DIR "${cuda_dir}" CACHE PATH "") + mark_as_advanced(CUDAToolkit_BIN_DIR) unset(cuda_dir) endif() @@ -631,6 +632,7 @@ endif() if(NOT CUDAToolkit_BIN_DIR AND CUDAToolkit_NVCC_EXECUTABLE) get_filename_component(cuda_dir "${CUDAToolkit_NVCC_EXECUTABLE}" DIRECTORY) set(CUDAToolkit_BIN_DIR "${cuda_dir}" CACHE PATH "" FORCE) + mark_as_advanced(CUDAToolkit_BIN_DIR) unset(cuda_dir) endif() @@ -732,6 +734,10 @@ find_package_handle_standard_args(CUDAToolkit VERSION_VAR CUDAToolkit_VERSION ) +mark_as_advanced(CUDA_CUDART + CUDAToolkit_INCLUDE_DIR + CUDAToolkit_NVCC_EXECUTABLE + ) #----------------------------------------------------------------------------- # Construct result variables @@ -749,7 +755,6 @@ if(CUDAToolkit_FOUND) set(search_names ${lib_name} ${arg_ALT}) - message(STATUS "arg_EXTRA_PATH_SUFFIXES: ${arg_EXTRA_PATH_SUFFIXES}") find_library(CUDA_${lib_name}_LIBRARY NAMES ${search_names} HINTS ${CUDAToolkit_LIBRARY_DIR} @@ -757,6 +762,7 @@ if(CUDAToolkit_FOUND) PATH_SUFFIXES nvidia/current lib64 lib64/stubs lib/x64 lib lib/stubs ${arg_EXTRA_PATH_SUFFIXES} ) + mark_as_advanced(CUDA_${lib_name}_LIBRARY) if (NOT TARGET CUDA::${lib_name} AND CUDA_${lib_name}_LIBRARY) add_library(CUDA::${lib_name} IMPORTED INTERFACE) @@ -798,6 +804,7 @@ if(CUDAToolkit_FOUND) if(UNIX AND NOT APPLE) # On Linux, you must link against librt when using the static cuda runtime. find_library(CUDAToolkit_rt_LIBRARY rt) + mark_as_advanced(CUDAToolkit_rt_LIBRARY) if(NOT CUDAToolkit_rt_LIBRARY) message(WARNING "Could not find librt library, needed by CUDA::cudart_static") else() diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake index e903f2a..a40d7f7 100644 --- a/Modules/FindPython/Support.cmake +++ b/Modules/FindPython/Support.cmake @@ -95,8 +95,9 @@ endmacro() macro (_PYTHON_FIND_FRAMEWORKS) set (${_PYTHON_PREFIX}_FRAMEWORKS) if (CMAKE_HOST_APPLE OR APPLE) + file(TO_CMAKE_PATH "$ENV{CMAKE_FRAMEWORK_PATH}" _pff_CMAKE_FRAMEWORK_PATH) set (_pff_frameworks ${CMAKE_FRAMEWORK_PATH} - $ENV{CMAKE_FRAMEWORK_PATH} + ${_pff_CMAKE_FRAMEWORK_PATH} ~/Library/Frameworks /usr/local/Frameworks ${CMAKE_SYSTEM_FRAMEWORK_PATH}) @@ -313,7 +314,7 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) list (REMOVE_DUPLICATES _values) elseif (NAME STREQUAL "SOABI") # clean-up: remove prefix character and suffix - string (REGEX REPLACE "^[.-](.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\.(so|pyd))$" "\\1" _values "${_values}") + string (REGEX REPLACE "^[.-](.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\\.(so|pyd))$" "\\1" _values "${_values}") endif() endif() endif() @@ -354,7 +355,7 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) list (GET _soabi 1 _values) if (_values) # clean-up: remove prefix character and suffix - string (REGEX REPLACE "^[.-](.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\.(so|pyd))$" "\\1" _values "${_values}") + string (REGEX REPLACE "^[.-](.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\\.(so|pyd))$" "\\1" _values "${_values}") endif() endif() endif() @@ -524,8 +525,8 @@ function (_PYTHON_VALIDATE_INTERPRETER) set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") else() # check that version is OK - string(REGEX REPLACE "^([0-9]+)\." "\\1" major_version "${version}") - string(REGEX REPLACE "^([0-9]+)\." "\\1" expected_major_version "${expected_version}") + string(REGEX REPLACE "^([0-9]+)\\..*$" "\\1" major_version "${version}") + string(REGEX REPLACE "^([0-9]+)\\.?.*$" "\\1" expected_major_version "${expected_version}") if (NOT major_version VERSION_EQUAL expected_major_version OR NOT version VERSION_GREATER_EQUAL expected_version) set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") diff --git a/Modules/FindRuby.cmake b/Modules/FindRuby.cmake index 7e01fbc..5df242b 100644 --- a/Modules/FindRuby.cmake +++ b/Modules/FindRuby.cmake @@ -17,279 +17,323 @@ standard syntax, e.g. find_package(Ruby 1.8) It also determines what the name of the library is. This code sets the following variables: -``RUBY_EXECUTABLE`` +``Ruby_EXECUTABLE`` full path to the ruby binary -``RUBY_INCLUDE_DIRS`` +``Ruby_INCLUDE_DIRS`` include dirs to be used when using the ruby library -``RUBY_LIBRARY`` +``Ruby_LIBRARY`` full path to the ruby library -``RUBY_VERSION`` +``Ruby_VERSION`` the version of ruby which was found, e.g. "1.8.7" -``RUBY_FOUND`` +``Ruby_FOUND`` set to true if ruby ws found successfully Also: -``RUBY_INCLUDE_PATH`` - same as RUBY_INCLUDE_DIRS, only provided for compatibility reasons, don't use it +``Ruby_INCLUDE_PATH`` + same as Ruby_INCLUDE_DIRS, only provided for compatibility reasons, don't use it #]=======================================================================] -# RUBY_ARCHDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"archdir"@:>@)'` -# RUBY_SITEARCHDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitearchdir"@:>@)'` -# RUBY_SITEDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitelibdir"@:>@)'` -# RUBY_LIBDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"libdir"@:>@)'` -# RUBY_LIBRUBYARG=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"LIBRUBYARG_SHARED"@:>@)'` +# Backwards compatibility +# Define camel case versions of input variables +foreach(UPPER + RUBY_EXECUTABLE + RUBY_LIBRARY + RUBY_INCLUDE_DIR + RUBY_CONFIG_INCLUDE_DIR + ) + if (DEFINED ${UPPER}) + string(REPLACE "RUBY_" "Ruby_" Camel ${UPPER}) + if (NOT DEFINED ${Camel}) + set(${Camel} ${${UPPER}}) + endif() + endif() +endforeach() + +# Ruby_ARCHDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"archdir"@:>@)'` +# Ruby_SITEARCHDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitearchdir"@:>@)'` +# Ruby_SITEDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitelibdir"@:>@)'` +# Ruby_LIBDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"libdir"@:>@)'` +# Ruby_LIBRUBYARG=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"LIBRUBYARG_SHARED"@:>@)'` # uncomment the following line to get debug output for this file -# set(_RUBY_DEBUG_OUTPUT TRUE) +# set(_Ruby_DEBUG_OUTPUT TRUE) # Determine the list of possible names of the ruby executable depending # on which version of ruby is required -set(_RUBY_POSSIBLE_EXECUTABLE_NAMES ruby) +set(_Ruby_POSSIBLE_EXECUTABLE_NAMES ruby) # if 1.9 is required, don't look for ruby18 and ruby1.8, default to version 1.8 if(DEFINED Ruby_FIND_VERSION_MAJOR AND DEFINED Ruby_FIND_VERSION_MINOR) - set(Ruby_FIND_VERSION_SHORT_NODOT "${Ruby_FIND_VERSION_MAJOR}${RUBY_FIND_VERSION_MINOR}") + set(Ruby_FIND_VERSION_SHORT_NODOT "${Ruby_FIND_VERSION_MAJOR}${Ruby_FIND_VERSION_MINOR}") # we can't construct that if only major version is given - set(_RUBY_POSSIBLE_EXECUTABLE_NAMES + set(_Ruby_POSSIBLE_EXECUTABLE_NAMES ruby${Ruby_FIND_VERSION_MAJOR}.${Ruby_FIND_VERSION_MINOR} ruby${Ruby_FIND_VERSION_MAJOR}${Ruby_FIND_VERSION_MINOR} - ${_RUBY_POSSIBLE_EXECUTABLE_NAMES}) + ${_Ruby_POSSIBLE_EXECUTABLE_NAMES}) else() set(Ruby_FIND_VERSION_SHORT_NODOT "18") endif() if(NOT Ruby_FIND_VERSION_EXACT) - list(APPEND _RUBY_POSSIBLE_EXECUTABLE_NAMES ruby2.4 ruby24) - list(APPEND _RUBY_POSSIBLE_EXECUTABLE_NAMES ruby2.3 ruby23) - list(APPEND _RUBY_POSSIBLE_EXECUTABLE_NAMES ruby2.2 ruby22) - list(APPEND _RUBY_POSSIBLE_EXECUTABLE_NAMES ruby2.1 ruby21) - list(APPEND _RUBY_POSSIBLE_EXECUTABLE_NAMES ruby2.0 ruby20) - list(APPEND _RUBY_POSSIBLE_EXECUTABLE_NAMES ruby1.9 ruby19) + list(APPEND _Ruby_POSSIBLE_EXECUTABLE_NAMES ruby2.4 ruby24) + list(APPEND _Ruby_POSSIBLE_EXECUTABLE_NAMES ruby2.3 ruby23) + list(APPEND _Ruby_POSSIBLE_EXECUTABLE_NAMES ruby2.2 ruby22) + list(APPEND _Ruby_POSSIBLE_EXECUTABLE_NAMES ruby2.1 ruby21) + list(APPEND _Ruby_POSSIBLE_EXECUTABLE_NAMES ruby2.0 ruby20) + list(APPEND _Ruby_POSSIBLE_EXECUTABLE_NAMES ruby1.9 ruby19) # if we want a version below 1.9, also look for ruby 1.8 if("${Ruby_FIND_VERSION_SHORT_NODOT}" VERSION_LESS "19") - list(APPEND _RUBY_POSSIBLE_EXECUTABLE_NAMES ruby1.8 ruby18) + list(APPEND _Ruby_POSSIBLE_EXECUTABLE_NAMES ruby1.8 ruby18) endif() - list(REMOVE_DUPLICATES _RUBY_POSSIBLE_EXECUTABLE_NAMES) + list(REMOVE_DUPLICATES _Ruby_POSSIBLE_EXECUTABLE_NAMES) endif() -find_program(RUBY_EXECUTABLE NAMES ${_RUBY_POSSIBLE_EXECUTABLE_NAMES}) +find_program(Ruby_EXECUTABLE NAMES ${_Ruby_POSSIBLE_EXECUTABLE_NAMES}) -if(RUBY_EXECUTABLE AND NOT RUBY_VERSION_MAJOR) +if(Ruby_EXECUTABLE AND NOT Ruby_VERSION_MAJOR) function(_RUBY_CONFIG_VAR RBVAR OUTVAR) - execute_process(COMMAND ${RUBY_EXECUTABLE} -r rbconfig -e "print RbConfig::CONFIG['${RBVAR}']" - RESULT_VARIABLE _RUBY_SUCCESS - OUTPUT_VARIABLE _RUBY_OUTPUT + execute_process(COMMAND ${Ruby_EXECUTABLE} -r rbconfig -e "print RbConfig::CONFIG['${RBVAR}']" + RESULT_VARIABLE _Ruby_SUCCESS + OUTPUT_VARIABLE _Ruby_OUTPUT ERROR_QUIET) - if(_RUBY_SUCCESS OR _RUBY_OUTPUT STREQUAL "") - execute_process(COMMAND ${RUBY_EXECUTABLE} -r rbconfig -e "print Config::CONFIG['${RBVAR}']" - RESULT_VARIABLE _RUBY_SUCCESS - OUTPUT_VARIABLE _RUBY_OUTPUT + if(_Ruby_SUCCESS OR _Ruby_OUTPUT STREQUAL "") + execute_process(COMMAND ${Ruby_EXECUTABLE} -r rbconfig -e "print Config::CONFIG['${RBVAR}']" + RESULT_VARIABLE _Ruby_SUCCESS + OUTPUT_VARIABLE _Ruby_OUTPUT ERROR_QUIET) endif() - set(${OUTVAR} "${_RUBY_OUTPUT}" PARENT_SCOPE) + set(${OUTVAR} "${_Ruby_OUTPUT}" PARENT_SCOPE) endfunction() # query the ruby version - _RUBY_CONFIG_VAR("MAJOR" RUBY_VERSION_MAJOR) - _RUBY_CONFIG_VAR("MINOR" RUBY_VERSION_MINOR) - _RUBY_CONFIG_VAR("TEENY" RUBY_VERSION_PATCH) + _RUBY_CONFIG_VAR("MAJOR" Ruby_VERSION_MAJOR) + _RUBY_CONFIG_VAR("MINOR" Ruby_VERSION_MINOR) + _RUBY_CONFIG_VAR("TEENY" Ruby_VERSION_PATCH) # query the different directories - _RUBY_CONFIG_VAR("archdir" RUBY_ARCH_DIR) - _RUBY_CONFIG_VAR("arch" RUBY_ARCH) - _RUBY_CONFIG_VAR("rubyhdrdir" RUBY_HDR_DIR) - _RUBY_CONFIG_VAR("rubyarchhdrdir" RUBY_ARCHHDR_DIR) - _RUBY_CONFIG_VAR("libdir" RUBY_POSSIBLE_LIB_DIR) - _RUBY_CONFIG_VAR("rubylibdir" RUBY_RUBY_LIB_DIR) + _RUBY_CONFIG_VAR("archdir" Ruby_ARCH_DIR) + _RUBY_CONFIG_VAR("arch" Ruby_ARCH) + _RUBY_CONFIG_VAR("rubyhdrdir" Ruby_HDR_DIR) + _RUBY_CONFIG_VAR("rubyarchhdrdir" Ruby_ARCHHDR_DIR) + _RUBY_CONFIG_VAR("libdir" Ruby_POSSIBLE_LIB_DIR) + _RUBY_CONFIG_VAR("rubylibdir" Ruby_RUBY_LIB_DIR) # site_ruby - _RUBY_CONFIG_VAR("sitearchdir" RUBY_SITEARCH_DIR) - _RUBY_CONFIG_VAR("sitelibdir" RUBY_SITELIB_DIR) + _RUBY_CONFIG_VAR("sitearchdir" Ruby_SITEARCH_DIR) + _RUBY_CONFIG_VAR("sitelibdir" Ruby_SITELIB_DIR) # vendor_ruby available ? - execute_process(COMMAND ${RUBY_EXECUTABLE} -r vendor-specific -e "print 'true'" - OUTPUT_VARIABLE RUBY_HAS_VENDOR_RUBY ERROR_QUIET) + execute_process(COMMAND ${Ruby_EXECUTABLE} -r vendor-specific -e "print 'true'" + OUTPUT_VARIABLE Ruby_HAS_VENDOR_RUBY ERROR_QUIET) - if(RUBY_HAS_VENDOR_RUBY) - _RUBY_CONFIG_VAR("vendorlibdir" RUBY_VENDORLIB_DIR) - _RUBY_CONFIG_VAR("vendorarchdir" RUBY_VENDORARCH_DIR) + if(Ruby_HAS_VENDOR_RUBY) + _RUBY_CONFIG_VAR("vendorlibdir" Ruby_VENDORLIB_DIR) + _RUBY_CONFIG_VAR("vendorarchdir" Ruby_VENDORARCH_DIR) endif() # save the results in the cache so we don't have to run ruby the next time again - set(RUBY_VERSION_MAJOR ${RUBY_VERSION_MAJOR} CACHE PATH "The Ruby major version" FORCE) - set(RUBY_VERSION_MINOR ${RUBY_VERSION_MINOR} CACHE PATH "The Ruby minor version" FORCE) - set(RUBY_VERSION_PATCH ${RUBY_VERSION_PATCH} CACHE PATH "The Ruby patch version" FORCE) - set(RUBY_ARCH_DIR ${RUBY_ARCH_DIR} CACHE PATH "The Ruby arch dir" FORCE) - set(RUBY_HDR_DIR ${RUBY_HDR_DIR} CACHE PATH "The Ruby header dir (1.9+)" FORCE) - set(RUBY_ARCHHDR_DIR ${RUBY_ARCHHDR_DIR} CACHE PATH "The Ruby arch header dir (2.0+)" FORCE) - set(RUBY_POSSIBLE_LIB_DIR ${RUBY_POSSIBLE_LIB_DIR} CACHE PATH "The Ruby lib dir" FORCE) - set(RUBY_RUBY_LIB_DIR ${RUBY_RUBY_LIB_DIR} CACHE PATH "The Ruby ruby-lib dir" FORCE) - set(RUBY_SITEARCH_DIR ${RUBY_SITEARCH_DIR} CACHE PATH "The Ruby site arch dir" FORCE) - set(RUBY_SITELIB_DIR ${RUBY_SITELIB_DIR} CACHE PATH "The Ruby site lib dir" FORCE) - set(RUBY_HAS_VENDOR_RUBY ${RUBY_HAS_VENDOR_RUBY} CACHE BOOL "Vendor Ruby is available" FORCE) - set(RUBY_VENDORARCH_DIR ${RUBY_VENDORARCH_DIR} CACHE PATH "The Ruby vendor arch dir" FORCE) - set(RUBY_VENDORLIB_DIR ${RUBY_VENDORLIB_DIR} CACHE PATH "The Ruby vendor lib dir" FORCE) + set(Ruby_VERSION_MAJOR ${Ruby_VERSION_MAJOR} CACHE PATH "The Ruby major version" FORCE) + set(Ruby_VERSION_MINOR ${Ruby_VERSION_MINOR} CACHE PATH "The Ruby minor version" FORCE) + set(Ruby_VERSION_PATCH ${Ruby_VERSION_PATCH} CACHE PATH "The Ruby patch version" FORCE) + set(Ruby_ARCH_DIR ${Ruby_ARCH_DIR} CACHE PATH "The Ruby arch dir" FORCE) + set(Ruby_HDR_DIR ${Ruby_HDR_DIR} CACHE PATH "The Ruby header dir (1.9+)" FORCE) + set(Ruby_ARCHHDR_DIR ${Ruby_ARCHHDR_DIR} CACHE PATH "The Ruby arch header dir (2.0+)" FORCE) + set(Ruby_POSSIBLE_LIB_DIR ${Ruby_POSSIBLE_LIB_DIR} CACHE PATH "The Ruby lib dir" FORCE) + set(Ruby_RUBY_LIB_DIR ${Ruby_RUBY_LIB_DIR} CACHE PATH "The Ruby ruby-lib dir" FORCE) + set(Ruby_SITEARCH_DIR ${Ruby_SITEARCH_DIR} CACHE PATH "The Ruby site arch dir" FORCE) + set(Ruby_SITELIB_DIR ${Ruby_SITELIB_DIR} CACHE PATH "The Ruby site lib dir" FORCE) + set(Ruby_HAS_VENDOR_RUBY ${Ruby_HAS_VENDOR_RUBY} CACHE BOOL "Vendor Ruby is available" FORCE) + set(Ruby_VENDORARCH_DIR ${Ruby_VENDORARCH_DIR} CACHE PATH "The Ruby vendor arch dir" FORCE) + set(Ruby_VENDORLIB_DIR ${Ruby_VENDORLIB_DIR} CACHE PATH "The Ruby vendor lib dir" FORCE) mark_as_advanced( - RUBY_ARCH_DIR - RUBY_ARCH - RUBY_HDR_DIR - RUBY_ARCHHDR_DIR - RUBY_POSSIBLE_LIB_DIR - RUBY_RUBY_LIB_DIR - RUBY_SITEARCH_DIR - RUBY_SITELIB_DIR - RUBY_HAS_VENDOR_RUBY - RUBY_VENDORARCH_DIR - RUBY_VENDORLIB_DIR - RUBY_VERSION_MAJOR - RUBY_VERSION_MINOR - RUBY_VERSION_PATCH + Ruby_ARCH_DIR + Ruby_ARCH + Ruby_HDR_DIR + Ruby_ARCHHDR_DIR + Ruby_POSSIBLE_LIB_DIR + Ruby_RUBY_LIB_DIR + Ruby_SITEARCH_DIR + Ruby_SITELIB_DIR + Ruby_HAS_VENDOR_RUBY + Ruby_VENDORARCH_DIR + Ruby_VENDORLIB_DIR + Ruby_VERSION_MAJOR + Ruby_VERSION_MINOR + Ruby_VERSION_PATCH ) endif() -# In case RUBY_EXECUTABLE could not be executed (e.g. cross compiling) +# In case Ruby_EXECUTABLE could not be executed (e.g. cross compiling) # try to detect which version we found. This is not too good. -if(RUBY_EXECUTABLE AND NOT RUBY_VERSION_MAJOR) +if(Ruby_EXECUTABLE AND NOT Ruby_VERSION_MAJOR) # by default assume 1.8.0 - set(RUBY_VERSION_MAJOR 1) - set(RUBY_VERSION_MINOR 8) - set(RUBY_VERSION_PATCH 0) + set(Ruby_VERSION_MAJOR 1) + set(Ruby_VERSION_MINOR 8) + set(Ruby_VERSION_PATCH 0) # check whether we found 1.9.x - if(${RUBY_EXECUTABLE} MATCHES "ruby1\\.?9") - set(RUBY_VERSION_MAJOR 1) - set(RUBY_VERSION_MINOR 9) + if(${Ruby_EXECUTABLE} MATCHES "ruby1\\.?9") + set(Ruby_VERSION_MAJOR 1) + set(Ruby_VERSION_MINOR 9) endif() # check whether we found 2.0.x - if(${RUBY_EXECUTABLE} MATCHES "ruby2\\.?0") - set(RUBY_VERSION_MAJOR 2) - set(RUBY_VERSION_MINOR 0) + if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?0") + set(Ruby_VERSION_MAJOR 2) + set(Ruby_VERSION_MINOR 0) endif() # check whether we found 2.1.x - if(${RUBY_EXECUTABLE} MATCHES "ruby2\\.?1") - set(RUBY_VERSION_MAJOR 2) - set(RUBY_VERSION_MINOR 1) + if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?1") + set(Ruby_VERSION_MAJOR 2) + set(Ruby_VERSION_MINOR 1) endif() # check whether we found 2.2.x - if(${RUBY_EXECUTABLE} MATCHES "ruby2\\.?2") - set(RUBY_VERSION_MAJOR 2) - set(RUBY_VERSION_MINOR 2) + if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?2") + set(Ruby_VERSION_MAJOR 2) + set(Ruby_VERSION_MINOR 2) endif() # check whether we found 2.3.x - if(${RUBY_EXECUTABLE} MATCHES "ruby2\\.?3") - set(RUBY_VERSION_MAJOR 2) - set(RUBY_VERSION_MINOR 3) + if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?3") + set(Ruby_VERSION_MAJOR 2) + set(Ruby_VERSION_MINOR 3) endif() # check whether we found 2.4.x - if(${RUBY_EXECUTABLE} MATCHES "ruby2\\.?4") - set(RUBY_VERSION_MAJOR 2) - set(RUBY_VERSION_MINOR 4) + if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?4") + set(Ruby_VERSION_MAJOR 2) + set(Ruby_VERSION_MINOR 4) endif() endif() -if(RUBY_VERSION_MAJOR) - set(RUBY_VERSION "${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}.${RUBY_VERSION_PATCH}") - set(_RUBY_VERSION_SHORT "${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}") - set(_RUBY_VERSION_SHORT_NODOT "${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}") - set(_RUBY_NODOT_VERSION "${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}${RUBY_VERSION_PATCH}") +if(Ruby_VERSION_MAJOR) + set(Ruby_VERSION "${Ruby_VERSION_MAJOR}.${Ruby_VERSION_MINOR}.${Ruby_VERSION_PATCH}") + set(_Ruby_VERSION_SHORT "${Ruby_VERSION_MAJOR}.${Ruby_VERSION_MINOR}") + set(_Ruby_VERSION_SHORT_NODOT "${Ruby_VERSION_MAJOR}${Ruby_VERSION_MINOR}") + set(_Ruby_NODOT_VERSION "${Ruby_VERSION_MAJOR}${Ruby_VERSION_MINOR}${Ruby_VERSION_PATCH}") endif() -find_path(RUBY_INCLUDE_DIR +find_path(Ruby_INCLUDE_DIR NAMES ruby.h HINTS - ${RUBY_HDR_DIR} - ${RUBY_ARCH_DIR} - /usr/lib/ruby/${_RUBY_VERSION_SHORT}/i586-linux-gnu/ + ${Ruby_HDR_DIR} + ${Ruby_ARCH_DIR} + /usr/lib/ruby/${_Ruby_VERSION_SHORT}/i586-linux-gnu/ ) -set(RUBY_INCLUDE_DIRS ${RUBY_INCLUDE_DIR} ) +set(Ruby_INCLUDE_DIRS ${Ruby_INCLUDE_DIR} ) # if ruby > 1.8 is required or if ruby > 1.8 was found, search for the config.h dir -if( "${Ruby_FIND_VERSION_SHORT_NODOT}" GREATER 18 OR "${_RUBY_VERSION_SHORT_NODOT}" GREATER 18 OR RUBY_HDR_DIR) - find_path(RUBY_CONFIG_INCLUDE_DIR +if( "${Ruby_FIND_VERSION_SHORT_NODOT}" GREATER 18 OR "${_Ruby_VERSION_SHORT_NODOT}" GREATER 18 OR Ruby_HDR_DIR) + find_path(Ruby_CONFIG_INCLUDE_DIR NAMES ruby/config.h config.h HINTS - ${RUBY_HDR_DIR}/${RUBY_ARCH} - ${RUBY_ARCH_DIR} - ${RUBY_ARCHHDR_DIR} + ${Ruby_HDR_DIR}/${Ruby_ARCH} + ${Ruby_ARCH_DIR} + ${Ruby_ARCHHDR_DIR} ) - set(RUBY_INCLUDE_DIRS ${RUBY_INCLUDE_DIRS} ${RUBY_CONFIG_INCLUDE_DIR} ) + set(Ruby_INCLUDE_DIRS ${Ruby_INCLUDE_DIRS} ${Ruby_CONFIG_INCLUDE_DIR} ) endif() # Determine the list of possible names for the ruby library -set(_RUBY_POSSIBLE_LIB_NAMES ruby ruby-static ruby${_RUBY_VERSION_SHORT} ruby${_RUBY_VERSION_SHORT_NODOT} ruby-${_RUBY_VERSION_SHORT} ruby-${RUBY_VERSION}) +set(_Ruby_POSSIBLE_LIB_NAMES ruby ruby-static ruby${_Ruby_VERSION_SHORT} ruby${_Ruby_VERSION_SHORT_NODOT} ruby-${_Ruby_VERSION_SHORT} ruby-${Ruby_VERSION}) if(WIN32) - set( _RUBY_MSVC_RUNTIME "" ) + set( _Ruby_MSVC_RUNTIME "" ) if( MSVC_VERSION EQUAL 1200 ) - set( _RUBY_MSVC_RUNTIME "60" ) + set( _Ruby_MSVC_RUNTIME "60" ) endif() if( MSVC_VERSION EQUAL 1300 ) - set( _RUBY_MSVC_RUNTIME "70" ) + set( _Ruby_MSVC_RUNTIME "70" ) endif() if( MSVC_VERSION EQUAL 1310 ) - set( _RUBY_MSVC_RUNTIME "71" ) + set( _Ruby_MSVC_RUNTIME "71" ) endif() if( MSVC_VERSION EQUAL 1400 ) - set( _RUBY_MSVC_RUNTIME "80" ) + set( _Ruby_MSVC_RUNTIME "80" ) endif() if( MSVC_VERSION EQUAL 1500 ) - set( _RUBY_MSVC_RUNTIME "90" ) + set( _Ruby_MSVC_RUNTIME "90" ) endif() - set(_RUBY_ARCH_PREFIX "") + set(_Ruby_ARCH_PREFIX "") if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(_RUBY_ARCH_PREFIX "x64-") + set(_Ruby_ARCH_PREFIX "x64-") endif() - list(APPEND _RUBY_POSSIBLE_LIB_NAMES - "${_RUBY_ARCH_PREFIX}msvcr${_RUBY_MSVC_RUNTIME}-ruby${_RUBY_NODOT_VERSION}" - "${_RUBY_ARCH_PREFIX}msvcr${_RUBY_MSVC_RUNTIME}-ruby${_RUBY_NODOT_VERSION}-static" - "${_RUBY_ARCH_PREFIX}msvcrt-ruby${_RUBY_NODOT_VERSION}" - "${_RUBY_ARCH_PREFIX}msvcrt-ruby${_RUBY_NODOT_VERSION}-static" ) + list(APPEND _Ruby_POSSIBLE_LIB_NAMES + "${_Ruby_ARCH_PREFIX}msvcr${_Ruby_MSVC_RUNTIME}-ruby${_Ruby_NODOT_VERSION}" + "${_Ruby_ARCH_PREFIX}msvcr${_Ruby_MSVC_RUNTIME}-ruby${_Ruby_NODOT_VERSION}-static" + "${_Ruby_ARCH_PREFIX}msvcrt-ruby${_Ruby_NODOT_VERSION}" + "${_Ruby_ARCH_PREFIX}msvcrt-ruby${_Ruby_NODOT_VERSION}-static" ) endif() -find_library(RUBY_LIBRARY NAMES ${_RUBY_POSSIBLE_LIB_NAMES} HINTS ${RUBY_POSSIBLE_LIB_DIR} ) +find_library(Ruby_LIBRARY NAMES ${_Ruby_POSSIBLE_LIB_NAMES} HINTS ${Ruby_POSSIBLE_LIB_DIR} ) include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) -set(_RUBY_REQUIRED_VARS RUBY_EXECUTABLE RUBY_INCLUDE_DIR RUBY_LIBRARY) -if(_RUBY_VERSION_SHORT_NODOT GREATER 18) - list(APPEND _RUBY_REQUIRED_VARS RUBY_CONFIG_INCLUDE_DIR) +set(_Ruby_REQUIRED_VARS Ruby_EXECUTABLE Ruby_INCLUDE_DIR Ruby_LIBRARY) +if(_Ruby_VERSION_SHORT_NODOT GREATER 18) + list(APPEND _Ruby_REQUIRED_VARS Ruby_CONFIG_INCLUDE_DIR) endif() -if(_RUBY_DEBUG_OUTPUT) +if(_Ruby_DEBUG_OUTPUT) message(STATUS "--------FindRuby.cmake debug------------") - message(STATUS "_RUBY_POSSIBLE_EXECUTABLE_NAMES: ${_RUBY_POSSIBLE_EXECUTABLE_NAMES}") - message(STATUS "_RUBY_POSSIBLE_LIB_NAMES: ${_RUBY_POSSIBLE_LIB_NAMES}") - message(STATUS "RUBY_ARCH_DIR: ${RUBY_ARCH_DIR}") - message(STATUS "RUBY_HDR_DIR: ${RUBY_HDR_DIR}") - message(STATUS "RUBY_POSSIBLE_LIB_DIR: ${RUBY_POSSIBLE_LIB_DIR}") - message(STATUS "Found RUBY_VERSION: \"${RUBY_VERSION}\" , short: \"${_RUBY_VERSION_SHORT}\", nodot: \"${_RUBY_VERSION_SHORT_NODOT}\"") - message(STATUS "_RUBY_REQUIRED_VARS: ${_RUBY_REQUIRED_VARS}") - message(STATUS "RUBY_EXECUTABLE: ${RUBY_EXECUTABLE}") - message(STATUS "RUBY_LIBRARY: ${RUBY_LIBRARY}") - message(STATUS "RUBY_INCLUDE_DIR: ${RUBY_INCLUDE_DIR}") - message(STATUS "RUBY_CONFIG_INCLUDE_DIR: ${RUBY_CONFIG_INCLUDE_DIR}") + message(STATUS "_Ruby_POSSIBLE_EXECUTABLE_NAMES: ${_Ruby_POSSIBLE_EXECUTABLE_NAMES}") + message(STATUS "_Ruby_POSSIBLE_LIB_NAMES: ${_Ruby_POSSIBLE_LIB_NAMES}") + message(STATUS "Ruby_ARCH_DIR: ${Ruby_ARCH_DIR}") + message(STATUS "Ruby_HDR_DIR: ${Ruby_HDR_DIR}") + message(STATUS "Ruby_POSSIBLE_LIB_DIR: ${Ruby_POSSIBLE_LIB_DIR}") + message(STATUS "Found Ruby_VERSION: \"${Ruby_VERSION}\" , short: \"${_Ruby_VERSION_SHORT}\", nodot: \"${_Ruby_VERSION_SHORT_NODOT}\"") + message(STATUS "_Ruby_REQUIRED_VARS: ${_Ruby_REQUIRED_VARS}") + message(STATUS "Ruby_EXECUTABLE: ${Ruby_EXECUTABLE}") + message(STATUS "Ruby_LIBRARY: ${Ruby_LIBRARY}") + message(STATUS "Ruby_INCLUDE_DIR: ${Ruby_INCLUDE_DIR}") + message(STATUS "Ruby_CONFIG_INCLUDE_DIR: ${Ruby_CONFIG_INCLUDE_DIR}") message(STATUS "--------------------") endif() -FIND_PACKAGE_HANDLE_STANDARD_ARGS(Ruby REQUIRED_VARS ${_RUBY_REQUIRED_VARS} - VERSION_VAR RUBY_VERSION ) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Ruby REQUIRED_VARS ${_Ruby_REQUIRED_VARS} + VERSION_VAR Ruby_VERSION ) mark_as_advanced( - RUBY_EXECUTABLE - RUBY_LIBRARY - RUBY_INCLUDE_DIR - RUBY_CONFIG_INCLUDE_DIR + Ruby_EXECUTABLE + Ruby_LIBRARY + Ruby_INCLUDE_DIR + Ruby_CONFIG_INCLUDE_DIR ) -# Set some variables for compatibility with previous version of this file -set(RUBY_POSSIBLE_LIB_PATH ${RUBY_POSSIBLE_LIB_DIR}) -set(RUBY_RUBY_LIB_PATH ${RUBY_RUBY_LIB_DIR}) -set(RUBY_INCLUDE_PATH ${RUBY_INCLUDE_DIRS}) +# Set some variables for compatibility with previous version of this file (no need to provide a CamelCase version of that...) +set(RUBY_POSSIBLE_LIB_PATH ${Ruby_POSSIBLE_LIB_DIR}) +set(RUBY_RUBY_LIB_PATH ${Ruby_RUBY_LIB_DIR}) +set(RUBY_INCLUDE_PATH ${Ruby_INCLUDE_DIRS}) + +# Backwards compatibility +# Define upper case versions of output variables +foreach(Camel + Ruby_EXECUTABLE + Ruby_INCLUDE_DIRS + Ruby_LIBRARY + Ruby_VERSION + Ruby_VERSION_MAJOR + Ruby_VERSION_MINOR + Ruby_VERSION_PATCH + Ruby_INCLUDE_PATH + + Ruby_ARCH_DIR + Ruby_ARCH + Ruby_HDR_DIR + Ruby_ARCHHDR_DIR + Ruby_POSSIBLE_LIB_DIR + Ruby_RUBY_LIB_DIR + Ruby_SITEARCH_DIR + Ruby_SITELIB_DIR + Ruby_HAS_VENDOR_RUBY + Ruby_VENDORARCH_DIR + + ) + string(TOUPPER ${Camel} UPPER) + set(${UPPER} ${${Camel}}) +endforeach() diff --git a/Modules/FindThreads.cmake b/Modules/FindThreads.cmake index 85174d9..f97e5c8 100644 --- a/Modules/FindThreads.cmake +++ b/Modules/FindThreads.cmake @@ -7,31 +7,44 @@ FindThreads This module determines the thread library of the system. -The following variables are set +Imported Targets +^^^^^^^^^^^^^^^^ -:: +This module defines the following :prop_tgt:`IMPORTED` target: - CMAKE_THREAD_LIBS_INIT - the thread library - CMAKE_USE_WIN32_THREADS_INIT - using WIN32 threads? - CMAKE_USE_PTHREADS_INIT - are we using pthreads - CMAKE_HP_PTHREADS_INIT - are we using hp pthreads +``Threads::Threads`` + The thread library, if found. -The following import target is created +Result Variables +^^^^^^^^^^^^^^^^ -:: +The following variables are set: - Threads::Threads +``Threads_FOUND`` + If a supported thread library was found. +``CMAKE_THREAD_LIBS_INIT`` + The thread library to use. This may be empty if the thread functions + are provided by the system libraries and no special flags are needed + to use them. +``CMAKE_USE_WIN32_THREADS_INIT`` + If the found thread library is the win32 one. +``CMAKE_USE_PTHREADS_INIT`` + If the found thread library is pthread compatible. +``CMAKE_HP_PTHREADS_INIT`` + If the found thread library is the HP thread library. -If the use of the -pthread compiler and linker flag is preferred then the -caller can set +Variables Affecting Behavior +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -:: +.. variable:: THREADS_PREFER_PTHREAD_FLAG - THREADS_PREFER_PTHREAD_FLAG + If the use of the -pthread compiler and linker flag is preferred then + the caller can set this variable to TRUE. The compiler flag can only be + used with the imported target. Use of both the imported target as well + as this switch is highly recommended for new code. -The compiler flag can only be used with the imported -target. Use of both the imported target as well as this switch is highly -recommended for new code. + This variable has no effect if the system libraries provide the + thread functions, i.e. when ``CMAKE_THREAD_LIBS_INIT`` will be empty. #]=======================================================================] include (CheckLibraryExists) diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake index a5bb863..1d4398e 100644 --- a/Modules/GoogleTest.cmake +++ b/Modules/GoogleTest.cmake @@ -151,6 +151,7 @@ same as the Google Test name (i.e. ``suite.testcase``); see also [PROPERTIES name1 value1...] [TEST_LIST var] [DISCOVERY_TIMEOUT seconds] + [XML_OUTPUT_DIR dir] ) ``gtest_discover_tests`` sets up a post-build command on the test executable @@ -236,6 +237,13 @@ same as the Google Test name (i.e. ``suite.testcase``); see also problem. The ambiguous behavior of the ``TIMEOUT`` keyword in 3.10.1 and 3.10.2 has not been preserved. + ``XML_OUTPUT_DIR dir`` + If specified, the parameter is passed along with ``--gtest_output=xml:`` + to test executable. The actual file name is the same as the test target, + including prefix and suffix. This should be used instead of + ``EXTRA_ARGS --gtest_output=xml`` to avoid race conditions writing the + XML result output when using parallel test execution. + #]=======================================================================] # Save project's policies @@ -372,7 +380,7 @@ function(gtest_discover_tests TARGET) cmake_parse_arguments( "" "NO_PRETTY_TYPES;NO_PRETTY_VALUES" - "TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;DISCOVERY_TIMEOUT" + "TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;DISCOVERY_TIMEOUT;XML_OUTPUT_DIR" "EXTRA_ARGS;PROPERTIES" ${ARGN} ) @@ -434,6 +442,7 @@ function(gtest_discover_tests TARGET) -D "TEST_LIST=${_TEST_LIST}" -D "CTEST_FILE=${ctest_tests_file}" -D "TEST_DISCOVERY_TIMEOUT=${_DISCOVERY_TIMEOUT}" + -D "TEST_XML_OUTPUT_DIR=${_XML_OUTPUT_DIR}" -P "${_GOOGLETEST_DISCOVER_TESTS_SCRIPT}" VERBATIM ) diff --git a/Modules/GoogleTestAddTests.cmake b/Modules/GoogleTestAddTests.cmake index 4f52ad2..753319f 100644 --- a/Modules/GoogleTestAddTests.cmake +++ b/Modules/GoogleTestAddTests.cmake @@ -13,11 +13,13 @@ set(tests) set(tests_buffer) # Overwrite possibly existing ${CTEST_FILE} with empty file -file(WRITE "${CTEST_FILE}" "") +set(flush_tests_MODE WRITE) # Flushes script to ${CTEST_FILE} macro(flush_script) - file(APPEND "${CTEST_FILE}" "${script}") + file(${flush_tests_MODE} "${CTEST_FILE}" "${script}") + set(flush_tests_MODE APPEND) + set(script "") endmacro() @@ -97,6 +99,11 @@ foreach(line ${output}) endif() string(REGEX REPLACE "^DISABLED_" "" pretty_test "${pretty_test}") string(REGEX REPLACE "#.*" "" test "${test}") + if(NOT TEST_XML_OUTPUT_DIR STREQUAL "") + set(TEST_XML_OUTPUT_PARAM "--gtest_output=xml:${TEST_XML_OUTPUT_DIR}/${prefix}${pretty_suite}.${pretty_test}${suffix}.xml") + else() + unset(TEST_XML_OUTPUT_PARAM) + endif() # ...and add to script add_command(add_test "${prefix}${pretty_suite}.${pretty_test}${suffix}" @@ -104,6 +111,7 @@ foreach(line ${output}) "${TEST_EXECUTABLE}" "--gtest_filter=${suite}.${test}" "--gtest_also_run_disabled_tests" + ${TEST_XML_OUTPUT_PARAM} ${extra_args} ) if(suite MATCHES "^DISABLED" OR test MATCHES "^DISABLED") diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake index af43f46..2f50280 100644 --- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake +++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake @@ -1,11 +1,11 @@ include(Platform/Windows-MSVC) set(CMAKE_CUDA_COMPILE_PTX_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -ptx <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -ptx <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") set(CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -dc <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -dc <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") set(CMAKE_CUDA_COMPILE_WHOLE_COMPILATION - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> -x cu -c <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -c <SOURCE> -o <OBJECT> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS") set(__IMPLICT_LINKS ) foreach(dir ${CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES}) @@ -48,7 +48,7 @@ unset(__IMPLICT_DLINK_DIRS) set(CMAKE_CUDA_DEVICE_LINK_LIBRARY "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <LANGUAGE_COMPILE_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}") set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE - "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}") + "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}") unset(__IMPLICT_DLINK_FLAGS) string(REPLACE "/D" "-D" _PLATFORM_DEFINES_CUDA "${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_CXX}") diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 24370aa..467abe9 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -354,6 +354,7 @@ set(SRCS cmMakefileTargetGenerator.cxx cmMakefileExecutableTargetGenerator.cxx cmMakefileLibraryTargetGenerator.cxx + cmMakefileProfilingData.cxx cmMakefileUtilityTargetGenerator.cxx cmMessageType.h cmMessenger.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 3fce9e5..00cc3bb 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 17) -set(CMake_VERSION_PATCH 20200310) +set(CMake_VERSION_PATCH 20200318) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CTest/cmCTestCurl.cxx b/Source/CTest/cmCTestCurl.cxx index 3ad4749..69c5793 100644 --- a/Source/CTest/cmCTestCurl.cxx +++ b/Source/CTest/cmCTestCurl.cxx @@ -55,7 +55,7 @@ size_t curlDebugCallback(CURL* /*unused*/, curl_infotype /*unused*/, char* chPtr, size_t size, void* data) { cm::append(*static_cast<std::vector<char>*>(data), chPtr, chPtr + size); - return size; + return 0; } } diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 2192843..50c963d 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -12,13 +12,13 @@ #include <iomanip> #include <iostream> #include <list> -#include <memory> #include <sstream> #include <stack> #include <unordered_map> #include <utility> #include <vector> +#include <cm/memory> #include <cmext/algorithm> #include "cmsys/FStream.hxx" @@ -172,7 +172,8 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) this->EraseTest(test); this->RunningCount += GetProcessorsUsed(test); - cmCTestRunTest* testRun = new cmCTestRunTest(*this); + auto testRun = cm::make_unique<cmCTestRunTest>(*this); + if (this->RepeatMode != cmCTest::Repeat::Never) { testRun->SetRepeatMode(this->RepeatMode); testRun->SetNumberOfRuns(this->RepeatCount); @@ -229,28 +230,25 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) e << "\n"; } e << "Resource spec file:\n\n " << this->TestHandler->ResourceSpecFile; - testRun->StartFailure(e.str(), "Insufficient resources"); - this->FinishTestProcess(testRun, false); + cmCTestRunTest::StartFailure(std::move(testRun), e.str(), + "Insufficient resources"); return false; } cmWorkingDirectory workdir(this->Properties[test]->Directory); if (workdir.Failed()) { - testRun->StartFailure("Failed to change working directory to " + - this->Properties[test]->Directory + " : " + - std::strerror(workdir.GetLastResult()), - "Failed to change working directory"); - } 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; - } + cmCTestRunTest::StartFailure(std::move(testRun), + "Failed to change working directory to " + + this->Properties[test]->Directory + " : " + + std::strerror(workdir.GetLastResult()), + "Failed to change working directory"); + return false; } - // Pass ownership of 'testRun'. - this->FinishTestProcess(testRun, false); - return false; + // Ownership of 'testRun' has moved to another structure. + // When the test finishes, FinishTestProcess will be called. + return cmCTestRunTest::StartTest(std::move(testRun), this->Completed, + this->Total); } bool cmCTestMultiProcessHandler::AllocateResources(int index) @@ -540,7 +538,8 @@ void cmCTestMultiProcessHandler::StartNextTests() if (this->SerialTestRunning) { break; } - // We can only start a RUN_SERIAL test if no other tests are also running. + // We can only start a RUN_SERIAL test if no other tests are also + // running. if (this->Properties[test]->RunSerial && this->RunningCount > 0) { continue; } @@ -618,8 +617,8 @@ void cmCTestMultiProcessHandler::OnTestLoadRetryCB(uv_timer_t* timer) self->StartNextTests(); } -void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner, - bool started) +void cmCTestMultiProcessHandler::FinishTestProcess( + std::unique_ptr<cmCTestRunTest> runner, bool started) { this->Completed++; @@ -631,7 +630,8 @@ void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner, this->SetStopTimePassed(); } if (started) { - if (!this->StopTimePassed && runner->StartAgain(this->Completed)) { + if (!this->StopTimePassed && + cmCTestRunTest::StartAgain(std::move(runner), this->Completed)) { this->Completed--; // remove the completed test because run again return; } @@ -659,7 +659,7 @@ void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner, } properties->Affinity.clear(); - delete runner; + runner.reset(); if (started) { this->StartNextTests(); } diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h index 5b429d4..c3686bc 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.h +++ b/Source/CTest/cmCTestMultiProcessHandler.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <map> +#include <memory> #include <set> #include <string> #include <vector> @@ -124,7 +125,7 @@ protected: // Removes the checkpoint file void MarkFinished(); void EraseTest(int index); - void FinishTestProcess(cmCTestRunTest* runner, bool started); + void FinishTestProcess(std::unique_ptr<cmCTestRunTest> runner, bool started); static void OnTestLoadRetryCB(uv_timer_t* timer); diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index ec54960..7d0f69b 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -314,23 +314,27 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) return passed || skipped; } -bool cmCTestRunTest::StartAgain(size_t completed) +bool cmCTestRunTest::StartAgain(std::unique_ptr<cmCTestRunTest> runner, + size_t completed) { - if (!this->RunAgain) { + auto* testRun = runner.get(); + + if (!testRun->RunAgain) { return false; } - this->RunAgain = false; // reset + testRun->RunAgain = false; // reset + testRun->TestProcess = cm::make_unique<cmProcess>(std::move(runner)); // change to tests directory - cmWorkingDirectory workdir(this->TestProperties->Directory); + cmWorkingDirectory workdir(testRun->TestProperties->Directory); if (workdir.Failed()) { - this->StartFailure("Failed to change working directory to " + - this->TestProperties->Directory + " : " + - std::strerror(workdir.GetLastResult()), - "Failed to change working directory"); + testRun->StartFailure("Failed to change working directory to " + + testRun->TestProperties->Directory + " : " + + std::strerror(workdir.GetLastResult()), + "Failed to change working directory"); return true; } - this->StartTest(completed, this->TotalNumberOfTests); + testRun->StartTest(completed, testRun->TotalNumberOfTests); return true; } @@ -382,6 +386,18 @@ void cmCTestRunTest::MemCheckPostProcess() handler->PostProcessTest(this->TestResult, this->Index); } +void cmCTestRunTest::StartFailure(std::unique_ptr<cmCTestRunTest> runner, + std::string const& output, + std::string const& detail) +{ + auto* testRun = runner.get(); + + testRun->TestProcess = cm::make_unique<cmProcess>(std::move(runner)); + testRun->StartFailure(output, detail); + + testRun->FinalizeTest(false); +} + void cmCTestRunTest::StartFailure(std::string const& output, std::string const& detail) { @@ -413,7 +429,6 @@ void cmCTestRunTest::StartFailure(std::string const& output, this->TestResult.Path = this->TestProperties->Directory; this->TestResult.Output = output; this->TestResult.FullCommandLine.clear(); - this->TestProcess = cm::make_unique<cmProcess>(*this); } std::string cmCTestRunTest::GetTestPrefix(size_t completed, size_t total) const @@ -437,6 +452,21 @@ std::string cmCTestRunTest::GetTestPrefix(size_t completed, size_t total) const return outputStream.str(); } +bool cmCTestRunTest::StartTest(std::unique_ptr<cmCTestRunTest> runner, + size_t completed, size_t total) +{ + auto* testRun = runner.get(); + + testRun->TestProcess = cm::make_unique<cmProcess>(std::move(runner)); + + if (!testRun->StartTest(completed, total)) { + testRun->FinalizeTest(false); + return false; + } + + return true; +} + // Starts the execution of a test. Returns once it has started bool cmCTestRunTest::StartTest(size_t completed, size_t total) { @@ -468,7 +498,6 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) if (this->TestProperties->Disabled) { this->TestResult.CompletionStatus = "Disabled"; this->TestResult.Status = cmCTestTestHandler::NOT_RUN; - this->TestProcess = cm::make_unique<cmProcess>(*this); this->TestResult.Output = "Disabled"; this->TestResult.FullCommandLine.clear(); return false; @@ -482,7 +511,6 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) // its arguments are irrelevant. This matters for the case where a fixture // dependency might be creating the executable we want to run. if (!this->FailedDependencies.empty()) { - this->TestProcess = cm::make_unique<cmProcess>(*this); std::string msg = "Failed test dependencies:"; for (std::string const& failedDep : this->FailedDependencies) { msg += " " + failedDep; @@ -499,7 +527,6 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) this->ComputeArguments(); std::vector<std::string>& args = this->TestProperties->Args; if (args.size() >= 2 && args[1] == "NOT_AVAILABLE") { - this->TestProcess = cm::make_unique<cmProcess>(*this); std::string msg; if (this->CTest->GetConfigType().empty()) { msg = "Test not available without configuration. (Missing \"-C " @@ -521,7 +548,6 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) for (std::string const& file : this->TestProperties->RequiredFiles) { if (!cmSystemTools::FileExists(file)) { // Required file was not found - this->TestProcess = cm::make_unique<cmProcess>(*this); *this->TestHandler->LogFile << "Unable to find required file: " << file << std::endl; cmCTestLog(this->CTest, ERROR_MESSAGE, @@ -537,7 +563,6 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) if (this->ActualCommand.empty()) { // if the command was not found create a TestResult object // that has that information - this->TestProcess = cm::make_unique<cmProcess>(*this); *this->TestHandler->LogFile << "Unable to find executable: " << args[1] << std::endl; cmCTestLog(this->CTest, ERROR_MESSAGE, @@ -649,7 +674,6 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout, std::vector<std::string>* environment, std::vector<size_t>* affinity) { - this->TestProcess = cm::make_unique<cmProcess>(*this); this->TestProcess->SetId(this->Index); this->TestProcess->SetWorkingDirectory(this->TestProperties->Directory); this->TestProcess->SetCommand(this->ActualCommand); @@ -816,7 +840,8 @@ void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total) "Testing " << this->TestProperties->Name << " ... "); } -void cmCTestRunTest::FinalizeTest() +void cmCTestRunTest::FinalizeTest(bool started) { - this->MultiTestHandler.FinishTestProcess(this, true); + this->MultiTestHandler.FinishTestProcess(this->TestProcess->GetRunner(), + started); } diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index 4988839..b1d188a 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -65,6 +65,15 @@ public: // Read and store output. Returns true if it must be called again. void CheckOutput(std::string const& line); + static bool StartTest(std::unique_ptr<cmCTestRunTest> runner, + size_t completed, size_t total); + static bool StartAgain(std::unique_ptr<cmCTestRunTest> runner, + size_t completed); + + static void StartFailure(std::unique_ptr<cmCTestRunTest> runner, + std::string const& output, + std::string const& detail); + // launch the test process, return whether it started correctly bool StartTest(size_t completed, size_t total); // capture and report the test results @@ -74,8 +83,6 @@ public: void ComputeWeightedCost(); - bool StartAgain(size_t completed); - void StartFailure(std::string const& output, std::string const& detail); cmCTest* GetCTest() const { return this->CTest; } @@ -84,7 +91,7 @@ public: const std::vector<std::string>& GetArguments() { return this->Arguments; } - void FinalizeTest(); + void FinalizeTest(bool started = true); bool TimedOutForStopTime() const { return this->TimeoutIsForStopTime; } diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index a8f201a..22ab48f 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -110,7 +110,7 @@ static size_t cmCTestSubmitHandlerCurlDebugCallback(CURL* /*unused*/, { cm::append(*static_cast<cmCTestSubmitHandlerVectorOfChar*>(data), chPtr, chPtr + size); - return size; + return 0; } cmCTestSubmitHandler::cmCTestSubmitHandler() diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx index 6026c69..452d714 100644 --- a/Source/CTest/cmCTestVC.cxx +++ b/Source/CTest/cmCTestVC.cxx @@ -38,7 +38,7 @@ void cmCTestVC::SetSourceDirectory(std::string const& dir) this->SourceDirectory = dir; } -bool cmCTestVC::InitialCheckout(const char* command) +bool cmCTestVC::InitialCheckout(const std::string& command) { cmCTestLog(this->CTest, HANDLER_OUTPUT, " First perform the initial checkout: " << command << "\n"); diff --git a/Source/CTest/cmCTestVC.h b/Source/CTest/cmCTestVC.h index 2a4765d..3037e01 100644 --- a/Source/CTest/cmCTestVC.h +++ b/Source/CTest/cmCTestVC.h @@ -36,7 +36,7 @@ public: std::string GetNightlyTime(); /** Prepare the work tree. */ - bool InitialCheckout(const char* command); + bool InitialCheckout(const std::string& command); /** Perform cleanup operations on the work tree. */ void Cleanup(); diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index cdf899c..76ffb20 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -5,6 +5,7 @@ #include <csignal> #include <iostream> #include <string> +#include <utility> #include <cmext/algorithm> @@ -18,12 +19,11 @@ #if defined(_WIN32) # include "cm_kwiml.h" #endif -#include <utility> #define CM_PROCESS_BUF_SIZE 65536 -cmProcess::cmProcess(cmCTestRunTest& runner) - : Runner(runner) +cmProcess::cmProcess(std::unique_ptr<cmCTestRunTest> runner) + : Runner(std::move(runner)) , Conv(cmProcessOutput::UTF8, CM_PROCESS_BUF_SIZE) { this->Timeout = cmDuration::zero(); @@ -69,7 +69,7 @@ bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) cm::uv_timer_ptr timer; int status = timer.init(loop, this); if (status != 0) { - cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, + cmCTestLog(this->Runner->GetCTest(), ERROR_MESSAGE, "Error initializing timer: " << uv_strerror(status) << std::endl); return false; @@ -84,7 +84,7 @@ bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) int fds[2] = { -1, -1 }; status = cmGetPipes(fds); if (status != 0) { - cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, + cmCTestLog(this->Runner->GetCTest(), ERROR_MESSAGE, "Error initializing pipe: " << uv_strerror(status) << std::endl); return false; @@ -127,7 +127,7 @@ bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) uv_read_start(pipe_reader, &cmProcess::OnAllocateCB, &cmProcess::OnReadCB); if (status != 0) { - cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, + cmCTestLog(this->Runner->GetCTest(), ERROR_MESSAGE, "Error starting read events: " << uv_strerror(status) << std::endl); return false; @@ -135,7 +135,7 @@ bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) status = this->Process.spawn(loop, options, this); if (status != 0) { - cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, + cmCTestLog(this->Runner->GetCTest(), ERROR_MESSAGE, "Process not started\n " << this->Command << "\n[" << uv_strerror(status) << "]\n"); return false; @@ -152,7 +152,7 @@ bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) void cmProcess::StartTimer() { - auto properties = this->Runner.GetTestProperties(); + auto properties = this->Runner->GetTestProperties(); auto msec = std::chrono::duration_cast<std::chrono::milliseconds>(this->Timeout); @@ -222,7 +222,7 @@ void cmProcess::OnRead(ssize_t nread, const uv_buf_t* buf) cm::append(this->Output, strdata); while (this->Output.GetLine(line)) { - this->Runner.CheckOutput(line); + this->Runner->CheckOutput(line); line.clear(); } @@ -236,20 +236,20 @@ void cmProcess::OnRead(ssize_t nread, const uv_buf_t* buf) // The process will provide no more data. if (nread != UV_EOF) { auto error = static_cast<int>(nread); - cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, + cmCTestLog(this->Runner->GetCTest(), ERROR_MESSAGE, "Error reading stream: " << uv_strerror(error) << std::endl); } // Look for partial last lines. if (this->Output.GetLast(line)) { - this->Runner.CheckOutput(line); + this->Runner->CheckOutput(line); } this->ReadHandleClosed = true; this->PipeReader.reset(); if (this->ProcessHandleClosed) { uv_timer_stop(this->Timer); - this->Runner.FinalizeTest(); + this->Runner->FinalizeTest(); } } @@ -291,7 +291,7 @@ void cmProcess::OnTimeout() // Our on-exit handler already ran but did not finish the test // because we were still reading output. We've just dropped // our read handler, so we need to finish the test now. - this->Runner.FinalizeTest(); + this->Runner->FinalizeTest(); } } @@ -333,7 +333,7 @@ void cmProcess::OnExit(int64_t exit_status, int term_signal) this->ProcessHandleClosed = true; if (this->ReadHandleClosed) { uv_timer_stop(this->Timer); - this->Runner.FinalizeTest(); + this->Runner->FinalizeTest(); } } diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h index 2c24f2d..0f69f68 100644 --- a/Source/CTest/cmProcess.h +++ b/Source/CTest/cmProcess.h @@ -6,7 +6,9 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <chrono> +#include <memory> #include <string> +#include <utility> #include <vector> #include <stddef.h> @@ -28,7 +30,7 @@ class cmCTestRunTest; class cmProcess { public: - explicit cmProcess(cmCTestRunTest& runner); + explicit cmProcess(std::unique_ptr<cmCTestRunTest> runner); ~cmProcess(); void SetCommand(std::string const& command); void SetCommandArguments(std::vector<std::string> const& arg); @@ -70,6 +72,11 @@ public: Exception GetExitException(); std::string GetExitExceptionString(); + std::unique_ptr<cmCTestRunTest> GetRunner() + { + return std::move(this->Runner); + } + private: cmDuration Timeout; std::chrono::steady_clock::time_point StartTime; @@ -82,7 +89,7 @@ private: cm::uv_timer_ptr Timer; std::vector<char> Buf; - cmCTestRunTest& Runner; + std::unique_ptr<cmCTestRunTest> Runner; cmProcessOutput Conv; int Signal = 0; cmProcess::State ProcessState = cmProcess::State::Starting; diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx index 49c9439..b82fb9a 100644 --- a/Source/cmBuildCommand.cxx +++ b/Source/cmBuildCommand.cxx @@ -108,7 +108,7 @@ bool TwoArgsSignature(std::vector<std::string> const& args, if (cacheValue) { return true; } - mf.AddCacheDefinition(define, makecommand.c_str(), + mf.AddCacheDefinition(define, makecommand, "Command used to build entire project " "from the command line.", cmStateEnums::STRING); diff --git a/Source/cmBuildNameCommand.cxx b/Source/cmBuildNameCommand.cxx index 3e517dc..ad4d665 100644 --- a/Source/cmBuildNameCommand.cxx +++ b/Source/cmBuildNameCommand.cxx @@ -28,7 +28,7 @@ bool cmBuildNameCommand(std::vector<std::string> const& args, std::replace(cv.begin(), cv.end(), '/', '_'); std::replace(cv.begin(), cv.end(), '(', '_'); std::replace(cv.begin(), cv.end(), ')', '_'); - mf.AddCacheDefinition(args[0], cv.c_str(), "Name of build.", + mf.AddCacheDefinition(args[0], cv, "Name of build.", cmStateEnums::STRING); } return true; @@ -54,7 +54,7 @@ bool cmBuildNameCommand(std::vector<std::string> const& args, std::replace(buildname.begin(), buildname.end(), '(', '_'); std::replace(buildname.begin(), buildname.end(), ')', '_'); - mf.AddCacheDefinition(args[0], buildname.c_str(), "Name of build.", + mf.AddCacheDefinition(args[0], buildname, "Name of build.", cmStateEnums::STRING); return true; } diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index f6c1e47..874efa5 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -585,7 +585,8 @@ const char* CCONV cmSourceFileGetProperty(void* arg, const char* prop) if (!strcmp(prop, "LOCATION")) { return sf->FullPath.c_str(); } - return sf->Properties.GetPropertyValue(prop); + cmProp retVal = sf->Properties.GetPropertyValue(prop); + return retVal ? retVal->c_str() : nullptr; } int CCONV cmSourceFileGetPropertyAsBool(void* arg, const char* prop) @@ -775,8 +776,9 @@ void CCONV DefineSourceFileProperty(void* arg, const char* name, const char* longDocs, int chained) { cmMakefile* mf = static_cast<cmMakefile*>(arg); - mf->GetState()->DefineProperty(name, cmProperty::SOURCE_FILE, briefDocs, - longDocs, chained != 0); + mf->GetState()->DefineProperty(name, cmProperty::SOURCE_FILE, + briefDocs ? briefDocs : "", + longDocs ? longDocs : "", chained != 0); } } // close the extern "C" scope diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index dc9aba1..ee89b0d 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -628,7 +628,8 @@ const char* cmCacheManager::CacheEntry::GetProperty( if (prop == "VALUE") { return this->Value.c_str(); } - return this->Properties.GetPropertyValue(prop); + cmProp retVal = this->Properties.GetPropertyValue(prop); + return retVal ? retVal->c_str() : nullptr; } void cmCacheManager::CacheEntry::SetProperty(const std::string& prop, diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 5ff6f8c..033cb60 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -248,7 +248,7 @@ void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags, int major; int minor; int patch; - std::string prop = cmStrCat("OSX_", name, "_VERSION"); + std::string prop = cmStrCat("MACHO_", name, "_VERSION"); std::string fallback_prop = so ? "SOVERSION" : "VERSION"; this->GeneratorTarget->GetTargetVersionFallback(prop, fallback_prop, major, minor, patch); diff --git a/Source/cmDefinePropertyCommand.cxx b/Source/cmDefinePropertyCommand.cxx index f4e4fda..4e2d9b0 100644 --- a/Source/cmDefinePropertyCommand.cxx +++ b/Source/cmDefinePropertyCommand.cxx @@ -95,7 +95,7 @@ bool cmDefinePropertyCommand(std::vector<std::string> const& args, // Actually define the property. status.GetMakefile().GetState()->DefineProperty( - PropertyName, scope, BriefDocs.c_str(), FullDocs.c_str(), inherited); + PropertyName, scope, BriefDocs, FullDocs, inherited); return true; } diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 6441e6f..003019a 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -1116,7 +1116,7 @@ void cmExportFileGenerator::GenerateMissingTargetsCheckCode( return; } /* clang-format off */ - os << "# Make sure the targets which have been exported in some other \n" + os << "# Make sure the targets which have been exported in some other\n" "# export set exist.\n" "unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n" "foreach(_target "; @@ -1215,9 +1215,9 @@ bool cmExportFileGenerator::PopulateExportProperties( std::string& errorMessage) { auto& targetProperties = gte->Target->GetProperties(); - if (const char* exportProperties = + if (cmProp exportProperties = targetProperties.GetPropertyValue("EXPORT_PROPERTIES")) { - for (auto& prop : cmExpandedList(exportProperties)) { + for (auto& prop : cmExpandedList(*exportProperties)) { /* Black list reserved properties */ if (cmHasLiteralPrefix(prop, "IMPORTED_") || cmHasLiteralPrefix(prop, "INTERFACE_")) { @@ -1228,15 +1228,15 @@ bool cmExportFileGenerator::PopulateExportProperties( errorMessage = e.str(); return false; } - auto propertyValue = targetProperties.GetPropertyValue(prop); + cmProp propertyValue = targetProperties.GetPropertyValue(prop); if (propertyValue == nullptr) { // Asked to export a property that isn't defined on the target. Do not // consider this an error, there's just nothing to export. continue; } std::string evaluatedValue = cmGeneratorExpression::Preprocess( - propertyValue, cmGeneratorExpression::StripAllGeneratorExpressions); - if (evaluatedValue != propertyValue) { + *propertyValue, cmGeneratorExpression::StripAllGeneratorExpressions); + if (evaluatedValue != *propertyValue) { std::ostringstream e; e << "Target \"" << gte->Target->GetName() << "\" contains property \"" << prop << "\" in EXPORT_PROPERTIES but this property contains a " @@ -1244,7 +1244,7 @@ bool cmExportFileGenerator::PopulateExportProperties( errorMessage = e.str(); return false; } - properties[prop] = propertyValue; + properties[prop] = *propertyValue; } } return true; diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index 78cabce..8ab30c0 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -255,8 +255,8 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, // The variable is in the env, but not in the cache. Use it and put it // in the cache valueToUse = envVarValue; - mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(), - cacheEntryName.c_str(), cmStateEnums::STRING, true); + mf->AddCacheDefinition(cacheEntryName, valueToUse, cacheEntryName.c_str(), + cmStateEnums::STRING, true); mf->GetCMakeInstance()->SaveCache(lg.GetBinaryDirectory()); } else if (!envVarSet && cacheValue != nullptr) { // It is already in the cache, but not in the env, so use it from the cache @@ -270,7 +270,7 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out, valueToUse = *cacheValue; if (valueToUse.find(envVarValue) == std::string::npos) { valueToUse = envVarValue; - mf->AddCacheDefinition(cacheEntryName, valueToUse.c_str(), + mf->AddCacheDefinition(cacheEntryName, valueToUse, cacheEntryName.c_str(), cmStateEnums::STRING, true); mf->GetCMakeInstance()->SaveCache(lg.GetBinaryDirectory()); diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 3b532c8..8b450d0 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -8,6 +8,7 @@ #include <cmath> #include <cstdio> #include <cstdlib> +#include <iterator> #include <map> #include <set> #include <sstream> @@ -49,6 +50,7 @@ #include "cmSubcommandTable.h" #include "cmSystemTools.h" #include "cmTimestamp.h" +#include "cmWorkingDirectory.h" #include "cmake.h" #if !defined(CMAKE_BOOTSTRAP) @@ -2893,6 +2895,210 @@ bool HandleConfigureCommand(std::vector<std::string> const& args, return true; } +bool HandleArchiveCreateCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + struct Arguments + { + std::string Output; + std::string Format; + std::string Type; + std::string MTime; + bool Verbose = false; + std::vector<std::string> Files; + std::vector<std::string> Directories; + }; + + static auto const parser = cmArgumentParser<Arguments>{} + .Bind("OUTPUT"_s, &Arguments::Output) + .Bind("FORMAT"_s, &Arguments::Format) + .Bind("TYPE"_s, &Arguments::Type) + .Bind("MTIME"_s, &Arguments::MTime) + .Bind("VERBOSE"_s, &Arguments::Verbose) + .Bind("FILES"_s, &Arguments::Files) + .Bind("DIRECTORY"_s, &Arguments::Directories); + + 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()) { + status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\"")); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + const std::vector<std::string> LIST_ARGS = { + "OUTPUT", "FORMAT", "TYPE", "MTIME", "FILES", "DIRECTORY", + }; + auto kwbegin = keywordsMissingValues.cbegin(); + auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS); + if (kwend != kwbegin) { + status.SetError(cmStrCat("Keywords missing values:\n ", + cmJoin(cmMakeRange(kwbegin, kwend), "\n "))); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + const char* knownFormats[] = { + "7zip", "gnutar", "pax", "paxr", "raw", "zip" + }; + + if (!parsedArgs.Format.empty() && + !cmContains(knownFormats, parsedArgs.Format)) { + status.SetError( + cmStrCat("archive format ", parsedArgs.Format, " not supported")); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + const char* zipFileFormats[] = { "7zip", "zip" }; + if (!parsedArgs.Type.empty() && + cmContains(zipFileFormats, parsedArgs.Format)) { + status.SetError(cmStrCat("archive format ", parsedArgs.Format, + " does not support TYPE arguments")); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + static std::map<std::string, cmSystemTools::cmTarCompression> + compressionTypeMap = { { "None", cmSystemTools::TarCompressNone }, + { "BZip2", cmSystemTools::TarCompressBZip2 }, + { "GZip", cmSystemTools::TarCompressGZip }, + { "XZ", cmSystemTools::TarCompressXZ }, + { "Zstd", cmSystemTools::TarCompressZstd } }; + + std::string const& outFile = parsedArgs.Output; + std::vector<std::string> files = parsedArgs.Files; + std::copy(parsedArgs.Directories.begin(), parsedArgs.Directories.end(), + std::back_inserter(files)); + + cmSystemTools::cmTarCompression compress = cmSystemTools::TarCompressNone; + auto typeIt = compressionTypeMap.find(parsedArgs.Type); + if (typeIt != compressionTypeMap.end()) { + compress = typeIt->second; + } else if (!parsedArgs.Type.empty()) { + status.SetError( + cmStrCat("compression type ", parsedArgs.Type, " is not supported")); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + if (files.empty()) { + status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, + "No files or directories specified"); + } + + if (!cmSystemTools::CreateTar(outFile, files, compress, parsedArgs.Verbose, + parsedArgs.MTime, parsedArgs.Format)) { + status.SetError(cmStrCat("failed to compress: ", outFile)); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + return true; +} + +bool HandleArchiveExtractCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + struct Arguments + { + std::string Input; + bool Verbose = false; + bool ListOnly = false; + std::string Destination; + std::vector<std::string> Files; + std::vector<std::string> Directories; + }; + + static auto const parser = cmArgumentParser<Arguments>{} + .Bind("INPUT"_s, &Arguments::Input) + .Bind("VERBOSE"_s, &Arguments::Verbose) + .Bind("LIST_ONLY"_s, &Arguments::ListOnly) + .Bind("DESTINATION"_s, &Arguments::Destination) + .Bind("FILES"_s, &Arguments::Files) + .Bind("DIRECTORY"_s, &Arguments::Directories); + + 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()) { + status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\"")); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + const std::vector<std::string> LIST_ARGS = { + "INPUT", + "DESTINATION", + "FILES", + "DIRECTORY", + }; + auto kwbegin = keywordsMissingValues.cbegin(); + auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS); + if (kwend != kwbegin) { + status.SetError(cmStrCat("Keywords missing values:\n ", + cmJoin(cmMakeRange(kwbegin, kwend), "\n "))); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + std::string inFile = parsedArgs.Input; + std::vector<std::string> files = parsedArgs.Files; + std::copy(parsedArgs.Directories.begin(), parsedArgs.Directories.end(), + std::back_inserter(files)); + + if (parsedArgs.ListOnly) { + if (!cmSystemTools::ListTar(inFile, files, parsedArgs.Verbose)) { + status.SetError(cmStrCat("failed to list: ", inFile)); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + } else { + std::string destDir = cmSystemTools::GetCurrentWorkingDirectory(); + if (!parsedArgs.Destination.empty()) { + if (cmSystemTools::FileIsFullPath(parsedArgs.Destination)) { + destDir = parsedArgs.Destination; + } else { + destDir = cmStrCat(destDir, "/", parsedArgs.Destination); + } + + if (!cmSystemTools::MakeDirectory(destDir)) { + status.SetError(cmStrCat("failed to create directory: ", destDir)); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + if (!cmSystemTools::FileIsFullPath(inFile)) { + inFile = + cmStrCat(cmSystemTools::GetCurrentWorkingDirectory(), "/", inFile); + } + } + + cmWorkingDirectory workdir(destDir); + if (workdir.Failed()) { + status.SetError( + cmStrCat("failed to change working directory to: ", destDir)); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + + if (!cmSystemTools::ExtractTar(inFile, files, parsedArgs.Verbose)) { + status.SetError(cmStrCat("failed to extract: ", inFile)); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + } + + return true; +} + } // namespace bool cmFileCommand(std::vector<std::string> const& args, @@ -2947,6 +3153,8 @@ bool cmFileCommand(std::vector<std::string> const& args, { "CREATE_LINK"_s, HandleCreateLinkCommand }, { "GET_RUNTIME_DEPENDENCIES"_s, HandleGetRuntimeDependenciesCommand }, { "CONFIGURE"_s, HandleConfigureCommand }, + { "ARCHIVE_CREATE"_s, HandleArchiveCreateCommand }, + { "ARCHIVE_EXTRACT"_s, HandleArchiveExtractCommand }, }; return subcommand(args[0], args, status); diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 6f9f7a2..31f1201 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -76,13 +76,13 @@ bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn) std::string const library = this->FindLibrary(); if (!library.empty()) { // Save the value in the cache - this->Makefile->AddCacheDefinition(this->VariableName, library.c_str(), + this->Makefile->AddCacheDefinition(this->VariableName, library, this->VariableDocumentation.c_str(), cmStateEnums::FILEPATH); return true; } std::string notfound = this->VariableName + "-NOTFOUND"; - this->Makefile->AddCacheDefinition(this->VariableName, notfound.c_str(), + this->Makefile->AddCacheDefinition(this->VariableName, notfound, this->VariableDocumentation.c_str(), cmStateEnums::FILEPATH); if (this->Required) { diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 297c72b..f606002 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -1060,8 +1060,8 @@ bool cmFindPackageCommand::FindConfig() 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); + this->Makefile->AddCacheDefinition(this->Variable, init, help.c_str(), + cmStateEnums::PATH, true); return found; } diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx index f5b52c2..4bab469 100644 --- a/Source/cmFindPathCommand.cxx +++ b/Source/cmFindPathCommand.cxx @@ -44,12 +44,12 @@ bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn) std::string result = this->FindHeader(); if (!result.empty()) { this->Makefile->AddCacheDefinition( - this->VariableName, result.c_str(), this->VariableDocumentation.c_str(), + this->VariableName, result, this->VariableDocumentation.c_str(), (this->IncludeFileInPath) ? cmStateEnums::FILEPATH : cmStateEnums::PATH); return true; } this->Makefile->AddCacheDefinition( - this->VariableName, (this->VariableName + "-NOTFOUND").c_str(), + this->VariableName, this->VariableName + "-NOTFOUND", this->VariableDocumentation.c_str(), (this->IncludeFileInPath) ? cmStateEnums::FILEPATH : cmStateEnums::PATH); if (this->Required) { diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index cbc3c78..4b88bea 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -128,14 +128,14 @@ bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn) std::string const result = FindProgram(); if (!result.empty()) { // Save the value in the cache - this->Makefile->AddCacheDefinition(this->VariableName, result.c_str(), + this->Makefile->AddCacheDefinition(this->VariableName, result, this->VariableDocumentation.c_str(), cmStateEnums::FILEPATH); return true; } this->Makefile->AddCacheDefinition( - this->VariableName, (this->VariableName + "-NOTFOUND").c_str(), + this->VariableName, this->VariableName + "-NOTFOUND", this->VariableDocumentation.c_str(), cmStateEnums::FILEPATH); if (this->Required) { this->Makefile->IssueMessage( diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index ad142d7..af45893 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -52,11 +52,11 @@ class cmMessenger; template <> -const char* cmTargetPropertyComputer::GetSources<cmGeneratorTarget>( +cmProp cmTargetPropertyComputer::GetSources<cmGeneratorTarget>( cmGeneratorTarget const* tgt, cmMessenger* /* messenger */, cmListFileBacktrace const& /* context */) { - return tgt->GetSourcesProperty().c_str(); + return &tgt->GetSourcesProperty(); } template <> @@ -376,9 +376,9 @@ const char* cmGeneratorTarget::GetProperty(const std::string& prop) const this->GetBacktrace())) { return nullptr; } - if (const char* result = cmTargetPropertyComputer::GetProperty( + if (cmProp result = cmTargetPropertyComputer::GetProperty( this, prop, this->Makefile->GetMessenger(), this->GetBacktrace())) { - return result; + return result->c_str(); } if (cmSystemTools::GetFatalErrorOccured()) { return nullptr; @@ -1282,6 +1282,86 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty( } namespace { +std::string AddSwiftInterfaceIncludeDirectories( + const cmGeneratorTarget* root, const cmGeneratorTarget* target, + const std::string& config, cmGeneratorExpressionDAGChecker* context) +{ + cmGeneratorExpressionDAGChecker dag{ target->GetBacktrace(), target, + "Swift_MODULE_DIRECTORY", nullptr, + context }; + switch (dag.Check()) { + case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: + dag.ReportError(nullptr, + "$<TARGET_PROPERTY:" + target->GetName() + + ",Swift_MODULE_DIRECTORY>"); + return ""; + case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: + // No error. We just skip cyclic references. + return ""; + case cmGeneratorExpressionDAGChecker::ALREADY_SEEN: + // No error. We have already seen this transitive property. + return ""; + case cmGeneratorExpressionDAGChecker::DAG: + break; + } + + std::string directories; + if (const auto* interface = + target->GetLinkInterfaceLibraries(config, root, true)) { + for (const cmLinkItem& library : interface->Libraries) { + if (const cmGeneratorTarget* dependency = library.Target) { + if (cmContains(dependency->GetAllConfigCompileLanguages(), "Swift")) { + std::string value = + dependency->GetSafeProperty("Swift_MODULE_DIRECTORY"); + if (value.empty()) { + value = + dependency->GetLocalGenerator()->GetCurrentBinaryDirectory(); + } + + if (!directories.empty()) { + directories += ";"; + } + directories += value; + } + } + } + } + return directories; +} + +void AddSwiftImplicitIncludeDirectories( + const cmGeneratorTarget* target, const std::string& config, + std::vector<EvaluatedTargetPropertyEntry>& entries) +{ + if (const auto* libraries = target->GetLinkImplementationLibraries(config)) { + cmGeneratorExpressionDAGChecker dag{ target->GetBacktrace(), target, + "Swift_MODULE_DIRECTORY", nullptr, + nullptr }; + + for (const cmLinkImplItem& library : libraries->Libraries) { + if (const cmGeneratorTarget* dependency = library.Target) { + if (cmContains(dependency->GetAllConfigCompileLanguages(), "Swift")) { + EvaluatedTargetPropertyEntry entry{ library, library.Backtrace }; + + if (const char* val = + dependency->GetProperty("Swift_MODULE_DIRECTORY")) { + entry.Values.emplace_back(val); + } else { + entry.Values.emplace_back( + dependency->GetLocalGenerator()->GetCurrentBinaryDirectory()); + } + + cmExpandList(AddSwiftInterfaceIncludeDirectories(target, dependency, + config, &dag), + entry.Values); + + entries.emplace_back(std::move(entry)); + } + } + } + } +} + void AddInterfaceEntries(cmGeneratorTarget const* headTarget, std::string const& config, std::string const& prop, std::string const& lang, @@ -3177,6 +3257,10 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( EvaluateTargetPropertyEntries(this, config, lang, &dagChecker, this->IncludeDirectoriesEntries); + if (lang == "Swift") { + AddSwiftImplicitIncludeDirectories(this, config, entries); + } + AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES", lang, &dagChecker, entries); diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx index 7d91a75..811421a 100644 --- a/Source/cmGetFilenameComponentCommand.cxx +++ b/Source/cmGetFilenameComponentCommand.cxx @@ -120,11 +120,11 @@ bool cmGetFilenameComponentCommand(std::vector<std::string> const& args, if (args.size() >= 4 && args.back() == "CACHE") { if (!programArgs.empty() && !storeArgs.empty()) { status.GetMakefile().AddCacheDefinition( - storeArgs, programArgs.c_str(), "", + storeArgs, programArgs, "", args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING); } status.GetMakefile().AddCacheDefinition( - args.front(), result.c_str(), "", + args.front(), result, "", args[2] == "PATH" ? cmStateEnums::FILEPATH : cmStateEnums::STRING); } else { if (!programArgs.empty() && !storeArgs.empty()) { diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 5e2248e..6470ea1 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -180,15 +180,12 @@ void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config, auto i = this->FlagsByLanguage.find(language); if (i == this->FlagsByLanguage.end()) { std::string flags; - const char* lang = language.c_str(); - - this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, lang, - config); - - this->LocalGenerator->AddCMP0018Flags(flags, this->GeneratorTarget, lang, - config); + this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, + language, config); + this->LocalGenerator->AddCMP0018Flags(flags, this->GeneratorTarget, + language, config); this->LocalGenerator->AddVisibilityPresetFlags( - flags, this->GeneratorTarget, lang); + flags, this->GeneratorTarget, language); // Append old-style preprocessor definition flags. if (this->Makefile->GetDefineFlags() != " ") { @@ -197,8 +194,8 @@ void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config, } // Add target-specific flags. - this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, lang, - config); + this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, + language, config); std::map<std::string, std::string>::value_type entry(language, flags); i = this->FlagsByLanguage.insert(entry).first; @@ -211,13 +208,12 @@ std::string cmGhsMultiTargetGenerator::GetDefines(const std::string& language, auto i = this->DefinesByLanguage.find(language); if (i == this->DefinesByLanguage.end()) { std::set<std::string> defines; - const char* lang = language.c_str(); // Add preprocessor definitions for this target and configuration. this->LocalGenerator->GetTargetDefines(this->GeneratorTarget, config, language, defines); std::string definesString; - this->LocalGenerator->JoinDefines(defines, definesString, lang); + this->LocalGenerator->JoinDefines(defines, definesString, language); std::map<std::string, std::string>::value_type entry(language, definesString); @@ -235,7 +231,7 @@ void cmGhsMultiTargetGenerator::WriteCompilerFlags(std::ostream& fout, if (!flagsByLangI->second.empty()) { std::vector<std::string> ghsCompFlags = cmSystemTools::ParseArguments(flagsByLangI->second); - for (auto& f : ghsCompFlags) { + for (const std::string& f : ghsCompFlags) { fout << " " << f << std::endl; } } @@ -290,14 +286,14 @@ void cmGhsMultiTargetGenerator::WriteTargetLinkLine(std::ostream& fout, // write out link options std::vector<std::string> lopts = cmSystemTools::ParseArguments(linkFlags); - for (auto& l : lopts) { + for (const std::string& l : lopts) { fout << " " << l << std::endl; } // write out link search paths // must be quoted for paths that contain spaces std::vector<std::string> lpath = cmSystemTools::ParseArguments(linkPath); - for (auto& l : lpath) { + for (const std::string& l : lpath) { fout << " -L\"" << l << "\"" << std::endl; } @@ -307,7 +303,7 @@ void cmGhsMultiTargetGenerator::WriteTargetLinkLine(std::ostream& fout, std::vector<std::string> llibs = cmSystemTools::ParseArguments(linkLibraries); - for (auto& l : llibs) { + for (const std::string& l : llibs) { if (l.compare(0, 2, "-l") == 0) { fout << " \"" << l << "\"" << std::endl; } else { @@ -463,7 +459,7 @@ void cmGhsMultiTargetGenerator::WriteSourceProperty( const char* prop = sf->GetProperty(propName); if (prop) { std::vector<std::string> list = cmExpandedList(prop); - for (auto& p : list) { + for (const std::string& p : list) { fout << " " << propFlag << p << std::endl; } } @@ -483,7 +479,7 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj) /* for each source file assign it to its group */ std::map<std::string, std::vector<cmSourceFile*>> groupFiles; std::set<std::string> groupNames; - for (auto& sf : sources) { + for (cmSourceFile* sf : sources) { cmSourceGroup* sourceGroup = this->Makefile->FindSourceGroup(sf->ResolveFullPath(), sourceGroups); std::string gn = sourceGroup->GetFullName(); @@ -730,7 +726,7 @@ bool cmGhsMultiTargetGenerator::DetermineIfIntegrityApp() } std::vector<cmSourceFile*> sources; this->GeneratorTarget->GetSourceFiles(sources, this->ConfigName); - for (auto& sf : sources) { + for (const cmSourceFile* sf : sources) { if ("int" == sf->GetExtension()) { return true; } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 0404715..0b9a3e5 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -446,8 +446,8 @@ bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf) cmSystemTools::GetShortPath(makeProgram, makeProgram); cmSystemTools::SplitProgramPath(makeProgram, dir, file); makeProgram = cmStrCat(dir, '/', saveFile); - mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram.c_str(), - "make program", cmStateEnums::FILEPATH); + mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram, "make program", + cmStateEnums::FILEPATH); } return true; } diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index bb9dd37..9754fd5 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -9,6 +9,7 @@ #include <utility> #include <cm/memory> +#include <cm/string> #include "cmAlgorithms.h" #include "cmDocumentationEntry.h" @@ -90,7 +91,7 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, /* store the full toolset for later use * -- already done if -T<toolset> was specified */ - mf->AddCacheDefinition("CMAKE_GENERATOR_TOOLSET", tsp.c_str(), + mf->AddCacheDefinition("CMAKE_GENERATOR_TOOLSET", tsp, "Location of generator toolset.", cmStateEnums::INTERNAL); } @@ -112,8 +113,8 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts, } /* store the toolset that is being used for this build */ - mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", gbuild.c_str(), - "build program to use", cmStateEnums::INTERNAL, true); + mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", gbuild, "build program to use", + cmStateEnums::INTERNAL, true); mf->AddDefinition("CMAKE_SYSTEM_VERSION", tsp); @@ -132,7 +133,7 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p, /* store the platform name for later use * -- already done if -A<arch> was specified */ - mf->AddCacheDefinition("CMAKE_GENERATOR_PLATFORM", arch.c_str(), + mf->AddCacheDefinition("CMAKE_GENERATOR_PLATFORM", arch, "Name of generator platform.", cmStateEnums::INTERNAL); } else { @@ -166,7 +167,7 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p, 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(), + mf->AddCacheDefinition("GHS_BSP_NAME", bspName, "Name of GHS target platform.", cmStateEnums::STRING, true); std::string m = cmStrCat( @@ -651,21 +652,16 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives( char const* const customization = this->GetCMakeInstance()->GetCacheDefinition("GHS_CUSTOMIZATION"); if (nullptr != customization && strlen(customization) > 0) { - fout << "customization=" << this->TrimQuotes(customization) << std::endl; + fout << "customization=" + << cmGlobalGhsMultiGenerator::TrimQuotes(customization) << std::endl; this->GetCMakeInstance()->MarkCliAsUsed("GHS_CUSTOMIZATION"); } } -std::string cmGlobalGhsMultiGenerator::TrimQuotes(std::string const& str) +std::string cmGlobalGhsMultiGenerator::TrimQuotes(std::string str) { - std::string result; - result.reserve(str.size()); - for (const char* ch = str.c_str(); *ch != '\0'; ++ch) { - if (*ch != '"') { - result += *ch; - } - } - return result; + cm::erase(str, '"'); + return str; } bool cmGlobalGhsMultiGenerator::TargetCompare::operator()( diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index b82e9f5..12ca8b6 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -111,7 +111,7 @@ private: std::vector<cmLocalGenerator*>& generators, std::string& all_target); - std::string TrimQuotes(std::string const& str); + static std::string TrimQuotes(std::string str); std::string OsDir; static const char* DEFAULT_BUILD_PROGRAM; diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index eb33825..43d31bc 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -128,7 +128,7 @@ void cmGlobalVisualStudio7Generator::EnableLanguage( // does not know about. std::string extraPath; if (cmSystemTools::GetEnv("CMAKE_MSVCIDE_RUN_PATH", extraPath)) { - mf->AddCacheDefinition("CMAKE_MSVCIDE_RUN_PATH", extraPath.c_str(), + mf->AddCacheDefinition("CMAKE_MSVCIDE_RUN_PATH", extraPath, "Saved environment variable CMAKE_MSVCIDE_RUN_PATH", cmStateEnums::STATIC); } diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index ac7d204..9db4817 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -2369,8 +2369,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, int minor; int patch; - // OSX_CURRENT_VERSION or VERSION -> current_version - gtgt->GetTargetVersionFallback("OSX_CURRENT_VERSION", "VERSION", major, + // MACHO_CURRENT_VERSION or VERSION -> current_version + gtgt->GetTargetVersionFallback("MACHO_CURRENT_VERSION", "VERSION", major, minor, patch); std::ostringstream v; @@ -2381,8 +2381,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, buildSettings->AddAttribute("DYLIB_CURRENT_VERSION", this->CreateString(v.str())); - // OSX_COMPATIBILITY_VERSION or SOVERSION -> compatibility_version - gtgt->GetTargetVersionFallback("OSX_COMPATIBILITY_VERSION", "SOVERSION", + // MACHO_COMPATIBILITY_VERSION or SOVERSION -> compatibility_version + gtgt->GetTargetVersionFallback("MACHO_COMPATIBILITY_VERSION", "SOVERSION", major, minor, patch); std::ostringstream vso; diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx index 8972a63..32395d1 100644 --- a/Source/cmInstalledFile.cxx +++ b/Source/cmInstalledFile.cxx @@ -42,7 +42,8 @@ void cmInstalledFile::RemoveProperty(const std::string& prop) } void cmInstalledFile::SetProperty(cmMakefile const* mf, - const std::string& prop, const char* value) + const std::string& prop, + const std::string& value) { this->RemoveProperty(prop); this->AppendProperty(mf, prop, value); @@ -50,13 +51,14 @@ void cmInstalledFile::SetProperty(cmMakefile const* mf, void cmInstalledFile::AppendProperty(cmMakefile const* mf, const std::string& prop, - const char* value, bool /*asString*/) + const std::string& value, + bool /*asString*/) { cmListFileBacktrace backtrace = mf->GetBacktrace(); cmGeneratorExpression ge(backtrace); Property& property = this->Properties[prop]; - property.ValueExpressions.push_back(ge.Parse(value ? value : "")); + property.ValueExpressions.push_back(ge.Parse(value)); } bool cmInstalledFile::HasProperty(const std::string& prop) const diff --git a/Source/cmInstalledFile.h b/Source/cmInstalledFile.h index 698151e..07f7081 100644 --- a/Source/cmInstalledFile.h +++ b/Source/cmInstalledFile.h @@ -49,10 +49,10 @@ public: void RemoveProperty(const std::string& prop); void SetProperty(cmMakefile const* mf, const std::string& prop, - const char* value); + const std::string& value); void AppendProperty(cmMakefile const* mf, const std::string& prop, - const char* value, bool asString = false); + const std::string& value, bool asString = false); bool HasProperty(const std::string& prop) const; diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index 86ee953..480c005 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -156,9 +156,11 @@ void cmLinkLineComputer::ComputeLinkPath( type = cmStateEnums::ImportLibraryArtifact; } - linkPathNoBT += cmStrCat( - " ", libPathFlag, item.Target->GetDirectory(cli.GetConfig(), type), - libPathTerminator, " "); + linkPathNoBT += + cmStrCat(" ", libPathFlag, + this->ConvertToOutputForExisting( + item.Target->GetDirectory(cli.GetConfig(), type)), + libPathTerminator, " "); } } diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index cf6802d..a7799b6 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2914,11 +2914,11 @@ void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines, // command line without any escapes. However we still have to // get the '$' and '#' characters through WMake as '$$' and // '$#'. - for (const char* c = define.c_str(); *c; ++c) { - if (*c == '$' || *c == '#') { + for (char c : define) { + if (c == '$' || c == '#') { def += '$'; } - def += *c; + def += c; } } else { // Make the definition appear properly on the command line. Use diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 0572e07..74219b5 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1510,10 +1510,9 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( if (const char* deps = sf.GetProperty("OBJECT_DEPENDS")) { std::vector<std::string> depends = cmExpandedList(deps); const char* sep = ""; - for (std::vector<std::string>::iterator j = depends.begin(); - j != depends.end(); ++j) { + for (const std::string& d : depends) { fc.AdditionalDeps += sep; - fc.AdditionalDeps += lg->ConvertToXMLOutputPath(*j); + fc.AdditionalDeps += lg->ConvertToXMLOutputPath(d); sep = ";"; needfc = true; } diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 94d99b7..76c559f 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -60,6 +60,7 @@ #include "cmake.h" #ifndef CMAKE_BOOTSTRAP +# include "cmMakefileProfilingData.h" # include "cmVariableWatch.h" #endif @@ -372,19 +373,30 @@ void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const class cmMakefileCall { public: - cmMakefileCall(cmMakefile* mf, cmCommandContext const& cc, + cmMakefileCall(cmMakefile* mf, cmListFileFunction const& lff, cmExecutionStatus& status) : Makefile(mf) { cmListFileContext const& lfc = cmListFileContext::FromCommandContext( - cc, this->Makefile->StateSnapshot.GetExecutionListFile()); + lff, this->Makefile->StateSnapshot.GetExecutionListFile()); this->Makefile->Backtrace = this->Makefile->Backtrace.Push(lfc); ++this->Makefile->RecursionDepth; this->Makefile->ExecutionStatusStack.push_back(&status); +#if !defined(CMAKE_BOOTSTRAP) + if (this->Makefile->GetCMakeInstance()->IsProfilingEnabled()) { + this->Makefile->GetCMakeInstance()->GetProfilingOutput().StartEntry(lff, + lfc); + } +#endif } ~cmMakefileCall() { +#if !defined(CMAKE_BOOTSTRAP) + if (this->Makefile->GetCMakeInstance()->IsProfilingEnabled()) { + this->Makefile->GetCMakeInstance()->GetProfilingOutput().StopEntry(); + } +#endif this->Makefile->ExecutionStatusStack.pop_back(); --this->Makefile->RecursionDepth; this->Makefile->Backtrace = this->Makefile->Backtrace.Pop(); diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 9c6dca6..081e69d 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -317,6 +317,12 @@ public: void AddCacheDefinition(const std::string& name, const char* value, const char* doc, cmStateEnums::CacheEntryType type, bool force = false); + void AddCacheDefinition(const std::string& name, const std::string& value, + const char* doc, cmStateEnums::CacheEntryType type, + bool force = false) + { + AddCacheDefinition(name, value.c_str(), doc, type, force); + } /** * Remove a variable definition from the build. This is not valid diff --git a/Source/cmMakefileProfilingData.cxx b/Source/cmMakefileProfilingData.cxx new file mode 100644 index 0000000..adf4eee --- /dev/null +++ b/Source/cmMakefileProfilingData.cxx @@ -0,0 +1,114 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmMakefileProfilingData.h" + +#include <chrono> +#include <stdexcept> +#include <vector> + +#include "cmsys/FStream.hxx" +#include "cmsys/SystemInformation.hxx" + +#include "cm_jsoncpp_value.h" +#include "cm_jsoncpp_writer.h" + +#include "cmListFileCache.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" + +cmMakefileProfilingData::cmMakefileProfilingData( + const std::string& profileStream) +{ + std::ios::openmode omode = std::ios::out | std::ios::trunc; + this->ProfileStream.open(profileStream.c_str(), omode); + Json::StreamWriterBuilder wbuilder; + this->JsonWriter = + std::unique_ptr<Json::StreamWriter>(wbuilder.newStreamWriter()); + if (!this->ProfileStream.good()) { + throw std::runtime_error(std::string("Unable to open: ") + profileStream); + } + + this->ProfileStream << "["; +}; + +cmMakefileProfilingData::~cmMakefileProfilingData() noexcept +{ + if (this->ProfileStream.good()) { + try { + this->ProfileStream << "]"; + this->ProfileStream.close(); + } catch (...) { + cmSystemTools::Error("Error writing profiling output!"); + } + } +} + +void cmMakefileProfilingData::StartEntry(const cmListFileFunction& lff, + cmListFileContext const& lfc) +{ + /* Do not try again if we previously failed to write to output. */ + if (!this->ProfileStream.good()) { + return; + } + + try { + if (this->ProfileStream.tellp() > 1) { + this->ProfileStream << ","; + } + cmsys::SystemInformation info; + Json::Value v; + v["ph"] = "B"; + v["name"] = lff.Name.Original; + v["cat"] = "cmake"; + v["ts"] = Json::Value::UInt64( + std::chrono::duration_cast<std::chrono::microseconds>( + std::chrono::steady_clock::now().time_since_epoch()) + .count()); + v["pid"] = static_cast<int>(info.GetProcessId()); + v["tid"] = 0; + Json::Value argsValue; + if (!lff.Arguments.empty()) { + std::string args; + for (const auto& a : lff.Arguments) { + args += (args.empty() ? "" : " ") + a.Value; + } + argsValue["functionArgs"] = args; + } + argsValue["location"] = lfc.FilePath + ":" + std::to_string(lfc.Line); + v["args"] = argsValue; + + this->JsonWriter->write(v, &this->ProfileStream); + } catch (std::ios_base::failure& fail) { + cmSystemTools::Error( + cmStrCat("Failed to write to profiling output: ", fail.what())); + } catch (...) { + cmSystemTools::Error("Error writing profiling output!"); + } +} + +void cmMakefileProfilingData::StopEntry() +{ + /* Do not try again if we previously failed to write to output. */ + if (!this->ProfileStream.good()) { + return; + } + + try { + this->ProfileStream << ","; + cmsys::SystemInformation info; + Json::Value v; + v["ph"] = "E"; + v["ts"] = Json::Value::UInt64( + std::chrono::duration_cast<std::chrono::microseconds>( + std::chrono::steady_clock::now().time_since_epoch()) + .count()); + v["pid"] = static_cast<int>(info.GetProcessId()); + v["tid"] = 0; + this->JsonWriter->write(v, &this->ProfileStream); + } catch (std::ios_base::failure& fail) { + cmSystemTools::Error( + cmStrCat("Failed to write to profiling output:", fail.what())); + } catch (...) { + cmSystemTools::Error("Error writing profiling output!"); + } +} diff --git a/Source/cmMakefileProfilingData.h b/Source/cmMakefileProfilingData.h new file mode 100644 index 0000000..1babd97 --- /dev/null +++ b/Source/cmMakefileProfilingData.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 cmMakefileProfilingData_h +#define cmMakefileProfilingData_h +#include <memory> +#include <string> + +#include "cmsys/FStream.hxx" + +namespace Json { +class StreamWriter; +} + +class cmListFileContext; +struct cmListFileFunction; + +class cmMakefileProfilingData +{ +public: + cmMakefileProfilingData(const std::string&); + ~cmMakefileProfilingData() noexcept; + void StartEntry(const cmListFileFunction& lff, cmListFileContext const& lfc); + void StopEntry(); + +private: + cmsys::ofstream ProfileStream; + std::unique_ptr<Json::StreamWriter> JsonWriter; +}; +#endif diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index a25fd42..2ec66d9 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -47,10 +47,10 @@ bool cmProjectCommand(std::vector<std::string> const& args, mf.SetProjectName(projectName); mf.AddCacheDefinition(projectName + "_BINARY_DIR", - mf.GetCurrentBinaryDirectory().c_str(), + mf.GetCurrentBinaryDirectory(), "Value Computed by CMake", cmStateEnums::STATIC); mf.AddCacheDefinition(projectName + "_SOURCE_DIR", - mf.GetCurrentSourceDirectory().c_str(), + mf.GetCurrentSourceDirectory(), "Value Computed by CMake", cmStateEnums::STATIC); mf.AddDefinition("PROJECT_BINARY_DIR", mf.GetCurrentBinaryDirectory()); @@ -66,7 +66,7 @@ bool cmProjectCommand(std::vector<std::string> const& args, // will work. if (!mf.GetDefinition("CMAKE_PROJECT_NAME") || mf.IsRootMakefile()) { mf.AddDefinition("CMAKE_PROJECT_NAME", projectName); - mf.AddCacheDefinition("CMAKE_PROJECT_NAME", projectName.c_str(), + mf.AddCacheDefinition("CMAKE_PROJECT_NAME", projectName, "Value Computed by CMake", cmStateEnums::STATIC); } @@ -379,7 +379,7 @@ static void TopLevelCMakeVarCondSet(cmMakefile& mf, std::string const& name, // CMakeLists.txt file, then go with the last one. if (!mf.GetDefinition(name) || mf.IsRootMakefile()) { mf.AddDefinition(name, value); - mf.AddCacheDefinition(name, value.c_str(), "Value Computed by CMake", + mf.AddCacheDefinition(name, value, "Value Computed by CMake", cmStateEnums::STATIC); } } diff --git a/Source/cmPropertyDefinition.cxx b/Source/cmPropertyDefinition.cxx index 6a3174c..c8efaf6 100644 --- a/Source/cmPropertyDefinition.cxx +++ b/Source/cmPropertyDefinition.cxx @@ -2,19 +2,17 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmPropertyDefinition.h" -void cmPropertyDefinition::DefineProperty(const std::string& name, - cmProperty::ScopeType scope, - const char* shortDescription, - const char* fullDescription, - bool chain) +#include <utility> + +cmPropertyDefinition::cmPropertyDefinition(std::string name, + cmProperty::ScopeType scope, + std::string shortDescription, + std::string fullDescription, + bool chain) + : Name(std::move(name)) + , ShortDescription(std::move(shortDescription)) + , FullDescription(std::move(fullDescription)) + , Scope(scope) + , Chained(chain) { - this->Name = name; - this->Scope = scope; - this->Chained = chain; - if (shortDescription) { - this->ShortDescription = shortDescription; - } - if (fullDescription) { - this->FullDescription = fullDescription; - } } diff --git a/Source/cmPropertyDefinition.h b/Source/cmPropertyDefinition.h index 0d68c32..d2e4467 100644 --- a/Source/cmPropertyDefinition.h +++ b/Source/cmPropertyDefinition.h @@ -21,13 +21,10 @@ class cmPropertyDefinition { public: - /// Define this property - void DefineProperty(const std::string& name, cmProperty::ScopeType scope, - const char* ShortDescription, - const char* FullDescription, bool chained); - - /// Default constructor - cmPropertyDefinition() { this->Chained = false; } + /// Constructor + cmPropertyDefinition(std::string name, cmProperty::ScopeType scope, + std::string ShortDescription, + std::string FullDescription, bool chained = false); /// Is the property chained? bool IsChained() const { return this->Chained; } diff --git a/Source/cmPropertyDefinitionMap.cxx b/Source/cmPropertyDefinitionMap.cxx index f752ed7..614d5a4 100644 --- a/Source/cmPropertyDefinitionMap.cxx +++ b/Source/cmPropertyDefinitionMap.cxx @@ -2,20 +2,20 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmPropertyDefinitionMap.h" +#include <tuple> #include <utility> -void cmPropertyDefinitionMap::DefineProperty(const std::string& name, - cmProperty::ScopeType scope, - const char* ShortDescription, - const char* FullDescription, - bool chain) +void cmPropertyDefinitionMap::DefineProperty( + const std::string& name, cmProperty::ScopeType scope, + const std::string& ShortDescription, const std::string& FullDescription, + bool chain) { auto it = this->find(name); - cmPropertyDefinition* prop; if (it == this->end()) { - prop = &(*this)[name]; - prop->DefineProperty(name, scope, ShortDescription, FullDescription, - chain); + // try_emplace() since C++17 + this->emplace(std::piecewise_construct, std::forward_as_tuple(name), + std::forward_as_tuple(name, scope, ShortDescription, + FullDescription, chain)); } } diff --git a/Source/cmPropertyDefinitionMap.h b/Source/cmPropertyDefinitionMap.h index 8ec7910..2ae6efb 100644 --- a/Source/cmPropertyDefinitionMap.h +++ b/Source/cmPropertyDefinitionMap.h @@ -17,8 +17,8 @@ class cmPropertyDefinitionMap public: // define the property void DefineProperty(const std::string& name, cmProperty::ScopeType scope, - const char* ShortDescription, - const char* FullDescription, bool chain); + const std::string& ShortDescription, + const std::string& FullDescription, bool chain); // has a named property been defined bool IsPropertyDefined(const std::string& name) const; diff --git a/Source/cmPropertyMap.cxx b/Source/cmPropertyMap.cxx index d4b3552..f22f36d 100644 --- a/Source/cmPropertyMap.cxx +++ b/Source/cmPropertyMap.cxx @@ -42,13 +42,11 @@ void cmPropertyMap::RemoveProperty(const std::string& name) Map_.erase(name); } -const char* cmPropertyMap::GetPropertyValue(const std::string& name) const +cmProp cmPropertyMap::GetPropertyValue(const std::string& name) const { - { - auto it = Map_.find(name); - if (it != Map_.end()) { - return it->second.c_str(); - } + auto it = Map_.find(name); + if (it != Map_.end()) { + return &it->second; } return nullptr; } diff --git a/Source/cmPropertyMap.h b/Source/cmPropertyMap.h index bea4372..40ac356 100644 --- a/Source/cmPropertyMap.h +++ b/Source/cmPropertyMap.h @@ -10,6 +10,8 @@ #include <utility> #include <vector> +using cmProp = const std::string*; + /** \class cmPropertyMap * \brief String property map. */ @@ -31,7 +33,7 @@ public: bool asString = false); //! Get the property value - const char* GetPropertyValue(const std::string& name) const; + cmProp GetPropertyValue(const std::string& name) const; //! Remove the property @a name from the map void RemoveProperty(const std::string& name); diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx index 5e2a146..d8927e8 100644 --- a/Source/cmSetCommand.cxx +++ b/Source/cmSetCommand.cxx @@ -149,8 +149,8 @@ bool cmSetCommand(std::vector<std::string> const& args, // if it is meant to be in the cache then define it in the cache if (cache) { - status.GetMakefile().AddCacheDefinition(variable, value.c_str(), docstring, - type, force); + status.GetMakefile().AddCacheDefinition(variable, value, docstring, type, + force); } else { // add the definition status.GetMakefile().AddDefinition(variable, value); diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx index 3705727..ce534e1 100644 --- a/Source/cmSetPropertyCommand.cxx +++ b/Source/cmSetPropertyCommand.cxx @@ -307,7 +307,7 @@ bool HandleTarget(cmTarget* target, cmMakefile& makefile, if (remove) { target->SetProperty(propertyName, nullptr); } else { - target->SetProperty(propertyName, propertyValue.c_str()); + target->SetProperty(propertyName, propertyValue); } } @@ -460,16 +460,15 @@ bool HandleCacheEntry(std::string const& cacheKey, const cmMakefile& makefile, bool appendMode, bool remove) { // Set or append the property. - const char* value = propertyValue.c_str(); cmState* state = makefile.GetState(); if (remove) { state->RemoveCacheEntryProperty(cacheKey, propertyName); } if (appendMode) { - state->AppendCacheEntryProperty(cacheKey, propertyName, value, + state->AppendCacheEntryProperty(cacheKey, propertyName, propertyValue, appendAsString); } else { - state->SetCacheEntryProperty(cacheKey, propertyName, value); + state->SetCacheEntryProperty(cacheKey, propertyName, propertyValue); } return true; @@ -505,13 +504,13 @@ bool HandleInstall(cmInstalledFile* file, cmMakefile& makefile, bool appendMode, bool remove) { // Set or append the property. - const char* value = propertyValue.c_str(); if (remove) { file->RemoveProperty(propertyName); } else if (appendMode) { - file->AppendProperty(&makefile, propertyName, value, appendAsString); + file->AppendProperty(&makefile, propertyName, propertyValue, + appendAsString); } else { - file->SetProperty(&makefile, propertyName, value); + file->SetProperty(&makefile, propertyName, propertyValue); } return true; } diff --git a/Source/cmSiteNameCommand.cxx b/Source/cmSiteNameCommand.cxx index d47f121..b2d905e 100644 --- a/Source/cmSiteNameCommand.cxx +++ b/Source/cmSiteNameCommand.cxx @@ -72,8 +72,7 @@ bool cmSiteNameCommand(std::vector<std::string> const& args, } #endif status.GetMakefile().AddCacheDefinition( - args[0], siteName.c_str(), - "Name of the computer/site where compile is being run", + args[0], siteName, "Name of the computer/site where compile is being run", cmStateEnums::STRING); return true; diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index fd9cacd..5dc8b05 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -361,7 +361,7 @@ const char* cmSourceFile::GetProperty(const std::string& prop) const return output.c_str(); } - const char* retVal = this->Properties.GetPropertyValue(prop); + cmProp retVal = this->Properties.GetPropertyValue(prop); if (!retVal) { cmMakefile const* mf = this->Location.GetMakefile(); const bool chain = @@ -369,9 +369,10 @@ const char* cmSourceFile::GetProperty(const std::string& prop) const if (chain) { return mf->GetProperty(prop, chain); } + return nullptr; } - return retVal; + return retVal->c_str(); } const char* cmSourceFile::GetSafeProperty(const std::string& prop) const diff --git a/Source/cmState.cxx b/Source/cmState.cxx index 9fc7615..f424afa 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -335,8 +335,8 @@ cmStateSnapshot cmState::Reset() void cmState::DefineProperty(const std::string& name, cmProperty::ScopeType scope, - const char* ShortDescription, - const char* FullDescription, bool chained) + const std::string& ShortDescription, + const std::string& FullDescription, bool chained) { this->PropertyDefinitions[scope].DefineProperty( name, scope, ShortDescription, FullDescription, chained); @@ -625,7 +625,8 @@ const char* cmState::GetGlobalProperty(const std::string& prop) } #undef STRING_LIST_ELEMENT - return this->GlobalProperties.GetPropertyValue(prop); + cmProp retVal = this->GlobalProperties.GetPropertyValue(prop); + return retVal ? retVal->c_str() : nullptr; } bool cmState::GetGlobalPropertyAsBool(const std::string& prop) diff --git a/Source/cmState.h b/Source/cmState.h index 6ee2b0c..460c6bb 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -121,8 +121,8 @@ public: cmStateSnapshot Reset(); // Define a property void DefineProperty(const std::string& name, cmProperty::ScopeType scope, - const char* ShortDescription, - const char* FullDescription, bool chain = false); + const std::string& ShortDescription, + const std::string& FullDescription, bool chain = false); // get property definition cmPropertyDefinition const* GetPropertyDefinition( diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index 4f003ed..e7de3c7 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -634,7 +634,7 @@ const char* cmStateDirectory::GetProperty(const std::string& prop, return output.c_str(); } - const char* retVal = this->DirectoryState->Properties.GetPropertyValue(prop); + cmProp retVal = this->DirectoryState->Properties.GetPropertyValue(prop); if (!retVal && chain) { cmStateSnapshot parentSnapshot = this->Snapshot_.GetBuildsystemDirectoryParent(); @@ -644,7 +644,7 @@ const char* cmStateDirectory::GetProperty(const std::string& prop, return this->Snapshot_.State->GetGlobalProperty(prop); } - return retVal; + return retVal ? retVal->c_str() : nullptr; } bool cmStateDirectory::GetPropertyAsBool(const std::string& prop) const diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index 832e74e..d79df6f 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -411,11 +411,12 @@ void cmStateSnapshot::InitializeFromParent() this->Position->BuildSystemDirectory->LinkDirectoriesBacktraces, this->Position->LinkDirectoriesPosition); - const char* include_regex = + cmProp include_regex = parent->BuildSystemDirectory->Properties.GetPropertyValue( "INCLUDE_REGULAR_EXPRESSION"); this->Position->BuildSystemDirectory->Properties.SetProperty( - "INCLUDE_REGULAR_EXPRESSION", include_regex); + "INCLUDE_REGULAR_EXPRESSION", + include_regex ? include_regex->c_str() : nullptr); } cmState* cmStateSnapshot::GetState() const diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 987f526..f92eea4 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -78,7 +78,7 @@ const std::string& cmTargetPropertyComputer::ComputeLocation<cmTarget>( } template <> -const char* cmTargetPropertyComputer::GetSources<cmTarget>( +cmProp cmTargetPropertyComputer::GetSources<cmTarget>( cmTarget const* tgt, cmMessenger* messenger, cmListFileBacktrace const& context) { @@ -156,7 +156,7 @@ const char* cmTargetPropertyComputer::GetSources<cmTarget>( } static std::string srcs; srcs = ss.str(); - return srcs.c_str(); + return &srcs; } class cmTargetInternals @@ -1007,7 +1007,7 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib, dependencies += ";"; dependencies += lib; dependencies += ";"; - mf.AddCacheDefinition(targetEntry, dependencies.c_str(), + mf.AddCacheDefinition(targetEntry, dependencies, "Dependencies for the target", cmStateEnums::STATIC); } } @@ -1613,7 +1613,9 @@ const char* cmTarget::GetComputedProperty( const std::string& prop, cmMessenger* messenger, cmListFileBacktrace const& context) const { - return cmTargetPropertyComputer::GetProperty(this, prop, messenger, context); + cmProp retVal = + cmTargetPropertyComputer::GetProperty(this, prop, messenger, context); + return retVal ? retVal->c_str() : nullptr; } const char* cmTarget::GetProperty(const std::string& prop) const @@ -1771,7 +1773,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const } } - const char* retVal = impl->Properties.GetPropertyValue(prop); + cmProp retVal = impl->Properties.GetPropertyValue(prop); if (!retVal) { const bool chain = impl->Makefile->GetState()->IsPropertyChained(prop, cmProperty::TARGET); @@ -1779,8 +1781,9 @@ const char* cmTarget::GetProperty(const std::string& prop) const return impl->Makefile->GetStateSnapshot().GetDirectory().GetProperty( prop, chain); } + return nullptr; } - return retVal; + return retVal->c_str(); } const char* cmTarget::GetSafeProperty(const std::string& prop) const diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h index df34f18..5387e00 100644 --- a/Source/cmTargetPropertyComputer.h +++ b/Source/cmTargetPropertyComputer.h @@ -14,15 +14,17 @@ class cmMessenger; +using cmProp = const std::string*; + class cmTargetPropertyComputer { public: template <typename Target> - static const char* GetProperty(Target const* tgt, const std::string& prop, - cmMessenger* messenger, - cmListFileBacktrace const& context) + static cmProp GetProperty(Target const* tgt, const std::string& prop, + cmMessenger* messenger, + cmListFileBacktrace const& context) { - if (const char* loc = GetLocation(tgt, prop, messenger, context)) { + if (cmProp loc = GetLocation(tgt, prop, messenger, context)) { return loc; } if (cmSystemTools::GetFatalErrorOccured()) { @@ -52,9 +54,9 @@ private: std::string const& config); template <typename Target> - static const char* GetLocation(Target const* tgt, std::string const& prop, - cmMessenger* messenger, - cmListFileBacktrace const& context) + static cmProp GetLocation(Target const* tgt, std::string const& prop, + cmMessenger* messenger, + cmListFileBacktrace const& context) { // Watch for special "computed" properties that are dependent on @@ -71,7 +73,7 @@ private: context)) { return nullptr; } - return ComputeLocationForBuild(tgt).c_str(); + return &ComputeLocationForBuild(tgt); } // Support "LOCATION_<CONFIG>". @@ -82,7 +84,7 @@ private: return nullptr; } std::string configName = prop.substr(9); - return ComputeLocation(tgt, configName).c_str(); + return &ComputeLocation(tgt, configName); } // Support "<CONFIG>_LOCATION". @@ -95,7 +97,7 @@ private: context)) { return nullptr; } - return ComputeLocation(tgt, configName).c_str(); + return &ComputeLocation(tgt, configName); } } } @@ -103,8 +105,8 @@ private: } template <typename Target> - static const char* GetSources(Target const* tgt, cmMessenger* messenger, - cmListFileBacktrace const& context); + static cmProp GetSources(Target const* tgt, cmMessenger* messenger, + cmListFileBacktrace const& context); }; #endif diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx index 3b731cc..56c441a 100644 --- a/Source/cmTest.cxx +++ b/Source/cmTest.cxx @@ -34,15 +34,16 @@ void cmTest::SetCommand(std::vector<std::string> const& command) const char* cmTest::GetProperty(const std::string& prop) const { - const char* retVal = this->Properties.GetPropertyValue(prop); + cmProp retVal = this->Properties.GetPropertyValue(prop); if (!retVal) { const bool chain = this->Makefile->GetState()->IsPropertyChained(prop, cmProperty::TEST); if (chain) { return this->Makefile->GetProperty(prop, chain); } + return nullptr; } - return retVal; + return retVal->c_str(); } bool cmTest::GetPropertyAsBool(const std::string& prop) const diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx index a43165c..5865a19 100644 --- a/Source/cmUtilitySourceCommand.cxx +++ b/Source/cmUtilitySourceCommand.cxx @@ -102,15 +102,15 @@ bool cmUtilitySourceCommand(std::vector<std::string> const& args, cmSystemTools::ReplaceString(utilityExecutable, "/./", "/"); // Enter the value into the cache. - status.GetMakefile().AddCacheDefinition( - cacheEntry, utilityExecutable.c_str(), "Path to an internal program.", - cmStateEnums::FILEPATH); + status.GetMakefile().AddCacheDefinition(cacheEntry, utilityExecutable, + "Path to an internal program.", + cmStateEnums::FILEPATH); // add a value into the cache that maps from the // full path to the name of the project cmSystemTools::ConvertToUnixSlashes(utilityExecutable); - status.GetMakefile().AddCacheDefinition( - utilityExecutable, utilityName.c_str(), "Executable to project name.", - cmStateEnums::INTERNAL); + status.GetMakefile().AddCacheDefinition(utilityExecutable, utilityName, + "Executable to project name.", + cmStateEnums::INTERNAL); return true; } diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 121ff6e..6f5d813 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1017,7 +1017,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0) if (p.find(propNamePrefix) == 0) { std::string tagName = p.substr(propNamePrefix.length()); if (!tagName.empty()) { - std::string value = props.GetPropertyValue(p); + const std::string& value = *props.GetPropertyValue(p); if (!value.empty()) { e2.Element(tagName, value); } @@ -4802,7 +4802,7 @@ void cmVisualStudio10TargetGenerator::GetCSharpSourceProperties( if (p.find(propNamePrefix) == 0) { std::string tagName = p.substr(propNamePrefix.length()); if (!tagName.empty()) { - const std::string val = props.GetPropertyValue(p); + const std::string& val = *props.GetPropertyValue(p); if (!val.empty()) { tags[tagName] = val; } else { diff --git a/Source/cmake.cxx b/Source/cmake.cxx index f4b9f16..29ed61d 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -9,6 +9,7 @@ #include <initializer_list> #include <iostream> #include <sstream> +#include <stdexcept> #include <utility> #include <cm/memory> @@ -39,6 +40,9 @@ #include "cmLinkLineComputer.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#if !defined(CMAKE_BOOTSTRAP) +# include "cmMakefileProfilingData.h" +#endif #include "cmMessenger.h" #include "cmState.h" #include "cmStateDirectory.h" @@ -613,6 +617,10 @@ void cmake::SetArgs(const std::vector<std::string>& args) { bool haveToolset = false; bool havePlatform = false; +#if !defined(CMAKE_BOOTSTRAP) + std::string profilingFormat; + std::string profilingOutput; +#endif for (unsigned int i = 1; i < args.size(); ++i) { std::string const& arg = args[i]; if (arg.find("-H", 0) == 0 || arg.find("-S", 0) == 0) { @@ -839,6 +847,20 @@ void cmake::SetArgs(const std::vector<std::string>& args) return; } this->SetGlobalGenerator(std::move(gen)); +#if !defined(CMAKE_BOOTSTRAP) + } else if (arg.find("--profiling-format", 0) == 0) { + profilingFormat = arg.substr(strlen("--profiling-format=")); + if (profilingFormat.empty()) { + cmSystemTools::Error("No format specified for --profiling-format"); + } + } else if (arg.find("--profiling-output", 0) == 0) { + profilingOutput = arg.substr(strlen("--profiling-output=")); + profilingOutput = cmSystemTools::CollapseFullPath(profilingOutput); + cmSystemTools::ConvertToUnixSlashes(profilingOutput); + if (profilingOutput.empty()) { + cmSystemTools::Error("No path specified for --profiling-output"); + } +#endif } // no option assume it is the path to the source or an existing build else { @@ -856,6 +878,29 @@ void cmake::SetArgs(const std::vector<std::string>& args) } } +#if !defined(CMAKE_BOOTSTRAP) + if (!profilingOutput.empty() || !profilingFormat.empty()) { + if (profilingOutput.empty()) { + cmSystemTools::Error( + "--profiling-format specified but no --profiling-output!"); + return; + } + if (profilingFormat == "google-trace") { + try { + this->ProfilingOutput = + cm::make_unique<cmMakefileProfilingData>(profilingOutput); + } catch (std::runtime_error& e) { + cmSystemTools::Error( + cmStrCat("Could not start profiling: ", e.what())); + return; + } + } else { + cmSystemTools::Error("Invalid format specified for --profiling-format"); + return; + } + } +#endif + const bool haveSourceDir = !this->GetHomeDirectory().empty(); const bool haveBinaryDir = !this->GetHomeOutputDirectory().empty(); @@ -2952,3 +2997,15 @@ void cmake::SetDeprecatedWarningsAsErrors(bool b) " and functions.", cmStateEnums::INTERNAL); } + +#if !defined(CMAKE_BOOTSTRAP) +cmMakefileProfilingData& cmake::GetProfilingOutput() +{ + return *(this->ProfilingOutput); +} + +bool cmake::IsProfilingEnabled() const +{ + return static_cast<bool>(this->ProfilingOutput); +} +#endif diff --git a/Source/cmake.h b/Source/cmake.h index 35425ec..58769fd 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -34,6 +34,9 @@ class cmFileTimeCache; class cmGlobalGenerator; class cmGlobalGeneratorFactory; class cmMakefile; +#if !defined(CMAKE_BOOTSTRAP) +class cmMakefileProfilingData; +#endif class cmMessenger; class cmVariableWatch; struct cmDocumentationEntry; @@ -549,6 +552,11 @@ public: bool GetRegenerateDuringBuild() const { return this->RegenerateDuringBuild; } +#if !defined(CMAKE_BOOTSTRAP) + cmMakefileProfilingData& GetProfilingOutput(); + bool IsProfilingEnabled() const; +#endif + protected: void RunCheckForUnusedVariables(); int HandleDeleteCacheVariables(const std::string& var); @@ -657,6 +665,10 @@ private: void AppendGlobalGeneratorsDocumentation(std::vector<cmDocumentationEntry>&); void AppendExtraGeneratorsDocumentation(std::vector<cmDocumentationEntry>&); + +#if !defined(CMAKE_BOOTSTRAP) + std::unique_ptr<cmMakefileProfilingData> ProfilingOutput; +#endif }; #define CMAKE_STANDARD_OPTIONS_TABLE \ diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 494d5d9..90d8ea6 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -93,6 +93,12 @@ const char* cmDocumentationOptions[][2] = { { "--check-system-vars", "Find problems with variable usage in system " "files." }, +# if !defined(CMAKE_BOOTSTRAP) + { "--profiling-format=<fmt>", "Output data for profiling CMake scripts." }, + { "--profiling-output=<file>", + "Select an output path for the profiling data enabled through " + "--profiling-format." }, +# endif { nullptr, nullptr } }; diff --git a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt index a53e441..49a4041 100644 --- a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt +++ b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt @@ -86,7 +86,7 @@ foreach(VTEST ALSA ARMADILLO BZIP2 CUPS CURL EXPAT FREETYPE GETTEXT GIT HG endforeach() foreach(VTEST BISON Boost CUDA DOXYGEN FLEX GIF GTK2 - HDF5 JPEG LibArchive OPENSCENEGRAPH RUBY SWIG Protobuf) + HDF5 JPEG LibArchive OPENSCENEGRAPH Ruby RUBY SWIG Protobuf) check_version_string(${VTEST} ${VTEST}_VERSION) endforeach() diff --git a/Tests/FindPython/CMakeLists.txt b/Tests/FindPython/CMakeLists.txt index bd6e8ab..d2326e4 100644 --- a/Tests/FindPython/CMakeLists.txt +++ b/Tests/FindPython/CMakeLists.txt @@ -67,14 +67,64 @@ if(CMake_TEST_FindPython) set_tests_properties(FindPython.Python3Fail PROPERTIES PASS_REGULAR_EXPRESSION "Could NOT find Python3 \\(missing: foobar\\)") - add_test(NAME FindPython.Python COMMAND + add_test(NAME FindPython.Python.LOCATION COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> --build-and-test "${CMake_SOURCE_DIR}/Tests/FindPython/Python" - "${CMake_BINARY_DIR}/Tests/FindPython/Python" + "${CMake_BINARY_DIR}/Tests/FindPython/Python.LOCATION" ${build_generator_args} --build-project TestPython - --build-options ${build_options} + --build-options ${build_options} -DPython_FIND_STRATEGY=LOCATION + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) + add_test(NAME FindPython.Python.VERSION COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/Python" + "${CMake_BINARY_DIR}/Tests/FindPython/Python.VERSION" + ${build_generator_args} + --build-project TestPython + --build-options ${build_options} -DPython_FIND_STRATEGY=VERSION + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) + add_test(NAME FindPython.Python.V2.LOCATION COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/Python" + "${CMake_BINARY_DIR}/Tests/FindPython/Python.V2.LOCATION" + ${build_generator_args} + --build-project TestPython + --build-options ${build_options} -DPython_REQUESTED_VERSION=2 -DPython_FIND_STRATEGY=LOCATION + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) + add_test(NAME FindPython.Python.V2.VERSION COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/Python" + "${CMake_BINARY_DIR}/Tests/FindPython/Python.V2.VERSION" + ${build_generator_args} + --build-project TestPython + --build-options ${build_options} -DPython_REQUESTED_VERSION=2 -DPython_FIND_STRATEGY=VERSION + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) + add_test(NAME FindPython.Python.V3.LOCATION COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/Python" + "${CMake_BINARY_DIR}/Tests/FindPython/Python.V3.LOCATION" + ${build_generator_args} + --build-project TestPython + --build-options ${build_options} -DPython_REQUESTED_VERSION=3 -DPython_FIND_STRATEGY=LOCATION + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) + add_test(NAME FindPython.Python.V3.VERSION COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/Python" + "${CMake_BINARY_DIR}/Tests/FindPython/Python.V3.VERSION" + ${build_generator_args} + --build-project TestPython + --build-options ${build_options} -DPython_REQUESTED_VERSION=3 -DPython_FIND_STRATEGY=VERSION --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> ) diff --git a/Tests/FindPython/Python/CMakeLists.txt b/Tests/FindPython/Python/CMakeLists.txt index 62c805e..3ee38e3 100644 --- a/Tests/FindPython/Python/CMakeLists.txt +++ b/Tests/FindPython/Python/CMakeLists.txt @@ -4,9 +4,9 @@ project(TestPython C) include(CTest) -find_package(Python 3 REQUIRED COMPONENTS Interpreter Development) +find_package(Python ${Python_REQUESTED_VERSION} REQUIRED COMPONENTS Interpreter Development) if (NOT Python_FOUND) - message (FATAL_ERROR "Fail to found Python 3") + message (FATAL_ERROR "Fail to found Python ${Python_REQUESTED_VERSION}") endif() if(NOT TARGET Python::Interpreter) @@ -20,13 +20,15 @@ if(NOT TARGET Python::Module) message(SEND_ERROR "Python::Module not found") endif() -Python_add_library (spam3 MODULE ../spam.c) -target_compile_definitions (spam3 PRIVATE PYTHON3) - -add_test (NAME python_spam3 - COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:spam3>" - "${Python_EXECUTABLE}" -c "import spam3; spam3.system(\"cd\")") - -add_test(NAME findpython_script - COMMAND "${CMAKE_COMMAND}" -DPYTHON_PACKAGE_NAME=Python - -P "${CMAKE_CURRENT_LIST_DIR}/../FindPythonScript.cmake") +if (Python_REQUESTED_VERSION) + Python_add_library (spam${Python_REQUESTED_VERSION} MODULE ../spam.c) + target_compile_definitions (spam${Python_REQUESTED_VERSION} PRIVATE PYTHON${Python_REQUESTED_VERSION}) + + add_test (NAME python_spam${Python_REQUESTED_VERSION} + COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:spam${Python_REQUESTED_VERSION}>" + "${Python_EXECUTABLE}" -c "import spam${Python_REQUESTED_VERSION}; spam${Python_REQUESTED_VERSION}.system(\"cd\")") +else() + add_test(NAME findpython_script + COMMAND "${CMAKE_COMMAND}" -DPYTHON_PACKAGE_NAME=Python + -P "${CMAKE_CURRENT_LIST_DIR}/../FindPythonScript.cmake") +endif() diff --git a/Tests/RunCMake/BuildDepends/GNU-AS-stdout.txt b/Tests/RunCMake/BuildDepends/GNU-AS-stdout.txt new file mode 100644 index 0000000..c4326ae --- /dev/null +++ b/Tests/RunCMake/BuildDepends/GNU-AS-stdout.txt @@ -0,0 +1,4 @@ +-- The ASM compiler identification is GNU +-- Found assembler: [^ +]*/as(\.exe)? +-- CMAKE_ASM_COMPILER_ID_VENDOR_MATCH='GNU assembler' diff --git a/Tests/RunCMake/BuildDepends/GNU-AS.cmake b/Tests/RunCMake/BuildDepends/GNU-AS.cmake new file mode 100644 index 0000000..21921ef --- /dev/null +++ b/Tests/RunCMake/BuildDepends/GNU-AS.cmake @@ -0,0 +1,13 @@ +enable_language(ASM) + +# Validate undocumented implementation detail. +message(STATUS "CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_MATCH='${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_MATCH}'") + +add_library(gnu_as STATIC gnu_as.s) +target_include_directories(gnu_as PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) + +file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT " +set(check_pairs + \"$<TARGET_FILE:gnu_as>|${CMAKE_CURRENT_BINARY_DIR}/gnu_as.inc\" + ) +") diff --git a/Tests/RunCMake/BuildDepends/GNU-AS.step1.cmake b/Tests/RunCMake/BuildDepends/GNU-AS.step1.cmake new file mode 100644 index 0000000..15a5e96 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/GNU-AS.step1.cmake @@ -0,0 +1 @@ +file(WRITE "${RunCMake_TEST_BINARY_DIR}/gnu_as.inc" "") diff --git a/Tests/RunCMake/BuildDepends/GNU-AS.step2.cmake b/Tests/RunCMake/BuildDepends/GNU-AS.step2.cmake new file mode 100644 index 0000000..15a5e96 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/GNU-AS.step2.cmake @@ -0,0 +1 @@ +file(WRITE "${RunCMake_TEST_BINARY_DIR}/gnu_as.inc" "") diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake index 14ae243..753417d 100644 --- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake +++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake @@ -103,3 +103,8 @@ endfunction() if(RunCMake_GENERATOR STREQUAL "Xcode") run_ReGeneration(regenerate-project) endif() + +if(CMake_TEST_BuildDepends_GNU_AS) + set(ENV{ASM} "${CMake_TEST_BuildDepends_GNU_AS}") + run_BuildDepends(GNU-AS) +endif() diff --git a/Tests/RunCMake/BuildDepends/gnu_as.s b/Tests/RunCMake/BuildDepends/gnu_as.s new file mode 100644 index 0000000..a2e7dfb --- /dev/null +++ b/Tests/RunCMake/BuildDepends/gnu_as.s @@ -0,0 +1 @@ +.include "gnu_as.inc" diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 4b5475e..101e10c 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -169,7 +169,20 @@ if(CMake_TEST_Qt5 AND Qt5Widgets_FOUND) set(autogen_with_qt5 TRUE) endif () add_RunCMake_test(Autogen -Dwith_qt5=${autogen_with_qt5}) -add_RunCMake_test(BuildDepends) +if(NOT DEFINED CMake_TEST_BuildDepends_GNU_AS + AND CMAKE_C_COMPILER_ID STREQUAL "GNU" + AND CMAKE_GENERATOR MATCHES "^Ninja" + ) + execute_process(COMMAND "${CMAKE_C_COMPILER}" -print-prog-name=as + RESULT_VARIABLE _gnu_res + OUTPUT_VARIABLE _gnu_as OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + if(_gnu_res EQUAL 0 AND _gnu_as) + set(CMake_TEST_BuildDepends_GNU_AS "${_gnu_as}") + endif() +endif() +add_RunCMake_test(BuildDepends + -DCMake_TEST_BuildDepends_GNU_AS=${CMake_TEST_BuildDepends_GNU_AS} + ) if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja") add_RunCMake_test(Byproducts) endif() @@ -448,6 +461,7 @@ if(CMAKE_C_COMPILER_ID STREQUAL "AppleClang" add_RunCMake_test(Framework) endif() +add_RunCMake_test(File_Archive) add_RunCMake_test(File_Configure) add_RunCMake_test(File_Generate) add_RunCMake_test(ExportWithoutLanguage) diff --git a/Tests/RunCMake/CommandLine/ProfilingTest-check.cmake b/Tests/RunCMake/CommandLine/ProfilingTest-check.cmake new file mode 100644 index 0000000..19ece86 --- /dev/null +++ b/Tests/RunCMake/CommandLine/ProfilingTest-check.cmake @@ -0,0 +1,18 @@ +if (NOT EXISTS ${ProfilingTestOutput}) + set(RunCMake_TEST_FAILED "Expected ${ProfilingTestOutput} to exists") +endif() + +file(READ "${ProfilingTestOutput}" JSON_HEADER LIMIT 2) +if (NOT JSON_HEADER MATCHES "^\\[{") + set(RunCMake_TEST_FAILED "Expected valid JSON start") + return() +endif() + +file(SIZE "${ProfilingTestOutput}" OUTPUT_SIZE) +math(EXPR END_OFFSET "${OUTPUT_SIZE} -2 ") + +file(READ "${ProfilingTestOutput}" JSON_TRAILER OFFSET ${END_OFFSET}) +if (NOT JSON_TRAILER MATCHES "^}]$") + set(RunCMake_TEST_FAILED "Expected valid JSON end") + return() +endif() diff --git a/Tests/RunCMake/CommandLine/ProfilingTest.cmake b/Tests/RunCMake/CommandLine/ProfilingTest.cmake new file mode 100644 index 0000000..837f4bf --- /dev/null +++ b/Tests/RunCMake/CommandLine/ProfilingTest.cmake @@ -0,0 +1 @@ +# This file is intentionally left blank diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 087ef21..41f13db 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -697,3 +697,25 @@ function(run_llvm_rc) unset(LLVMRC_RESULT) endfunction() run_llvm_rc() + +set(RunCMake_TEST_OPTIONS --profiling-output=/no/such/file.txt --profiling-format=google-trace) +run_cmake(profiling-all-params) +unset(RunCMake_TEST_OPTIONS) + +set(RunCMake_TEST_OPTIONS --profiling-output=/no/such/file.txt --profiling-format=invalid-format) +run_cmake(profiling-invalid-format) +unset(RunCMake_TEST_OPTIONS) + +set(RunCMake_TEST_OPTIONS --profiling-output=/no/such/file.txt) +run_cmake(profiling-missing-format) +unset(RunCMake_TEST_OPTIONS) + +set(RunCMake_TEST_OPTIONS --profiling-format=google-trace) +run_cmake(profiling-missing-output) +unset(RunCMake_TEST_OPTIONS) + +set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/profiling-test") +set(ProfilingTestOutput ${RunCMake_TEST_BINARY_DIR}/output.json) +set(RunCMake_TEST_OPTIONS --profiling-format=google-trace --profiling-output=${ProfilingTestOutput}) +run_cmake(ProfilingTest) +unset(RunCMake_TEST_OPTIONS) diff --git a/Tests/RunCMake/CommandLine/profiling-all-params-result.txt b/Tests/RunCMake/CommandLine/profiling-all-params-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/profiling-all-params-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/profiling-all-params-stderr.txt b/Tests/RunCMake/CommandLine/profiling-all-params-stderr.txt new file mode 100644 index 0000000..6b5c373 --- /dev/null +++ b/Tests/RunCMake/CommandLine/profiling-all-params-stderr.txt @@ -0,0 +1 @@ +^.*Could not start profiling: Unable to open: /no/such/file.txt$ diff --git a/Tests/RunCMake/CommandLine/profiling-invalid-format-result.txt b/Tests/RunCMake/CommandLine/profiling-invalid-format-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/profiling-invalid-format-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/profiling-invalid-format-stderr.txt b/Tests/RunCMake/CommandLine/profiling-invalid-format-stderr.txt new file mode 100644 index 0000000..459bc3a --- /dev/null +++ b/Tests/RunCMake/CommandLine/profiling-invalid-format-stderr.txt @@ -0,0 +1 @@ +^.*Invalid format specified for --profiling-format$ diff --git a/Tests/RunCMake/CommandLine/profiling-missing-format-result.txt b/Tests/RunCMake/CommandLine/profiling-missing-format-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/profiling-missing-format-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/profiling-missing-format-stderr.txt b/Tests/RunCMake/CommandLine/profiling-missing-format-stderr.txt new file mode 100644 index 0000000..459bc3a --- /dev/null +++ b/Tests/RunCMake/CommandLine/profiling-missing-format-stderr.txt @@ -0,0 +1 @@ +^.*Invalid format specified for --profiling-format$ diff --git a/Tests/RunCMake/CommandLine/profiling-missing-output-result.txt b/Tests/RunCMake/CommandLine/profiling-missing-output-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/profiling-missing-output-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/profiling-missing-output-stderr.txt b/Tests/RunCMake/CommandLine/profiling-missing-output-stderr.txt new file mode 100644 index 0000000..9ab0c8f --- /dev/null +++ b/Tests/RunCMake/CommandLine/profiling-missing-output-stderr.txt @@ -0,0 +1 @@ +^.*--profiling-format specified but no --profiling-output!$ diff --git a/Tests/RunCMake/File_Archive/7zip.cmake b/Tests/RunCMake/File_Archive/7zip.cmake new file mode 100644 index 0000000..7b0b9b7 --- /dev/null +++ b/Tests/RunCMake/File_Archive/7zip.cmake @@ -0,0 +1,7 @@ +set(OUTPUT_NAME "test.7z") + +set(COMPRESSION_FORMAT 7zip) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("377abcaf271c" LIMIT 6 HEX) diff --git a/Tests/RunCMake/File_Archive/CMakeLists.txt b/Tests/RunCMake/File_Archive/CMakeLists.txt new file mode 100644 index 0000000..2897109 --- /dev/null +++ b/Tests/RunCMake/File_Archive/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.0) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/File_Archive/RunCMakeTest.cmake b/Tests/RunCMake/File_Archive/RunCMakeTest.cmake new file mode 100644 index 0000000..871cb6d --- /dev/null +++ b/Tests/RunCMake/File_Archive/RunCMakeTest.cmake @@ -0,0 +1,17 @@ +include(RunCMake) + +run_cmake(7zip) +run_cmake(gnutar) +run_cmake(gnutar-gz) +run_cmake(pax) +run_cmake(pax-xz) +run_cmake(pax-zstd) +run_cmake(paxr) +run_cmake(paxr-bz2) +run_cmake(zip) + +# Extracting only selected files or directories +run_cmake(zip-filtered) + +run_cmake(unsupported-format) +run_cmake(zip-with-bad-type) diff --git a/Tests/RunCMake/File_Archive/gnutar-gz.cmake b/Tests/RunCMake/File_Archive/gnutar-gz.cmake new file mode 100644 index 0000000..f4e3975 --- /dev/null +++ b/Tests/RunCMake/File_Archive/gnutar-gz.cmake @@ -0,0 +1,8 @@ +set(OUTPUT_NAME "test.tar.gz") + +set(COMPRESSION_FORMAT gnutar) +set(COMPRESSION_TYPE GZip) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("1f8b" LIMIT 2 HEX) diff --git a/Tests/RunCMake/File_Archive/gnutar.cmake b/Tests/RunCMake/File_Archive/gnutar.cmake new file mode 100644 index 0000000..e5cbd35 --- /dev/null +++ b/Tests/RunCMake/File_Archive/gnutar.cmake @@ -0,0 +1,7 @@ +set(OUTPUT_NAME "test.tar") + +set(COMPRESSION_FORMAT gnutar) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("7573746172202000" OFFSET 257 LIMIT 8 HEX) diff --git a/Tests/RunCMake/File_Archive/pax-xz.cmake b/Tests/RunCMake/File_Archive/pax-xz.cmake new file mode 100644 index 0000000..47fb0fd --- /dev/null +++ b/Tests/RunCMake/File_Archive/pax-xz.cmake @@ -0,0 +1,8 @@ +set(OUTPUT_NAME "test.tar.xz") + +set(COMPRESSION_FORMAT pax) +set(COMPRESSION_TYPE XZ) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("fd377a585a00" LIMIT 6 HEX) diff --git a/Tests/RunCMake/File_Archive/pax-zstd.cmake b/Tests/RunCMake/File_Archive/pax-zstd.cmake new file mode 100644 index 0000000..59e0443 --- /dev/null +++ b/Tests/RunCMake/File_Archive/pax-zstd.cmake @@ -0,0 +1,8 @@ +set(OUTPUT_NAME "test.tar.zstd") + +set(COMPRESSION_FORMAT pax) +set(COMPRESSION_TYPE Zstd) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("28b52ffd0058" LIMIT 6 HEX) diff --git a/Tests/RunCMake/File_Archive/pax.cmake b/Tests/RunCMake/File_Archive/pax.cmake new file mode 100644 index 0000000..e50c74f --- /dev/null +++ b/Tests/RunCMake/File_Archive/pax.cmake @@ -0,0 +1,7 @@ +set(OUTPUT_NAME "test.tar") + +set(COMPRESSION_FORMAT pax) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX) diff --git a/Tests/RunCMake/File_Archive/paxr-bz2.cmake b/Tests/RunCMake/File_Archive/paxr-bz2.cmake new file mode 100644 index 0000000..469a131 --- /dev/null +++ b/Tests/RunCMake/File_Archive/paxr-bz2.cmake @@ -0,0 +1,8 @@ +set(OUTPUT_NAME "test.tar.bz2") + +set(COMPRESSION_FORMAT paxr) +set(COMPRESSION_TYPE BZip2) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("425a68" LIMIT 3 HEX) diff --git a/Tests/RunCMake/File_Archive/paxr.cmake b/Tests/RunCMake/File_Archive/paxr.cmake new file mode 100644 index 0000000..e3a4d5c --- /dev/null +++ b/Tests/RunCMake/File_Archive/paxr.cmake @@ -0,0 +1,7 @@ +set(OUTPUT_NAME "test.tar") + +set(COMPRESSION_FORMAT paxr) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("7573746172003030" OFFSET 257 LIMIT 8 HEX) diff --git a/Tests/RunCMake/File_Archive/roundtrip.cmake b/Tests/RunCMake/File_Archive/roundtrip.cmake new file mode 100644 index 0000000..9050400 --- /dev/null +++ b/Tests/RunCMake/File_Archive/roundtrip.cmake @@ -0,0 +1,92 @@ +foreach(parameter OUTPUT_NAME COMPRESSION_FORMAT) + if(NOT DEFINED ${parameter}) + message(FATAL_ERROR "missing required parameter ${parameter}") + endif() +endforeach() + +set(COMPRESS_DIR compress_dir) +set(FULL_COMPRESS_DIR ${CMAKE_CURRENT_BINARY_DIR}/${COMPRESS_DIR}) + +set(DECOMPRESS_DIR decompress_dir) +set(FULL_DECOMPRESS_DIR ${CMAKE_CURRENT_BINARY_DIR}/${DECOMPRESS_DIR}) + +set(FULL_OUTPUT_NAME ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_NAME}) + +set(CHECK_FILES + "f1.txt" + "d1/f1.txt" + "d 2/f1.txt" + "d + 3/f1.txt" + "d_4/f1.txt" + "d-4/f1.txt" + "My Special Directory/f1.txt" +) + +foreach(file ${CHECK_FILES}) + configure_file(${CMAKE_CURRENT_LIST_FILE} ${FULL_COMPRESS_DIR}/${file} COPYONLY) +endforeach() + +if(UNIX) + execute_process(COMMAND ln -sf f1.txt ${FULL_COMPRESS_DIR}/d1/f2.txt) + list(APPEND CHECK_FILES "d1/f2.txt") +endif() + +file(REMOVE ${FULL_OUTPUT_NAME}) +file(REMOVE_RECURSE ${FULL_DECOMPRESS_DIR}) +file(MAKE_DIRECTORY ${FULL_DECOMPRESS_DIR}) + +file(ARCHIVE_CREATE + OUTPUT ${FULL_OUTPUT_NAME} + FORMAT "${COMPRESSION_FORMAT}" + TYPE "${COMPRESSION_TYPE}" + VERBOSE + DIRECTORY ${COMPRESS_DIR}) + +file(ARCHIVE_EXTRACT + INPUT ${FULL_OUTPUT_NAME} + ${DECOMPRESSION_OPTIONS} + DESTINATION ${FULL_DECOMPRESS_DIR} + VERBOSE) + +if(CUSTOM_CHECK_FILES) + set(CHECK_FILES ${CUSTOM_CHECK_FILES}) +endif() + +foreach(file ${CHECK_FILES}) + set(input ${FULL_COMPRESS_DIR}/${file}) + set(output ${FULL_DECOMPRESS_DIR}/${COMPRESS_DIR}/${file}) + + if(NOT EXISTS ${input}) + message(SEND_ERROR "Cannot find input file ${output}") + endif() + + if(NOT EXISTS ${output}) + message(SEND_ERROR "Cannot find output file ${output}") + endif() + + file(MD5 ${input} input_md5) + file(MD5 ${output} output_md5) + + if(NOT input_md5 STREQUAL output_md5) + message(SEND_ERROR "Files \"${input}\" and \"${output}\" are different") + endif() +endforeach() + +foreach(file ${NOT_EXISTING_FILES_CHECK}) + set(output ${FULL_DECOMPRESS_DIR}/${COMPRESS_DIR}/${file}) + + if(EXISTS ${output}) + message(SEND_ERROR "File ${output} exists but it shouldn't") + endif() +endforeach() + +function(check_magic EXPECTED) + file(READ ${FULL_OUTPUT_NAME} ACTUAL + ${ARGN} + ) + + if(NOT ACTUAL STREQUAL EXPECTED) + message(FATAL_ERROR + "Actual [${ACTUAL}] does not match expected [${EXPECTED}]") + endif() +endfunction() diff --git a/Tests/RunCMake/File_Archive/unsupported-format-result.txt b/Tests/RunCMake/File_Archive/unsupported-format-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/File_Archive/unsupported-format-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Archive/unsupported-format-stderr.txt b/Tests/RunCMake/File_Archive/unsupported-format-stderr.txt new file mode 100644 index 0000000..4328022 --- /dev/null +++ b/Tests/RunCMake/File_Archive/unsupported-format-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at roundtrip.cmake:38 \(file\): + file archive format rar not supported +Call Stack \(most recent call first\): + unsupported-format.cmake:5 \(include\) + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/File_Archive/unsupported-format.cmake b/Tests/RunCMake/File_Archive/unsupported-format.cmake new file mode 100644 index 0000000..61edc1b --- /dev/null +++ b/Tests/RunCMake/File_Archive/unsupported-format.cmake @@ -0,0 +1,5 @@ +set(OUTPUT_NAME "test.rar") + +set(COMPRESSION_FORMAT rar) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) diff --git a/Tests/RunCMake/File_Archive/zip-filtered.cmake b/Tests/RunCMake/File_Archive/zip-filtered.cmake new file mode 100644 index 0000000..2d259bc --- /dev/null +++ b/Tests/RunCMake/File_Archive/zip-filtered.cmake @@ -0,0 +1,26 @@ +set(OUTPUT_NAME "test.zip") + +set(COMPRESSION_FORMAT zip) + +set(DECOMPRESSION_OPTIONS + FILES + compress_dir/f1.txt # Decompress only file + compress_dir/d1 # and whole directory +) + +set(CUSTOM_CHECK_FILES + "f1.txt" + "d1/f1.txt" +) + +# This files shouldn't exists +set(NOT_EXISTING_FILES_CHECK + "d 2/f1.txt" + "d + 3/f1.txt" + "d_4/f1.txt" + "d-4/f1.txt" +) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("504b0304" LIMIT 4 HEX) diff --git a/Tests/RunCMake/File_Archive/zip-with-bad-type-result.txt b/Tests/RunCMake/File_Archive/zip-with-bad-type-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/File_Archive/zip-with-bad-type-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Archive/zip-with-bad-type-stderr.txt b/Tests/RunCMake/File_Archive/zip-with-bad-type-stderr.txt new file mode 100644 index 0000000..fe12feb --- /dev/null +++ b/Tests/RunCMake/File_Archive/zip-with-bad-type-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at roundtrip.cmake:38 \(file\): + file archive format zip does not support TYPE arguments +Call Stack \(most recent call first\): + zip-with-bad-type.cmake:6 \(include\) + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/File_Archive/zip-with-bad-type.cmake b/Tests/RunCMake/File_Archive/zip-with-bad-type.cmake new file mode 100644 index 0000000..ebb97a3 --- /dev/null +++ b/Tests/RunCMake/File_Archive/zip-with-bad-type.cmake @@ -0,0 +1,6 @@ +set(OUTPUT_NAME "test.zip") + +set(COMPRESSION_FORMAT zip) +set(COMPRESSION_TYPE BZip2) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) diff --git a/Tests/RunCMake/File_Archive/zip.cmake b/Tests/RunCMake/File_Archive/zip.cmake new file mode 100644 index 0000000..1b93058 --- /dev/null +++ b/Tests/RunCMake/File_Archive/zip.cmake @@ -0,0 +1,7 @@ +set(OUTPUT_NAME "test.zip") + +set(COMPRESSION_FORMAT zip) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("504b0304" LIMIT 4 HEX) diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-result.txt b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-build-result.txt index d197c91..d197c91 100644 --- a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-result.txt +++ b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-build-result.txt diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-build-stdout.txt index 3a6572c..3a6572c 100644 --- a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-stdout.txt +++ b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-build-stdout.txt diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-result.txt b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-result.txt new file mode 100644 index 0000000..d197c91 --- /dev/null +++ b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-result.txt @@ -0,0 +1 @@ +[^0] diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-stderr.txt b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-stderr.txt new file mode 100644 index 0000000..f6be939 --- /dev/null +++ b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-stderr.txt @@ -0,0 +1,2 @@ +Unable to find executable: discovery_timeout_test_NOT_BUILT +Errors while running CTest diff --git a/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-stdout.txt b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-stdout.txt new file mode 100644 index 0000000..d4c4e7b --- /dev/null +++ b/Tests/RunCMake/GoogleTest/GoogleTest-discovery-timeout-test-stdout.txt @@ -0,0 +1,18 @@ +Test project .*GoogleTest-build +[ \t]*Start [0-9]+: discovery_timeout_test_NOT_BUILT +Could not find executable discovery_timeout_test_NOT_BUILT +Looked in the following places: +discovery_timeout_test_NOT_BUILT +discovery_timeout_test_NOT_BUILT(\.exe)? +Debug/discovery_timeout_test_NOT_BUILT +Debug/discovery_timeout_test_NOT_BUILT(\.exe)? +Debug/discovery_timeout_test_NOT_BUILT +Debug/discovery_timeout_test_NOT_BUILT(\.exe)? +[^\n]+discovery_timeout_test_NOT_BUILT +\.+\*\*\*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: +[^\n]+discovery_timeout_test_NOT_BUILT \(Not Run\) diff --git a/Tests/RunCMake/GoogleTest/GoogleTestXML-result-check.cmake b/Tests/RunCMake/GoogleTest/GoogleTestXML-result-check.cmake new file mode 100644 index 0000000..3bfdac3 --- /dev/null +++ b/Tests/RunCMake/GoogleTest/GoogleTestXML-result-check.cmake @@ -0,0 +1,4 @@ +set(RESULT_FILE "${RunCMake_TEST_BINARY_DIR}/GoogleTestXML.Foo.xml") +if(NOT EXISTS ${RESULT_FILE}) + set(RunCMake_TEST_FAILED "Result XML file ${RESULT_FILE} was not created") +endif() diff --git a/Tests/RunCMake/GoogleTest/GoogleTestXML.cmake b/Tests/RunCMake/GoogleTest/GoogleTestXML.cmake new file mode 100644 index 0000000..c86de63 --- /dev/null +++ b/Tests/RunCMake/GoogleTest/GoogleTestXML.cmake @@ -0,0 +1,11 @@ +project(test_include_dirs) +include(CTest) +include(GoogleTest) + +enable_testing() + +add_executable(xml_output xml_output.cpp) +gtest_discover_tests( + xml_output + XML_OUTPUT_DIR ${CMAKE_BINARY_DIR} +) diff --git a/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake b/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake index 0fa4e2a..8070512 100644 --- a/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake +++ b/Tests/RunCMake/GoogleTest/RunCMakeTest.cmake @@ -27,7 +27,7 @@ function(run_GoogleTest) ) set(RunCMake_TEST_OUTPUT_MERGE 1) - run_cmake_command(GoogleTest-discovery-timeout + run_cmake_command(GoogleTest-discovery-timeout-build ${CMAKE_COMMAND} --build . --config Debug @@ -69,6 +69,41 @@ function(run_GoogleTest) -R property_timeout\\.case_with_discovery --no-label-summary ) + + run_cmake_command(GoogleTest-discovery-timeout-test + ${CMAKE_CTEST_COMMAND} + -C Debug + -R discovery_timeout_test + --no-label-summary + ) +endfunction() + +function(run_GoogleTestXML) + # Use a single build tree for a few tests without cleaning. + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/GoogleTestXML-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(GoogleTestXML) + + run_cmake_command(GoogleTestXML-discovery + ${CMAKE_COMMAND} + --build . + --config Debug + --target xml_output + ) + + run_cmake_command(GoogleTestXML-result + ${CMAKE_CTEST_COMMAND} + -C Debug + -R GoogleTestXML + --no-label-summary + ) endfunction() run_GoogleTest() +run_GoogleTestXML() diff --git a/Tests/RunCMake/GoogleTest/xml_output.cpp b/Tests/RunCMake/GoogleTest/xml_output.cpp new file mode 100644 index 0000000..e130231 --- /dev/null +++ b/Tests/RunCMake/GoogleTest/xml_output.cpp @@ -0,0 +1,26 @@ +#include <fstream> +#include <iostream> +#include <string> + +int main(int argc, char** argv) +{ + // Note: GoogleTestXML.cmake doesn't actually depend on Google Test as such; + // it only mimicks the output file creation using the path passed to this + // test without any content + for (int i = 0; i < argc; i++) { + std::string param(argv[i]); + if (param.find("--gtest_list_tests") != std::string::npos) { + // This actually defines the name of the file passed in the 2nd run + std::cout << "GoogleTestXML." << std::endl; + std::cout << " Foo" << std::endl; + } else if (param.find("--gtest_output=xml:") != std::string::npos) { + std::string::size_type split = param.find(":"); + std::string filepath = param.substr(split + 1); + // The full file path is passed + std::ofstream ostrm(filepath.c_str(), std::ios::binary); + ostrm << "--gtest_output=xml: mockup file\n"; + } + } + + return 0; +} diff --git a/Tests/RunCMake/MacOSVersions/MacOSVersions.cmake b/Tests/RunCMake/MacOSVersions/MacOSVersions.cmake index 629e445..fc51bd8 100644 --- a/Tests/RunCMake/MacOSVersions/MacOSVersions.cmake +++ b/Tests/RunCMake/MacOSVersions/MacOSVersions.cmake @@ -4,6 +4,6 @@ add_library(foo SHARED foo.c) set_target_properties(foo PROPERTIES VERSION 1.0 SOVERSION 1 - OSX_COMPATIBILITY_VERSION 2.1.0 - OSX_CURRENT_VERSION 3.2.1 + MACHO_COMPATIBILITY_VERSION 2.1.0 + MACHO_CURRENT_VERSION 3.2.1 ) diff --git a/Tests/SwiftOnly/CMakeLists.txt b/Tests/SwiftOnly/CMakeLists.txt index f4cbac2..e24279b 100644 --- a/Tests/SwiftOnly/CMakeLists.txt +++ b/Tests/SwiftOnly/CMakeLists.txt @@ -1,4 +1,16 @@ cmake_minimum_required(VERSION 3.3) + +# NOTE: Force the Release mode configuration as there are some issues with the +# debug information handling on macOS on certain Xcode builds. +if(NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build" FORCE) +endif() + +# NOTE: enable shared libraries by default. Older Xcode releases do not play +# well with static libraries, and Windows does not currently support static +# libraries in Swift. +set(BUILD_SHARED_LIBS YES) + project(SwiftOnly Swift) if(NOT XCODE_VERSION VERSION_LESS 10.2) @@ -7,7 +19,19 @@ elseif(NOT XCODE_VERSION VERSION_LESS 8.0) set(CMAKE_Swift_LANGUAGE_VERSION 3.0) endif() +set(CMAKE_Swift_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/swift) + add_executable(SwiftOnly main.swift) +add_library(L L.swift) + +add_library(M M.swift) +target_link_libraries(M PUBLIC + L) + +add_library(N N.swift) +target_link_libraries(N PUBLIC + M) + # Dummy to make sure generation works with such targets. add_library(SwiftIface INTERFACE) diff --git a/Tests/SwiftOnly/L.swift b/Tests/SwiftOnly/L.swift new file mode 100644 index 0000000..79ff87e --- /dev/null +++ b/Tests/SwiftOnly/L.swift @@ -0,0 +1 @@ +public let ThirtyTwo: Int = 32 diff --git a/Tests/SwiftOnly/M.swift b/Tests/SwiftOnly/M.swift new file mode 100644 index 0000000..dd333fe --- /dev/null +++ b/Tests/SwiftOnly/M.swift @@ -0,0 +1,2 @@ +import L +public let SixtyFour: Int = ThirtyTwo * 2 diff --git a/Tests/SwiftOnly/N.swift b/Tests/SwiftOnly/N.swift new file mode 100644 index 0000000..990ddf9 --- /dev/null +++ b/Tests/SwiftOnly/N.swift @@ -0,0 +1,2 @@ +import M +public let OneTwentyEight = SixtyFour * 2 @@ -17,7 +17,7 @@ cmake_extract_standard_flags() cmake_version_component() { sed -n " -/^set(CMake_VERSION_${1}/ {s/set(CMake_VERSION_${1} *\([0-9]*\))/\1/;p;} +/^set(CMake_VERSION_${1}/ {s/set(CMake_VERSION_${1} *\([0-9]*\)).*/\1/;p;} " "${cmake_source_dir}/Source/CMakeVersion.cmake" } |