diff options
46 files changed, 864 insertions, 410 deletions
diff --git a/Auxiliary/cmake-mode.el b/Auxiliary/cmake-mode.el index ddc7b40..8224d9e 100644 --- a/Auxiliary/cmake-mode.el +++ b/Auxiliary/cmake-mode.el @@ -53,6 +53,9 @@ set the path with these commands: (defconst cmake-regex-comment "#.*") (defconst cmake-regex-paren-left "(") (defconst cmake-regex-paren-right ")") +(defconst cmake-regex-closing-parens-line (concat "^[[:space:]]*\\(" + cmake-regex-paren-right + "+\\)[[:space:]]*$")) (defconst cmake-regex-argument-quoted (rx ?\" (* (or (not (any ?\" ?\\)) (and ?\\ anything))) ?\")) (defconst cmake-regex-argument-unquoted @@ -74,6 +77,8 @@ set the path with these commands: (defconst cmake-regex-close (rx-to-string `(and bol (* space) (regexp ,cmake-regex-block-close) (* space) (regexp ,cmake-regex-paren-left)))) +(defconst cmake-regex-token-paren-left (concat "^" cmake-regex-paren-left "$")) +(defconst cmake-regex-token-paren-right (concat "^" cmake-regex-paren-right "$")) ;------------------------------------------------------------------------------ @@ -130,30 +135,47 @@ set the path with these commands: (save-excursion (beginning-of-line) (let ((point-start (point)) + (closing-parens-only (looking-at cmake-regex-closing-parens-line)) (case-fold-search t) ;; case-insensitive token) - ; Search back for the last indented line. + ;; Search back for the last indented line. (cmake-find-last-indented-line) - ; Start with the indentation on this line. + ;; Start with the indentation on this line. (setq cur-indent (current-indentation)) - ; Search forward counting tokens that adjust indentation. - (while (re-search-forward cmake-regex-token point-start t) - (setq token (match-string 0)) - (when (or (string-match (concat "^" cmake-regex-paren-left "$") token) - (and (string-match cmake-regex-block-open token) - (looking-at (concat "[ \t]*" cmake-regex-paren-left)))) - (setq cur-indent (+ cur-indent cmake-tab-width))) - (when (string-match (concat "^" cmake-regex-paren-right "$") token) - (setq cur-indent (- cur-indent cmake-tab-width))) - ) - (goto-char point-start) - ;; If next token closes the block, decrease indentation - (when (looking-at cmake-regex-close) - (setq cur-indent (- cur-indent cmake-tab-width)) + (if closing-parens-only + (let ((open-parens 0)) + (while (re-search-forward cmake-regex-token point-start t) + (setq token (match-string 0)) + (cond + ((string-match cmake-regex-token-paren-left token) + (setq open-parens (+ open-parens 1))) + ((string-match cmake-regex-token-paren-right token) + (setq open-parens (- open-parens 1))))) + ;; Don't outdent if last indented line has open parens + (unless (> open-parens 0) + (setq cur-indent (- cur-indent cmake-tab-width)))) + ;; Skip detailed analysis if last indented line is a 'closing + ;; parens only line' + (unless (looking-at cmake-regex-closing-parens-line) + ;; Search forward counting tokens that adjust indentation. + (while (re-search-forward cmake-regex-token point-start t) + (setq token (match-string 0)) + (when (or (string-match cmake-regex-token-paren-left token) + (and (string-match cmake-regex-block-open token) + (looking-at (concat "[ \t]*" cmake-regex-paren-left)))) + (setq cur-indent (+ cur-indent cmake-tab-width))) + (when (string-match cmake-regex-token-paren-right token) + (setq cur-indent (- cur-indent cmake-tab-width))) + )) + (goto-char point-start) + ;; If next token closes the block, decrease indentation + (when (looking-at cmake-regex-close) + (setq cur-indent (- cur-indent cmake-tab-width)) + ) ) ) ) - ; Indent this line by the amount selected. + ;; Indent this line by the amount selected. (cmake-indent-line-to (max cur-indent 0)) ) ) diff --git a/Help/command/add_test.rst b/Help/command/add_test.rst index 95cd037..53555a4 100644 --- a/Help/command/add_test.rst +++ b/Help/command/add_test.rst @@ -20,6 +20,9 @@ if necessary. See policy :policy:`CMP0110`. The options are: automatically be replaced by the location of the executable created at build time. + The command may be specified using + :manual:`generator expressions <cmake-generator-expressions(7)>`. + ``CONFIGURATIONS`` Restrict execution of the test only to the named configurations. @@ -30,6 +33,9 @@ if necessary. See policy :policy:`CMP0110`. The options are: directory set to the build directory corresponding to the current source directory. + The working directory may be specified using + :manual:`generator expressions <cmake-generator-expressions(7)>`. + ``COMMAND_EXPAND_LISTS`` .. versionadded:: 3.16 @@ -48,9 +54,10 @@ unless the :prop_test:`PASS_REGULAR_EXPRESSION`, .. versionadded:: 3.16 Added :prop_test:`SKIP_REGULAR_EXPRESSION` property. -The ``COMMAND`` and ``WORKING_DIRECTORY`` options may use "generator -expressions" with the syntax ``$<...>``. See the -:manual:`cmake-generator-expressions(7)` manual for available expressions. +Tests added with the ``add_test(NAME)`` signature support using +:manual:`generator expressions <cmake-generator-expressions(7)>` +in test properties set by :command:`set_property(TEST)` or +:command:`set_tests_properties`. Example usage: @@ -73,10 +80,15 @@ file produced by target ``myexe``. --------------------------------------------------------------------- +This command also supports a simpler, but less flexible, signature: + .. code-block:: cmake add_test(<name> <command> [<arg>...]) -Add a test called ``<name>`` with the given command-line. Unlike -the above ``NAME`` signature no transformation is performed on the -command-line to support target names or generator expressions. +Add a test called ``<name>`` with the given command-line. + +Unlike the above ``NAME`` signature, target names are not supported +in the command-line. Furthermore, tests added with this signature do not +support :manual:`generator expressions <cmake-generator-expressions(7)>` +in the command-line or test properties. diff --git a/Help/command/define_property.rst b/Help/command/define_property.rst index cd75dea..c882347 100644 --- a/Help/command/define_property.rst +++ b/Help/command/define_property.rst @@ -13,11 +13,13 @@ Define and document custom properties. [INITIALIZE_FROM_VARIABLE <variable>]) Defines one property in a scope for use with the :command:`set_property` and -:command:`get_property` commands. This is primarily useful to associate -documentation with property names that may be retrieved with the -:command:`get_property` command. The first argument determines the kind of -scope in which the property should be used. It must be one of the -following: +:command:`get_property` commands. It is mainly useful for defining the way +a property is initialized or inherited. Historically, the command also +associated documentation with a property, but that is no longer considered a +primary use case. + +The first argument determines the kind of scope in which the property should +be used. It must be one of the following: :: @@ -56,14 +58,16 @@ out the contents to append to. The ``BRIEF_DOCS`` and ``FULL_DOCS`` options are followed by strings to be associated with the property as its brief and full documentation. -Corresponding options to the :command:`get_property` command will retrieve -the documentation. +CMake does not use this documentation other than making it available to the +project via corresponding options to the :command:`get_property` command. .. versionchanged:: 3.23 The ``BRIEF_DOCS`` and ``FULL_DOCS`` options are optional. -The ``INITIALIZE_FROM_VARIABLE`` option is followed by the name of a variable -from which to initialize the property. The variable name must end with the -property name, must have a prefix before the property name, and must not begin -with ``CMAKE_`` or ``_CMAKE_``. +.. versionadded:: 3.23 + + The ``INITIALIZE_FROM_VARIABLE`` option specifies a variable from which the + property should be initialized. It can only be used with target properties. + The ``<variable>`` name must end with the property name, must have a prefix + before the property name, and must not begin with ``CMAKE_`` or ``_CMAKE_``. diff --git a/Help/command/set_property.rst b/Help/command/set_property.rst index 555520d..b9b12c4 100644 --- a/Help/command/set_property.rst +++ b/Help/command/set_property.rst @@ -85,6 +85,10 @@ It must be one of the following: Scope may name zero or more existing tests. See also the :command:`set_tests_properties` command. + Test property values may be specified using + :manual:`generator expressions <cmake-generator-expressions(7)>` + for tests created by the :command:`add_test(NAME)` signature. + ``CACHE`` Scope must name zero or more cache existing entries. diff --git a/Help/command/set_tests_properties.rst b/Help/command/set_tests_properties.rst index 9bc94ae..eadde33 100644 --- a/Help/command/set_tests_properties.rst +++ b/Help/command/set_tests_properties.rst @@ -9,8 +9,10 @@ Set a property of the tests. Sets a property for the tests. If the test is not found, CMake will report an error. -:manual:`Generator expressions <cmake-generator-expressions(7)>` will be -expanded the same as supported by the test's :command:`add_test` call. + +Test property values may be specified using +:manual:`generator expressions <cmake-generator-expressions(7)>` +for tests created by the :command:`add_test(NAME)` signature. See also the :command:`set_property(TEST)` command. diff --git a/Help/cpack_gen/productbuild.rst b/Help/cpack_gen/productbuild.rst index dc98c85..26e0782 100644 --- a/Help/cpack_gen/productbuild.rst +++ b/Help/cpack_gen/productbuild.rst @@ -90,14 +90,15 @@ macOS using ProductBuild: .. versionadded:: 3.23 - Adds a domains element to Distribution XML if specified. When set to true, - the productbuild generator creates the following XML element: + This option enables more granular control over where the product may be + installed. When it is set to true, a ``domains`` element of the following + form will be added to the productbuild Distribution XML: .. code-block:: xml <domains enable_anywhere="true" enable_currentUserHome="false" enable_localSystem="true"/> - The default values used for the attributes can be overridden with + The default values are as shown above, but can be overridden with :variable:`CPACK_PRODUCTBUILD_DOMAINS_ANYWHERE`, :variable:`CPACK_PRODUCTBUILD_DOMAINS_USER`, and :variable:`CPACK_PRODUCTBUILD_DOMAINS_ROOT`. @@ -106,25 +107,43 @@ macOS using ProductBuild: .. versionadded:: 3.23 - May be used to override the ``enable_anywhere`` attribute in the domains - element in the Distribution XML when :variable:`CPACK_PRODUCTBUILD_DOMAINS` - is set to ``TRUE``. + May be used to override the ``enable_anywhere`` attribute in the ``domains`` + element of the Distribution XML. When set to true, the product can be + installed at the root of any volume, including non-system volumes. + + :variable:`CPACK_PRODUCTBUILD_DOMAINS` must be set to true for this variable + to have any effect. .. variable:: CPACK_PRODUCTBUILD_DOMAINS_USER .. versionadded:: 3.23 - May be used to override the ``enable_currentUserHome`` attribute in the domains - element in the Distribution XML when :variable:`CPACK_PRODUCTBUILD_DOMAINS` - is set to ``TRUE``. + May be used to override the ``enable_currentUserHome`` attribute in the + ``domains`` element of the Distribution XML. When set to true, the product + can be installed into the current user's home directory. Note that when + installing into the user's home directory, the following additional + requirements will apply: + + * The installer may not write outside the user's home directory. + * The install will be performed as the current user rather than as ``root``. + This may have ramifications for :variable:`CPACK_PREFLIGHT_<COMP>_SCRIPT` + and :variable:`CPACK_POSTFLIGHT_<COMP>_SCRIPT`. + * Administrative privileges will not be needed to perform the install. + + :variable:`CPACK_PRODUCTBUILD_DOMAINS` must be set to true for this variable + to have any effect. .. variable:: CPACK_PRODUCTBUILD_DOMAINS_ROOT .. versionadded:: 3.23 - May be used to override the ``enable_localSystem`` attribute in the domains - element in the Distribution XML when :variable:`CPACK_PRODUCTBUILD_DOMAINS` - is set to ``TRUE``. + May be used to override the ``enable_localSystem`` attribute in the + ``domains`` element of the Distribution XML. When set to true, the product + can be installed in the root directory. This should normally be set to true + unless the product should only be installed to the user's home directory. + + :variable:`CPACK_PRODUCTBUILD_DOMAINS` must be set to true for this variable + to have any effect. Background Image """""""""""""""" diff --git a/Help/guide/tutorial/Packaging an Installer.rst b/Help/guide/tutorial/Packaging an Installer.rst index 55e74e0..0ee5db2 100644 --- a/Help/guide/tutorial/Packaging an Installer.rst +++ b/Help/guide/tutorial/Packaging an Installer.rst @@ -22,7 +22,7 @@ That is all there is to it. We start by including libraries that are needed by the project for the current platform. Next we set some CPack variables to where we have stored the license and version information for this project. The version information was set earlier in this -tutorial and the ``license.txt`` has been included in the top-level source +tutorial and the ``License.txt`` has been included in the top-level source directory for this step. The :variable:`CPACK_SOURCE_GENERATOR` variable selects a file format for the source package. diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index 2394eb2..b79cf3a 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -1125,9 +1125,9 @@ Output-Related Expressions add_library(lib1 STATIC ...) add_library(lib2 ...) - target_link_libraries(lib2 PRIVATE "$<LINK_LIBRARY:whole_archive,lib1>") + target_link_libraries(lib2 PRIVATE "$<LINK_LIBRARY:load_archive,lib1>") - This specify to use the ``lib1`` target with feature ``whole_archive`` for + This specify to use the ``lib1`` target with feature ``load_archive`` for linking target ``lib2``. The feature must have be defined by :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>` variable or, if :variable:`CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED` is false, diff --git a/Help/release/3.23.rst b/Help/release/3.23.rst index 69b935d..285a471 100644 --- a/Help/release/3.23.rst +++ b/Help/release/3.23.rst @@ -182,7 +182,9 @@ CPack :variable:`CPACK_PRODUCTBUILD_DOMAINS_ANYWHERE`, :variable:`CPACK_PRODUCTBUILD_DOMAINS_USER`, and :variable:`CPACK_PRODUCTBUILD_DOMAINS_ROOT` variables for - adding the domains element to the Distribution XML. + adding the domains element to the Distribution XML. With these variables, + it is now possible to install products to the user's home directory + without requiring administrative privileges. * The :cpack_gen:`CPack productbuild Generator` gained a new variable, :variable:`CPACK_PRODUCTBUILD_IDENTIFIER`, used to customize the unique diff --git a/Help/release/dev/LINK_LIBRARY-WHOLE_ARCHIVE.rst b/Help/release/dev/LINK_LIBRARY-WHOLE_ARCHIVE.rst new file mode 100644 index 0000000..abaf3a9 --- /dev/null +++ b/Help/release/dev/LINK_LIBRARY-WHOLE_ARCHIVE.rst @@ -0,0 +1,14 @@ +LINK_LIBRARY-WHOLE_ARCHIVE +-------------------------- + +* The :genex:`LINK_LIBRARY` generator expression gained the feature + ``WHOLE_ARCHIVE`` to force load of all members in a static library. This + feature is supported on the following target platforms: + + * all ``Apple`` variants + * ``Linux`` + * all ``BSD`` variants + * ``SunOS`` + * ``Windows`` + * ``CYGWIN`` + * ``MSYS`` diff --git a/Help/release/dev/ghs_predefined_targets.rst b/Help/release/dev/ghs_predefined_targets.rst new file mode 100644 index 0000000..eeca5a9 --- /dev/null +++ b/Help/release/dev/ghs_predefined_targets.rst @@ -0,0 +1,6 @@ +ghs_predefined_targets +---------------------- + +* A new predefined target `RERUN_CMAKE` is added for + :generator:`Green Hills MULTI` generator to easily rerun + CMake if any CMake files were updated. diff --git a/Help/variable/CMAKE_LINK_LIBRARY_USING_FEATURE.txt b/Help/variable/CMAKE_LINK_LIBRARY_USING_FEATURE.txt index ad393b0..ec293d3 100644 --- a/Help/variable/CMAKE_LINK_LIBRARY_USING_FEATURE.txt +++ b/Help/variable/CMAKE_LINK_LIBRARY_USING_FEATURE.txt @@ -46,27 +46,27 @@ is offered by various environments but with a specific syntax: .. code-block:: cmake - set(CMAKE_C_LINK_LIBRARY_USING_whole_archive_SUPPORTED TRUE) + set(CMAKE_C_LINK_LIBRARY_USING_load_archive_SUPPORTED TRUE) if(CMAKE_C_COMPILER_ID STREQUAL "AppleClang") - set(CMAKE_C_LINK_LIBRARY_USING_whole_archive "-force_load <LIB_ITEM>") + set(CMAKE_C_LINK_LIBRARY_USING_load_archive "-force_load <LIB_ITEM>") elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_SYSTEM_NAME STREQUAL "Linux") - set(CMAKE_C_LINK_LIBRARY_USING_whole_archive "LINKER:--push-state,--whole-archive" - "<LINK_ITEM>" - "LINKER:--pop-state") + set(CMAKE_C_LINK_LIBRARY_USING_load_archive "LINKER:--push-state,--whole-archive" + "<LINK_ITEM>" + "LINKER:--pop-state") elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC") - set(CMAKE_C_LINK_LIBRARY_USING_whole_archive "/WHOLEARCHIVE:<LIBRARY>") + set(CMAKE_C_LINK_LIBRARY_USING_load_archive "/WHOLEARCHIVE:<LIBRARY>") else() # feature not yet supported for the other environments - set(CMAKE_C_LINK_LIBRARY_USING_whole_archive_SUPPORTED FALSE) + set(CMAKE_C_LINK_LIBRARY_USING_load_archive_SUPPORTED FALSE) endif() add_library(lib1 STATIC ...) add_library(lib2 SHARED ...) - if(CMAKE_C_LINK_LIBRARY_USING_whole_archive_SUPPORTED) + if(CMAKE_C_LINK_LIBRARY_USING_load_archive_SUPPORTED) target_link_libraries(lib2 PRIVATE - "$<LINK_LIBRARY:whole_archive,lib1,$<IF:$<LINK_LANG_AND_ID:C,Clang>,libexternal.a,external>>") + "$<LINK_LIBRARY:load_archive,lib1,$<IF:$<LINK_LANG_AND_ID:C,Clang>,libexternal.a,external>>") else() target_link_libraries(lib2 PRIVATE lib1 external) endif() diff --git a/Help/variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt b/Help/variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt index 936bd31..e4fa0ed8 100644 --- a/Help/variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt +++ b/Help/variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt @@ -5,6 +5,24 @@ useful with :prop_tgt:`LINK_LIBRARY_OVERRIDE` and :prop_tgt:`LINK_LIBRARY_OVERRIDE_<LIBRARY>` target properties. +**Features available for a subset of environments** + +``WHOLE_ARCHIVE`` + Force load of all members in a static library. + + Target platforms supported: all ``Apple`` variants, ``Linux``, all ``BSD`` + variants, ``SunOS``, ``Windows``, ``CYGWIN``, and ``MSYS``. + + Platform-specific notes: + + * On Apple platforms, the library must be specified as a CMake target name, a + library file name (such as ``libfoo.a``), or a library file path (such as + ``/path/to/libfoo.a``). It cannot be specified as a plain library name + (such as ``foo``, where ``foo`` is not CMake target), due to a limitation + in the Apple linker. + * On Windows platforms, for ``MSVC`` or MSVC-like toolchains, the version + must be greater than ``1900``. + **Features available in Apple environments** It is assumed that the linker used is the one provided by `XCode` or is diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake index f68c4b2..66020e8 100644 --- a/Modules/CMakeDetermineCUDACompiler.cmake +++ b/Modules/CMakeDetermineCUDACompiler.cmake @@ -260,11 +260,11 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) set(nvcc_test_flags "--keep --keep-dir tmp") if(CMAKE_CUDA_HOST_COMPILER) string(APPEND nvcc_test_flags " -ccbin=\"${CMAKE_CUDA_HOST_COMPILER}\"") - - # If the user has specified a host compiler we should fail instead of trying without. - # Succeeding detection without may result in confusing errors later on, see #21076. - set(CMAKE_CUDA_COMPILER_ID_REQUIRE_SUCCESS ON) endif() + # If we have extracted the vendor as NVIDIA we should require detection to + # work. If we don't, users will get confusing errors later about failure + # to detect a default value for CMAKE_CUDA_ARCHITECTURES + set(CMAKE_CUDA_COMPILER_ID_REQUIRE_SUCCESS ON) elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "Clang") set(clang_test_flags "--cuda-path=\"${CMAKE_CUDA_COMPILER_LIBRARY_ROOT}\"") if(CMAKE_CROSSCOMPILING) diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake index 7ecc9d4..afdd4c4 100644 --- a/Modules/FindCUDAToolkit.cmake +++ b/Modules/FindCUDAToolkit.cmake @@ -938,7 +938,7 @@ if(CUDAToolkit_FOUND) # cuFFTW depends on cuFFT _CUDAToolkit_find_and_add_import_lib(cufftw DEPS cufft) - _CUDAToolkit_find_and_add_import_lib(cufftw DEPS cufft_static) + _CUDAToolkit_find_and_add_import_lib(cufftw_static DEPS cufft_static) if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 9.2) _CUDAToolkit_find_and_add_import_lib(cufft_static_nocallback DEPS culibos) endif() diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake index 17c1fa1..81bc473 100644 --- a/Modules/FindMatlab.cmake +++ b/Modules/FindMatlab.cmake @@ -769,6 +769,10 @@ function(matlab_get_version_from_matlab_run matlab_binary_program matlab_list_ve set(devnull INPUT_FILE NUL) endif() + # we first try to run a simple program using the -r option, and then we use the + # -batch option that is supported and recommended since R2019a + set(_matlab_get_version_failed_with_r_option FALSE) + # timeout set to 120 seconds, in case it does not start # note as said before OUTPUT_VARIABLE cannot be used in a platform # independent manner however, not setting it would flush the output of Matlab @@ -786,21 +790,57 @@ function(matlab_get_version_from_matlab_run matlab_binary_program matlab_list_ve if(_matlab_result_version_call MATCHES "timeout") if(MATLAB_FIND_DEBUG) message(WARNING "[MATLAB] Unable to determine the version of Matlab." - " Matlab call timed out after 120 seconds.") + " Matlab call with -r option timed out after 120 seconds.") endif() - return() + set(_matlab_get_version_failed_with_r_option TRUE) endif() - if(${_matlab_result_version_call}) + if(NOT ${_matlab_get_version_failed_with_r_option} AND ${_matlab_result_version_call}) if(MATLAB_FIND_DEBUG) - message(WARNING "[MATLAB] Unable to determine the version of Matlab. Matlab call returned with error ${_matlab_result_version_call}.") + message(WARNING "[MATLAB] Unable to determine the version of Matlab. Matlab call with -r option returned with error ${_matlab_result_version_call}.") endif() - return() - elseif(NOT EXISTS "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp") + set(_matlab_get_version_failed_with_r_option TRUE) + elseif(NOT ${_matlab_get_version_failed_with_r_option} AND NOT EXISTS "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp") if(MATLAB_FIND_DEBUG) message(WARNING "[MATLAB] Unable to determine the version of Matlab. The log file does not exist.") endif() - return() + set(_matlab_get_version_failed_with_r_option TRUE) + endif() + + if(_matlab_get_version_failed_with_r_option) + execute_process( + COMMAND "${matlab_binary_program}" -nosplash -nojvm ${_matlab_additional_commands} -logfile "matlabVersionLog.cmaketmp" -nodesktop -nodisplay -batch "version, exit" + OUTPUT_VARIABLE _matlab_version_from_cmd_dummy_batch + RESULT_VARIABLE _matlab_result_version_call_batch + ERROR_VARIABLE _matlab_result_version_call_error_batch + TIMEOUT 120 + WORKING_DIRECTORY "${_matlab_temporary_folder}" + ${devnull} + ) + + if(_matlab_result_version_call_batch MATCHES "timeout") + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Unable to determine the version of Matlab." + " Matlab call with -batch option timed out after 120 seconds.") + endif() + return() + endif() + + if(${_matlab_result_version_call_batch}) + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Command executed \"${matlab_binary_program}\" -nosplash -nojvm ${_matlab_additional_commands} -logfile \"matlabVersionLog.cmaketmp\" -nodesktop -nodisplay -batch \"version, exit\"") + message(WARNING "_matlab_version_from_cmd_dummy_batch (OUTPUT_VARIABLE): ${_matlab_version_from_cmd_dummy_batch}") + message(WARNING "_matlab_result_version_call_batch (RESULT_VARIABLE): ${_matlab_result_version_call_batch}") + message(WARNING "_matlab_result_version_call_error_batch (ERROR_VARIABLE): ${_matlab_result_version_call_error_batch}") + message(WARNING "[MATLAB] Unable to determine the version of Matlab. Matlab call with -batch option returned with error ${_matlab_result_version_call_batch}.") + endif() + return() + elseif(NOT ${_matlab_get_version_failed_with_r_option} AND NOT EXISTS "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp") + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Unable to determine the version of Matlab. The log file does not exist.") + endif() + return() + endif() endif() # if successful, read back the log @@ -928,6 +968,16 @@ function(matlab_add_unit_test) message(FATAL_ERROR "[MATLAB] The Matlab test name cannot be empty") endif() + # The option to run a batch program with MATLAB changes depending on the MATLAB version + # For MATLAB before R2019a (9.6), the only supported option is -r, afterwords the suggested option + # is -batch as -r is deprecated + set(maut_BATCH_OPTION "-r") + if(NOT (Matlab_VERSION_STRING STREQUAL "")) + if(Matlab_VERSION_STRING VERSION_GREATER_EQUAL "9.6") + set(maut_BATCH_OPTION "-batch") + endif() + endif() + add_test(NAME ${${prefix}_NAME} COMMAND ${CMAKE_COMMAND} "-Dtest_name=${${prefix}_NAME}" @@ -941,6 +991,7 @@ function(matlab_add_unit_test) "-Dunittest_file_to_run=${${prefix}_UNITTEST_FILE}" "-Dcustom_Matlab_test_command=${${prefix}_CUSTOM_TEST_COMMAND}" "-Dcmd_to_run_before_test=${${prefix}_UNITTEST_PRECOMMAND}" + "-Dmaut_BATCH_OPTION=${maut_BATCH_OPTION}" -P ${_FindMatlab_SELF_DIR}/MatlabTestsRedirect.cmake ${${prefix}_TEST_ARGS} ${${prefix}_UNPARSED_ARGUMENTS} diff --git a/Modules/Internal/CPack/CPack.distribution.dist.in b/Modules/Internal/CPack/CPack.distribution.dist.in index f20e66c..291b24d 100644 --- a/Modules/Internal/CPack/CPack.distribution.dist.in +++ b/Modules/Internal/CPack/CPack.distribution.dist.in @@ -1,9 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <installer-gui-script minSpecVersion="1.0"> - <title>@CPACK_PACKAGE_NAME@</title> - <welcome file="@CPACK_RESOURCE_FILE_WELCOME_NOPATH@"/> - <readme file="@CPACK_RESOURCE_FILE_README_NOPATH@"/> - <license file="@CPACK_RESOURCE_FILE_LICENSE_NOPATH@"/> - <options allow-external-scripts="no" customize="allow" rootVolumeOnly="false"></options> - @CPACK_PACKAGEMAKER_CHOICES@ + <title>@CPACK_PACKAGE_NAME@</title> + <welcome file="@CPACK_RESOURCE_FILE_WELCOME_NOPATH@"/> + <readme file="@CPACK_RESOURCE_FILE_README_NOPATH@"/> + <license file="@CPACK_RESOURCE_FILE_LICENSE_NOPATH@"/> +@CPACK_APPLE_PKG_INSTALLER_CONTENT@ </installer-gui-script> diff --git a/Modules/Internal/CPack/NSIS.template.in b/Modules/Internal/CPack/NSIS.template.in index e3abf22..23c45c7 100644 --- a/Modules/Internal/CPack/NSIS.template.in +++ b/Modules/Internal/CPack/NSIS.template.in @@ -931,9 +931,11 @@ Function .onInit ;Run the uninstaller uninst: ClearErrors - StrLen $2 "\@CPACK_NSIS_UNINSTALL_NAME@.exe" - StrCpy $3 $0 -$2 # remove "\@CPACK_NSIS_UNINSTALL_NAME@.exe" from UninstallString to get path - ExecWait '"$0" /S _?=$3' ;Do not copy the uninstaller to a temp file + StrCpy $2 $0 1 + StrCmp '"' $2 0 +3 ; checks if string is quoted (CPack before v3.20.6 did not quote it) + ExecWait '$0 /S' + Goto +2 + ExecWait '"$0" /S' IfErrors uninst_failed inst uninst_failed: diff --git a/Modules/MatlabTestsRedirect.cmake b/Modules/MatlabTestsRedirect.cmake index fc36fc3..d651cdd 100644 --- a/Modules/MatlabTestsRedirect.cmake +++ b/Modules/MatlabTestsRedirect.cmake @@ -15,6 +15,7 @@ # -Dcustom_Matlab_test_command="" # -Dcmd_to_run_before_test="" # -Dunittest_file_to_run +# -Dmaut_BATCH_OPTION="-batch" # -P FindMatlab_TestsRedirect.cmake set(Matlab_UNIT_TESTS_CMD -nosplash -nodesktop -nodisplay ${Matlab_ADDITIONAL_STARTUP_OPTIONS}) @@ -84,7 +85,7 @@ execute_process( # Do not use a full path to log file. Depend on the fact that the log file # is always going to go in the working_directory. This is because matlab # on unix is a shell script that does not handle spaces in the logfile path. - COMMAND "${Matlab_PROGRAM}" ${Matlab_UNIT_TESTS_CMD} -logfile "${log_file_name}" -r "${Matlab_SCRIPT_TO_RUN}" + COMMAND "${Matlab_PROGRAM}" ${Matlab_UNIT_TESTS_CMD} -logfile "${log_file_name}" "${maut_BATCH_OPTION}" "${Matlab_SCRIPT_TO_RUN}" RESULT_VARIABLE res ${test_timeout} OUTPUT_QUIET # we do not want the output twice diff --git a/Modules/Platform/CYGWIN-GNU.cmake b/Modules/Platform/CYGWIN-GNU.cmake index b81bd4d..ef64012 100644 --- a/Modules/Platform/CYGWIN-GNU.cmake +++ b/Modules/Platform/CYGWIN-GNU.cmake @@ -14,6 +14,34 @@ string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " -Wl,--enable-auto-import") set(CMAKE_GNULD_IMAGE_VERSION "-Wl,--major-image-version,<TARGET_VERSION_MAJOR>,--minor-image-version,<TARGET_VERSION_MINOR>") set(CMAKE_GENERATOR_RC windres) + + +# Features for LINK_LIBRARY generator expression +## check linker capabilities +if(NOT DEFINED _CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + execute_process(COMMAND "${CMAKE_LINKER}" --help + OUTPUT_VARIABLE __linker_help + ERROR_VARIABLE __linker_help) + if(__linker_help MATCHES "--push-state" AND __linker_help MATCHES "--pop-state") + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED TRUE CACHE INTERNAL "linker supports push/pop state") + else() + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED FALSE CACHE INTERNAL "linker supports push/pop state") + endif() + unset(__linker_help) +endif() +## WHOLE_ARCHIVE: Force loading all members of an archive +if(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--push-state,--whole-archive" + "<LINK_ITEM>" + "LINKER:--pop-state") +else() + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--whole-archive" + "<LINK_ITEM>" + "LINKER:--no-whole-archive") +endif() +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) + + macro(__cygwin_compiler_gnu lang) # Binary link rules. set(CMAKE_${lang}_CREATE_SHARED_MODULE diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake index a27bb36..ec88a37 100644 --- a/Modules/Platform/Darwin.cmake +++ b/Modules/Platform/Darwin.cmake @@ -108,7 +108,7 @@ foreach(lang C CXX Fortran OBJC OBJCXX) set(CMAKE_${lang}_FRAMEWORK_SEARCH_FLAG -F) endforeach() -# Defines link features for frameworks +# Defines LINK_LIBRARY features for frameworks set(CMAKE_LINK_LIBRARY_USING_FRAMEWORK "LINKER:-framework,<LIBRARY>") set(CMAKE_LINK_LIBRARY_USING_FRAMEWORK_SUPPORTED TRUE) @@ -121,7 +121,7 @@ set(CMAKE_LINK_LIBRARY_USING_REEXPORT_FRAMEWORK_SUPPORTED TRUE) set(CMAKE_LINK_LIBRARY_USING_WEAK_FRAMEWORK "LINKER:-weak_framework,<LIBRARY>") set(CMAKE_LINK_LIBRARY_USING_WEAK_FRAMEWORK_SUPPORTED TRUE) -# Defines link features for libraries +# Defines LINK_LIBRARY features for libraries set(CMAKE_LINK_LIBRARY_USING_NEEDED_LIBRARY "PATH{LINKER:-needed_library <LIBRARY>}NAME{LINKER:-needed-l<LIB_ITEM>}") set(CMAKE_LINK_LIBRARY_USING_NEEDED_LIBRARY_SUPPORTED TRUE) @@ -131,6 +131,10 @@ set(CMAKE_LINK_LIBRARY_USING_REEXPORT_LIBRARY_SUPPORTED TRUE) set(CMAKE_LINK_LIBRARY_USING_WEAK_LIBRARY "PATH{LINKER:-weak_library <LIBRARY>}NAME{LINKER:-weak-l<LIB_ITEM>}") set(CMAKE_LINK_LIBRARY_USING_WEAK_LIBRARY_SUPPORTED TRUE) +# Defines LINK_LIBRARY feature to Force loading of all members of an archive +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:-force_load <LIB_ITEM>") +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) + # default to searching for frameworks first if(NOT DEFINED CMAKE_FIND_FRAMEWORK) set(CMAKE_FIND_FRAMEWORK FIRST) diff --git a/Modules/Platform/FreeBSD.cmake b/Modules/Platform/FreeBSD.cmake index 4a4c00d..4c8cb6a 100644 --- a/Modules/Platform/FreeBSD.cmake +++ b/Modules/Platform/FreeBSD.cmake @@ -26,4 +26,31 @@ foreach(type SHARED_LIBRARY SHARED_MODULE EXE) set(CMAKE_${type}_LINK_DYNAMIC_C_FLAGS "-Wl,-Bdynamic") endforeach() + +# Features for LINK_LIBRARY generator expression +## check linker capabilities +if(NOT DEFINED _CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + execute_process(COMMAND "${CMAKE_LINKER}" --help + OUTPUT_VARIABLE __linker_help + ERROR_VARIABLE __linker_help) + if(__linker_help MATCHES "--push-state" AND __linker_help MATCHES "--pop-state") + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED TRUE CACHE INTERNAL "linker supports push/pop state") + else() + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED FALSE CACHE INTERNAL "linker supports push/pop state") + endif() + unset(__linker_help) +endif() +## WHOLE_ARCHIVE: Force loading all members of an archive +if(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--push-state,--whole-archive" + "<LINK_ITEM>" + "LINKER:--pop-state") +else() + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--whole-archive" + "<LINK_ITEM>" + "LINKER:--no-whole-archive") +endif() +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) + + include(Platform/UnixPaths) diff --git a/Modules/Platform/GHS-MULTI.cmake b/Modules/Platform/GHS-MULTI.cmake index 60a15c4..5b28f29 100644 --- a/Modules/Platform/GHS-MULTI.cmake +++ b/Modules/Platform/GHS-MULTI.cmake @@ -13,5 +13,3 @@ set(GHSMULTI 1) set(CMAKE_FIND_LIBRARY_PREFIXES "") set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") - -include(Platform/WindowsPaths) diff --git a/Modules/Platform/Linux.cmake b/Modules/Platform/Linux.cmake index 95102e1..a7e58ab 100644 --- a/Modules/Platform/Linux.cmake +++ b/Modules/Platform/Linux.cmake @@ -20,6 +20,31 @@ foreach(type SHARED_LIBRARY SHARED_MODULE EXE) endforeach() +# Features for LINK_LIBRARY generator expression +## check linker capabilities +if(NOT DEFINED _CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + execute_process(COMMAND "${CMAKE_LINKER}" --help + OUTPUT_VARIABLE __linker_help + ERROR_VARIABLE __linker_help) + if(__linker_help MATCHES "--push-state" AND __linker_help MATCHES "--pop-state") + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED TRUE CACHE INTERNAL "linker supports push/pop state") + else() + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED FALSE CACHE INTERNAL "linker supports push/pop state") + endif() + unset(__linker_help) +endif() +## WHOLE_ARCHIVE: Force loading all members of an archive +if(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--push-state,--whole-archive" + "<LINK_ITEM>" + "LINKER:--pop-state") +else() + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--whole-archive" + "<LINK_ITEM>" + "LINKER:--no-whole-archive") +endif() +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) + # Features for LINK_GROUP generator expression ## RESCAN: request the linker to rescan static libraries until there is ## no pending undefined symbols diff --git a/Modules/Platform/NetBSD.cmake b/Modules/Platform/NetBSD.cmake index d99cb4a..8774159 100644 --- a/Modules/Platform/NetBSD.cmake +++ b/Modules/Platform/NetBSD.cmake @@ -12,4 +12,31 @@ set(CMAKE_SHARED_LIBRARY_RPATH_LINK_C_FLAG "-Wl,-rpath-link,") set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-Wl,-soname,") set(CMAKE_EXE_EXPORTS_C_FLAG "-Wl,--export-dynamic") + +# Features for LINK_LIBRARY generator expression +## check linker capabilities +if(NOT DEFINED _CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + execute_process(COMMAND "${CMAKE_LINKER}" --help + OUTPUT_VARIABLE __linker_help + ERROR_VARIABLE __linker_help) + if(__linker_help MATCHES "--push-state" AND __linker_help MATCHES "--pop-state") + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED TRUE CACHE INTERNAL "linker supports push/pop state") + else() + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED FALSE CACHE INTERNAL "linker supports push/pop state") + endif() + unset(__linker_help) +endif() +## WHOLE_ARCHIVE: Force loading all members of an archive +if(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--push-state,--whole-archive" + "<LINK_ITEM>" + "LINKER:--pop-state") +else() + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--whole-archive" + "<LINK_ITEM>" + "LINKER:--no-whole-archive") +endif() +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) + + include(Platform/UnixPaths) diff --git a/Modules/Platform/SunOS.cmake b/Modules/Platform/SunOS.cmake index e01e892..b8a302c 100644 --- a/Modules/Platform/SunOS.cmake +++ b/Modules/Platform/SunOS.cmake @@ -8,6 +8,20 @@ if(CMAKE_SYSTEM MATCHES "SunOS-4") endif() +# Features for LINK_LIBRARY generator expression +## WHOLE_ARCHIVE: Force loading all members of an archive +if (CMAKE_SYSTEM_VERSION VERSION_GREATER "5.10") + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--whole-archive" + "<LINK_ITEM>" + "LINKER:--no-whole-archive") +else() + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:-z,allextract" + "<LINK_ITEM>" + "LINKER:-z,defaultextract") +endif() +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) + + # Features for LINK_GROUP generator expression if (CMAKE_SYSTEM_VERSION VERSION_GREATER "5.9") ## RESCAN: request the linker to rescan static libraries until there is diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake index e7e975d..7600c8d 100644 --- a/Modules/Platform/Windows-Clang.cmake +++ b/Modules/Platform/Windows-Clang.cmake @@ -113,6 +113,13 @@ macro(__windows_compiler_clang_gnu lang) string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_LOWER) set(CMAKE_${lang}_STANDARD_LIBRARIES_INIT "-lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -loldnames") + # Features for LINK_LIBRARY generator expression + if(MSVC_VERSION GREATER "1900") + ## WHOLE_ARCHIVE: Force loading all members of an archive + set(CMAKE_${lang}_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:/WHOLEARCHIVE:<LIBRARY>") + set(CMAKE_${lang}_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) + endif() + enable_language(RC) endmacro() diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake index 3c24c21..b464169 100644 --- a/Modules/Platform/Windows-GNU.cmake +++ b/Modules/Platform/Windows-GNU.cmake @@ -45,6 +45,31 @@ if("${_help}" MATCHES "GNU ld .* 2\\.1[1-6]") endif() +# Features for LINK_LIBRARY generator expression +## check linker capabilities +if(NOT DEFINED _CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + execute_process(COMMAND "${CMAKE_LINKER}" --help + OUTPUT_VARIABLE __linker_help + ERROR_VARIABLE __linker_help) + if(__linker_help MATCHES "--push-state" AND __linker_help MATCHES "--pop-state") + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED TRUE CACHE INTERNAL "linker supports push/pop state") + else() + set(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED FALSE CACHE INTERNAL "linker supports push/pop state") + endif() + unset(__linker_help) +endif() +## WHOLE_ARCHIVE: Force loading all members of an archive +if(_CMAKE_LINKER_PUSHPOP_STATE_SUPPORTED) + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--push-state,--whole-archive" + "<LINK_ITEM>" + "LINKER:--pop-state") +else() + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:--whole-archive" + "<LINK_ITEM>" + "LINKER:--no-whole-archive") +endif() +set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) + # Features for LINK_GROUP generator expression ## RESCAN: request the linker to rescan static libraries until there is ## no pending undefined symbols diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index b2cc6f4..e74ec9e 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -331,6 +331,15 @@ else() endif() unset(__WINDOWS_MSVC_CMP0091) + +# Features for LINK_LIBRARY generator expression +if(MSVC_VERSION GREATER "1900") + ## WHOLE_ARCHIVE: Force loading all members of an archive + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "/WHOLEARCHIVE:<LIBRARY>") + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) +endif() + + macro(__windows_compiler_msvc lang) if(NOT MSVC_VERSION LESS 1400) # for 2005 make sure the manifest is put in the dll with mt diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index cdc2e96..fc6fc5f 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 23) -set(CMake_VERSION_PATCH 20220318) +set(CMake_VERSION_PATCH 20220322) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx index d8095cc..2a14ccf 100644 --- a/Source/CPack/cmCPackPKGGenerator.cxx +++ b/Source/CPack/cmCPackPKGGenerator.cxx @@ -120,10 +120,20 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile, std::string distributionFile = cmStrCat(metapackageFile, "/Contents/distribution.dist"); + std::ostringstream xContents; + cmXMLWriter xout(xContents, 1); + + // Installer-wide options + xout.StartElement("options"); + xout.Attribute("allow-external-scripts", "no"); + xout.Attribute("customize", "allow"); + if (cmIsOff(this->GetOption("CPACK_PRODUCTBUILD_DOMAINS"))) { + xout.Attribute("rootVolumeOnly", "false"); + } + xout.EndElement(); + // Create the choice outline, which provides a tree-based view of // the components in their groups. - std::ostringstream choiceOut; - cmXMLWriter xout(choiceOut, 1); xout.StartElement("choices-outline"); // Emit the outline for the groups @@ -169,7 +179,7 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile, // Dark Aqua this->CreateBackground("darkAqua", metapackageFile, genName, xout); - this->SetOption("CPACK_PACKAGEMAKER_CHOICES", choiceOut.str()); + this->SetOption("CPACK_APPLE_PKG_INSTALLER_CONTENT", xContents.str()); // Create the distribution.dist file in the metapackage to turn it // into a distribution package. @@ -293,8 +303,7 @@ void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component, void cmCPackPKGGenerator::CreateDomains(cmXMLWriter& xout) { - std::string opt = "CPACK_PRODUCTBUILD_DOMAINS"; - if (cmIsOff(this->GetOption(opt))) { + if (cmIsOff(this->GetOption("CPACK_PRODUCTBUILD_DOMAINS"))) { return; } @@ -302,19 +311,19 @@ void cmCPackPKGGenerator::CreateDomains(cmXMLWriter& xout) // Product can be installed at the root of any volume by default // unless specified - cmValue param = this->GetOption(cmStrCat(opt, "_ANYWHERE")); + cmValue param = this->GetOption("CPACK_PRODUCTBUILD_DOMAINS_ANYWHERE"); xout.Attribute("enable_anywhere", (param && cmIsOff(param)) ? "false" : "true"); // Product cannot be installed into the current user's home directory // by default unless specified - param = this->GetOption(cmStrCat(opt, "_USER")); + param = this->GetOption("CPACK_PRODUCTBUILD_DOMAINS_USER"); xout.Attribute("enable_currentUserHome", (param && cmIsOn(param)) ? "true" : "false"); // Product can be installed into the root directory by default // unless specified - param = this->GetOption(cmStrCat(opt, "_ROOT")); + param = this->GetOption("CPACK_PRODUCTBUILD_DOMAINS_ROOT"); xout.Attribute("enable_localSystem", (param && cmIsOff(param)) ? "false" : "true"); diff --git a/Source/cmDefinePropertyCommand.cxx b/Source/cmDefinePropertyCommand.cxx index 7a2f34f..15b2652 100644 --- a/Source/cmDefinePropertyCommand.cxx +++ b/Source/cmDefinePropertyCommand.cxx @@ -97,20 +97,20 @@ bool cmDefinePropertyCommand(std::vector<std::string> const& args, PropertyName, "\"")); return false; } - } - // Make sure the variable is not reserved. - static constexpr const char* reservedPrefixes[] = { - "CMAKE_", - "_CMAKE_", - }; - if (std::any_of(std::begin(reservedPrefixes), std::end(reservedPrefixes), - [&initializeFromVariable](const char* prefix) { - return cmHasPrefix(initializeFromVariable, prefix); - })) { - status.SetError( - cmStrCat("variable name \"", initializeFromVariable, "\" is reserved")); - return false; + // Make sure the variable is not reserved. + static constexpr const char* reservedPrefixes[] = { + "CMAKE_", + "_CMAKE_", + }; + if (std::any_of(std::begin(reservedPrefixes), std::end(reservedPrefixes), + [&initializeFromVariable](const char* prefix) { + return cmHasPrefix(initializeFromVariable, prefix); + })) { + status.SetError(cmStrCat("variable name \"", initializeFromVariable, + "\" is reserved")); + return false; + } } // Actually define the property. diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index a2d64aa..a7796c9 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -107,12 +107,6 @@ void cmGhsMultiTargetGenerator::Generate() return; } - // Tell the global generator the name of the project file - this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME", - this->Name); - this->GeneratorTarget->Target->SetProperty( - "GENERATOR_FILE_NAME_EXT", GhsMultiGpj::GetGpjTag(this->TagType)); - this->GenerateTarget(); } @@ -121,7 +115,14 @@ void cmGhsMultiTargetGenerator::GenerateTarget() // Open the target file in copy-if-different mode. std::string fproj = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/', - this->Name, cmGlobalGhsMultiGenerator::FILE_EXTENSION); + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), + '/', this->Name, cmGlobalGhsMultiGenerator::FILE_EXTENSION); + + // Tell the global generator the name of the project file + this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME", fproj); + this->GeneratorTarget->Target->SetProperty( + "GENERATOR_FILE_NAME_EXT", GhsMultiGpj::GetGpjTag(this->TagType)); + cmGeneratedFileStream fout(fproj); fout.SetCopyIfDifferent(true); @@ -155,10 +156,16 @@ void cmGhsMultiTargetGenerator::WriteTargetSpecifics(std::ostream& fout, { std::string outpath; + /* Determine paths from the target project file to where the output artifacts + * need to be located. + */ if (this->TagType != GhsMultiGpj::SUBPROJECT) { // set target binary file destination - outpath = this->GeneratorTarget->GetDirectory(config); - outpath = this->LocalGenerator->MaybeRelativeToCurBinDir(outpath); + std::string binpath = cmStrCat( + this->LocalGenerator->GetCurrentBinaryDirectory(), '/', + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget)); + outpath = cmSystemTools::RelativePath( + binpath, this->GeneratorTarget->GetDirectory(config)); /* clang-format off */ fout << " :binDirRelative=\"" << outpath << "\"\n" " -o \"" << this->TargetNameReal << "\"\n"; @@ -166,7 +173,7 @@ void cmGhsMultiTargetGenerator::WriteTargetSpecifics(std::ostream& fout, } // set target object file destination - outpath = this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); + outpath = "."; fout << " :outputDirRelative=\"" << outpath << "\"\n"; } @@ -576,11 +583,12 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj) // Open the filestream in copy-if-different mode. std::string gname = sg; cmsys::SystemTools::ReplaceString(gname, "\\", "_"); - std::string lpath = cmStrCat( - this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), '/', - gname, cmGlobalGhsMultiGenerator::FILE_EXTENSION); + std::string lpath = + cmStrCat(gname, cmGlobalGhsMultiGenerator::FILE_EXTENSION); std::string fpath = cmStrCat( - this->LocalGenerator->GetCurrentBinaryDirectory(), '/', lpath); + this->LocalGenerator->GetCurrentBinaryDirectory(), '/', + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), '/', + lpath); cmGeneratedFileStream* f = new cmGeneratedFileStream(fpath); f->SetCopyIfDifferent(true); gfiles.push_back(f); diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index 5e51dd2..f405a04 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -2,14 +2,19 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalGhsMultiGenerator.h" +#include <algorithm> +#include <functional> #include <map> -#include <ostream> +#include <sstream> #include <utility> #include <cm/memory> #include <cm/string> #include <cmext/algorithm> +#include <cmext/memory> +#include "cmCustomCommand.h" +#include "cmCustomCommandLines.h" #include "cmDocumentationEntry.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" @@ -18,10 +23,13 @@ #include "cmLocalGhsMultiGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmPolicies.h" +#include "cmSourceFile.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmTarget.h" #include "cmValue.h" #include "cmVersion.h" #include "cmake.h" @@ -32,6 +40,8 @@ const char* cmGlobalGhsMultiGenerator::DEFAULT_BUILD_PROGRAM = "gbuild"; #elif defined(_WIN32) const char* cmGlobalGhsMultiGenerator::DEFAULT_BUILD_PROGRAM = "gbuild.exe"; #endif +const char* cmGlobalGhsMultiGenerator::CHECK_BUILD_SYSTEM_TARGET = + "RERUN_CMAKE"; cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator(cmake* cm) : cmGlobalGenerator(cm) @@ -279,7 +289,7 @@ void cmGlobalGhsMultiGenerator::WriteTopLevelProject(std::ostream& fout, { this->WriteFileHeader(fout); this->WriteMacros(fout, root); - this->WriteHighLevelDirectives(root, fout); + this->WriteHighLevelDirectives(fout, root); GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fout); fout << "# Top Level Project File\n"; @@ -308,9 +318,13 @@ void cmGlobalGhsMultiGenerator::WriteTopLevelProject(std::ostream& fout, } void cmGlobalGhsMultiGenerator::WriteSubProjects(std::ostream& fout, - std::string& all_target) + bool filterPredefined) { - fout << "CMakeFiles/" << all_target << " [Project]\n"; + std::set<std::string> predefinedTargets; + predefinedTargets.insert(this->GetInstallTargetName()); + predefinedTargets.insert(this->GetAllTargetName()); + predefinedTargets.insert(std::string(CHECK_BUILD_SYSTEM_TARGET)); + // All known targets for (cmGeneratorTarget const* target : this->ProjectTargets) { if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY || @@ -320,8 +334,13 @@ void cmGlobalGhsMultiGenerator::WriteSubProjects(std::ostream& fout, target->GetName() != this->GetInstallTargetName())) { continue; } - fout << "CMakeFiles/" << target->GetName() + ".tgt" + FILE_EXTENSION - << " [Project]\n"; + /* Check if the current target is a predefined CMake target */ + bool predefinedTarget = + predefinedTargets.find(target->GetName()) != predefinedTargets.end(); + if ((filterPredefined && predefinedTarget) || + (!filterPredefined && !predefinedTarget)) { + fout << target->GetName() + ".tgt" + FILE_EXTENSION << " [Project]\n"; + } } } @@ -329,36 +348,22 @@ void cmGlobalGhsMultiGenerator::WriteProjectLine( std::ostream& fout, cmGeneratorTarget const* target, std::string& rootBinaryDir) { - cmValue projName = target->GetProperty("GENERATOR_FILE_NAME"); + cmValue projFile = target->GetProperty("GENERATOR_FILE_NAME"); cmValue projType = target->GetProperty("GENERATOR_FILE_NAME_EXT"); - if (projName && projType) { - cmLocalGenerator* lg = target->GetLocalGenerator(); - std::string dir = lg->GetCurrentBinaryDirectory(); - dir = cmSystemTools::ForceToRelativePath(rootBinaryDir, dir); - if (dir == ".") { - dir.clear(); - } else { - if (dir.back() != '/') { - dir += "/"; - } - } + /* If either value is not valid then this particular target is an + * unsupported target type and should be skipped. + */ + if (projFile && projType) { + std::string path = cmSystemTools::RelativePath(rootBinaryDir, projFile); - std::string projFile = dir + *projName + FILE_EXTENSION; - fout << projFile; + fout << path; fout << ' ' << *projType << '\n'; - } else { - /* Should never happen */ - std::string message = - "The project file for target [" + target->GetName() + "] is missing.\n"; - cmSystemTools::Error(message); - fout << "{comment} " << target->GetName() << " [missing project file]\n"; } } void cmGlobalGhsMultiGenerator::WriteTargets(cmLocalGenerator* root) { - std::string rootBinaryDir = - cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeFiles"); + std::string rootBinaryDir = root->GetCurrentBinaryDirectory(); // All known targets for (cmGeneratorTarget const* target : this->ProjectTargets) { @@ -391,62 +396,6 @@ void cmGlobalGhsMultiGenerator::WriteTargets(cmLocalGenerator* root) } } -void cmGlobalGhsMultiGenerator::WriteAllTarget( - cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators, - std::string& all_target) -{ - this->ProjectTargets.clear(); - - // create target build file - all_target = root->GetProjectName() + "." + this->GetAllTargetName() + - ".tgt" + FILE_EXTENSION; - std::string fname = - root->GetCurrentBinaryDirectory() + "/CMakeFiles/" + all_target; - cmGeneratedFileStream fbld(fname); - fbld.SetCopyIfDifferent(true); - this->WriteFileHeader(fbld); - GhsMultiGpj::WriteGpjTag(GhsMultiGpj::PROJECT, fbld); - - // Collect all targets under this root generator and the transitive - // closure of their dependencies. - TargetDependSet projectTargets; - TargetDependSet originalTargets; - this->GetTargetSets(projectTargets, originalTargets, root, generators); - OrderedTargetDependSet sortedProjectTargets(projectTargets, ""); - std::vector<cmGeneratorTarget const*> defaultTargets; - for (cmGeneratorTarget const* t : sortedProjectTargets) { - /* save list of all targets in sorted order */ - this->ProjectTargets.push_back(t); - } - for (cmGeneratorTarget const* t : sortedProjectTargets) { - if (!t->IsInBuildSystem()) { - continue; - } - if (!this->IsExcluded(t->GetLocalGenerator(), t)) { - defaultTargets.push_back(t); - } - } - std::vector<cmGeneratorTarget const*> build; - if (this->ComputeTargetBuildOrder(defaultTargets, build)) { - std::string message = "The inter-target dependency graph for project [" + - root->GetProjectName() + "] had a cycle.\n"; - cmSystemTools::Error(message); - } else { - // determine the targets for ALL target - std::string rootBinaryDir = - cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeFiles"); - for (cmGeneratorTarget const* target : build) { - if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY || - target->GetType() == cmStateEnums::MODULE_LIBRARY || - target->GetType() == cmStateEnums::SHARED_LIBRARY) { - continue; - } - this->WriteProjectLine(fbld, target, rootBinaryDir); - } - } - fbld.Close(); -} - void cmGlobalGhsMultiGenerator::Generate() { std::string fname; @@ -476,18 +425,36 @@ void cmGlobalGhsMultiGenerator::Generate() this->WriteFileHeader(ftarget); this->WriteCustomTargetBOD(ftarget); ftarget.Close(); + + // create the stamp file when running CMake + if (!this->StampFile.empty()) { + cmGeneratedFileStream fstamp(this->StampFile); + fstamp.SetCopyIfDifferent(false); + fstamp.Close(); + } } void cmGlobalGhsMultiGenerator::OutputTopLevelProject( cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators) { std::string fname; - std::string all_target; if (generators.empty()) { return; } + // Collect all targets under this root generator and the transitive + // closure of their dependencies. + TargetDependSet projectTargets; + TargetDependSet originalTargets; + this->GetTargetSets(projectTargets, originalTargets, root, generators); + OrderedTargetDependSet sortedProjectTargets(projectTargets, ""); + this->ProjectTargets.clear(); + for (cmGeneratorTarget const* t : sortedProjectTargets) { + /* save list of all targets in sorted order */ + this->ProjectTargets.push_back(t); + } + /* Name top-level projects as filename.top.gpj to avoid name clashes * with target projects. This avoid the issue where the project has * the same name as the executable target. @@ -498,11 +465,9 @@ void cmGlobalGhsMultiGenerator::OutputTopLevelProject( cmGeneratedFileStream top(fname); top.SetCopyIfDifferent(true); this->WriteTopLevelProject(top, root); - - this->WriteAllTarget(root, generators, all_target); this->WriteTargets(root); - - this->WriteSubProjects(top, all_target); + this->WriteSubProjects(top, true); + this->WriteSubProjects(top, false); top.Close(); } @@ -510,59 +475,62 @@ std::vector<cmGlobalGenerator::GeneratedMakeCommand> cmGlobalGhsMultiGenerator::GenerateBuildCommand( const std::string& makeProgram, const std::string& projectName, const std::string& projectDir, std::vector<std::string> const& targetNames, - const std::string& /*config*/, int jobs, bool /*verbose*/, + const std::string& /*config*/, int jobs, bool verbose, const cmBuildOptions& /*buildOptions*/, std::vector<std::string> const& makeOptions) { - GeneratedMakeCommand makeCommand = {}; - std::string gbuild; - if (cmValue gbuildCached = - this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM")) { - gbuild = *gbuildCached; - } - makeCommand.Add(this->SelectMakeProgram(makeProgram, gbuild)); + GeneratedMakeCommand makeCommand; + + makeCommand.Add(this->SelectMakeProgram(makeProgram)); if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) { - makeCommand.Add("-parallel"); - if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) { - makeCommand.Add(std::to_string(jobs)); + if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) { + makeCommand.Add("-parallel"); + } else { + makeCommand.Add(std::string("-parallel=") + std::to_string(jobs)); } } - makeCommand.Add(makeOptions.begin(), makeOptions.end()); - - /* determine which top-project file to use */ + /* determine the top-project file in the project directory */ std::string proj = projectName + ".top" + FILE_EXTENSION; std::vector<std::string> files; cmSystemTools::Glob(projectDir, ".*\\.top\\.gpj", files); if (!files.empty()) { - /* if multiple top-projects are found in build directory - * then prefer projectName top-project. - */ - if (!cm::contains(files, proj)) { - proj = files.at(0); - } + /* use the real top-level project in the directory */ + proj = files.at(0); } - makeCommand.Add("-top", proj); + + /* determine targets to build */ + bool build_all = false; if (!targetNames.empty()) { - if (cm::contains(targetNames, "clean")) { - makeCommand.Add("-clean"); - } else { - for (const auto& tname : targetNames) { - if (!tname.empty()) { + for (const auto& tname : targetNames) { + if (!tname.empty()) { + if (tname == "clean") { + makeCommand.Add("-clean"); + } else { makeCommand.Add(tname + ".tgt.gpj"); } + } else { + build_all = true; } } } else { + build_all = true; + } + + if (build_all) { /* transform name to default build */; - std::string all = proj; - all.replace(all.end() - 7, all.end(), - std::string(this->GetAllTargetName()) + ".tgt.gpj"); + std::string all = std::string(this->GetAllTargetName()) + ".tgt.gpj"; makeCommand.Add(all); } - return { makeCommand }; + + if (verbose) { + makeCommand.Add("-commands"); + } + makeCommand.Add(makeOptions.begin(), makeOptions.end()); + + return { std::move(makeCommand) }; } void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout, @@ -579,7 +547,7 @@ void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout, } void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives( - cmLocalGenerator* root, std::ostream& fout) + std::ostream& fout, cmLocalGenerator* root) { /* put primary target and customization files into project file */ cmValue const tgt = root->GetMakefile()->GetDefinition("GHS_PRIMARY_TARGET"); @@ -681,3 +649,147 @@ bool cmGlobalGhsMultiGenerator::VisitTarget( /* already complete */ return false; } + +bool cmGlobalGhsMultiGenerator::AddCheckTarget() +{ + // Skip the target if no regeneration is to be done. + if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) { + return false; + } + + // Get the generators. + std::vector<std::unique_ptr<cmLocalGenerator>> const& generators = + this->LocalGenerators; + auto& lg = + cm::static_reference_cast<cmLocalGhsMultiGenerator>(generators[0]); + + // The name of the output file for the custom command. + this->StampFile = lg.GetBinaryDirectory() + std::string("/CMakeFiles/") + + CHECK_BUILD_SYSTEM_TARGET; + + // Add a custom rule to re-run CMake if any input files changed. + { + // Collect the input files used to generate all targets in this + // project. + std::vector<std::string> listFiles; + for (const auto& gen : generators) { + cm::append(listFiles, gen->GetMakefile()->GetListFiles()); + } + + // Add the cache file. + listFiles.push_back(cmStrCat( + this->GetCMakeInstance()->GetHomeOutputDirectory(), "/CMakeCache.txt")); + + // Print not implemented warning. + if (this->GetCMakeInstance()->DoWriteGlobVerifyTarget()) { + std::ostringstream msg; + msg << "Any pre-check scripts, such as those generated for file(GLOB " + "CONFIGURE_DEPENDS), will not be run by gbuild."; + this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING, + msg.str()); + } + + // Sort the list of input files and remove duplicates. + std::sort(listFiles.begin(), listFiles.end(), std::less<std::string>()); + auto newEnd = std::unique(listFiles.begin(), listFiles.end()); + listFiles.erase(newEnd, listFiles.end()); + + // Create a rule to re-run CMake and create output file. + std::string argS = cmStrCat("-S", lg.GetSourceDirectory()); + std::string argB = cmStrCat("-B", lg.GetBinaryDirectory()); + cmCustomCommandLines commandLines = cmMakeSingleCommandLine( + { cmSystemTools::GetCMakeCommand(), argS, argB }); + + /* Create the target(Exclude from ALL_BUILD). + * + * The build tool, currently, does not support rereading the project files + * if they get updated. So do not run this target as part of ALL_BUILD. + */ + auto cc = cm::make_unique<cmCustomCommand>(); + cmTarget* tgt = + lg.AddUtilityCommand(CHECK_BUILD_SYSTEM_TARGET, true, std::move(cc)); + auto ptr = cm::make_unique<cmGeneratorTarget>(tgt, &lg); + auto* gt = ptr.get(); + lg.AddGeneratorTarget(std::move(ptr)); + + // Add the rule. + cc = cm::make_unique<cmCustomCommand>(); + cc->SetOutputs(this->StampFile); + cc->SetDepends(listFiles); + cc->SetCommandLines(commandLines); + cc->SetComment("Checking Build System"); + cc->SetCMP0116Status(cmPolicies::NEW); + cc->SetEscapeOldStyle(false); + cc->SetStdPipesUTF8(true); + + if (cmSourceFile* file = + lg.AddCustomCommandToOutput(std::move(cc), true)) { + gt->AddSource(file->ResolveFullPath()); + } else { + cmSystemTools::Error("Error adding rule for " + this->StampFile); + } + // Organize in the "predefined targets" folder: + if (this->UseFolderProperty()) { + tgt->SetProperty("FOLDER", this->GetPredefinedTargetsFolder()); + } + } + + return true; +} + +void cmGlobalGhsMultiGenerator::AddAllTarget() +{ + // Add a special target that depends on ALL projects for easy build + // of one configuration only. + for (auto const& it : this->ProjectMap) { + std::vector<cmLocalGenerator*> const& gen = it.second; + // add the ALL_BUILD to the first local generator of each project + if (!gen.empty()) { + // Use no actual command lines so that the target itself is not + // considered always out of date. + auto cc = cm::make_unique<cmCustomCommand>(); + cc->SetCMP0116Status(cmPolicies::NEW); + cc->SetEscapeOldStyle(false); + cc->SetComment("Build all projects"); + cmTarget* allBuild = gen[0]->AddUtilityCommand(this->GetAllTargetName(), + true, std::move(cc)); + + gen[0]->AddGeneratorTarget( + cm::make_unique<cmGeneratorTarget>(allBuild, gen[0])); + + // Organize in the "predefined targets" folder: + if (this->UseFolderProperty()) { + allBuild->SetProperty("FOLDER", this->GetPredefinedTargetsFolder()); + } + + // Now make all targets depend on the ALL_BUILD target + for (cmLocalGenerator const* i : gen) { + for (const auto& tgt : i->GetGeneratorTargets()) { + // Skip global or imported targets + if (tgt->GetType() == cmStateEnums::GLOBAL_TARGET || + tgt->IsImported()) { + continue; + } + // Skip Exclude From All Targets + if (!this->IsExcluded(gen[0], tgt.get())) { + allBuild->AddUtility(tgt->GetName(), false); + } + } + } + } + } +} + +void cmGlobalGhsMultiGenerator::AddExtraIDETargets() +{ + // Add a special target that depends on ALL projects. + this->AddAllTarget(); + + /* Add Custom Target to check if CMake needs to be rerun. + * + * The build tool, currently, does not support rereading the project files + * if they get updated. So do not make the other targets dependent on this + * check. + */ + this->AddCheckTarget(); +} diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index 26ea3c7..aa68d3b 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -81,8 +81,6 @@ public: // Write the common disclaimer text at the top of each build file. void WriteFileHeader(std::ostream& fout); - const char* GetInstallTargetName() const override { return "install"; } - protected: void Generate() override; std::vector<GeneratedMakeCommand> GenerateBuildCommand( @@ -92,6 +90,7 @@ protected: const cmBuildOptions& buildOptions = cmBuildOptions(), std::vector<std::string> const& makeOptions = std::vector<std::string>()) override; + void AddExtraIDETargets() override; private: void GetToolset(cmMakefile* mf, std::string& tsd, const std::string& ts); @@ -101,20 +100,21 @@ private: std::vector<cmLocalGenerator*>& generators); void WriteTopLevelProject(std::ostream& fout, cmLocalGenerator* root); void WriteMacros(std::ostream& fout, cmLocalGenerator* root); - void WriteHighLevelDirectives(cmLocalGenerator* root, std::ostream& fout); - void WriteSubProjects(std::ostream& fout, std::string& all_target); + void WriteHighLevelDirectives(std::ostream& fout, cmLocalGenerator* root); + void WriteSubProjects(std::ostream& fout, bool filterPredefined); void WriteTargets(cmLocalGenerator* root); void WriteProjectLine(std::ostream& fout, cmGeneratorTarget const* target, std::string& rootBinaryDir); void WriteCustomRuleBOD(std::ostream& fout); void WriteCustomTargetBOD(std::ostream& fout); - void WriteAllTarget(cmLocalGenerator* root, - std::vector<cmLocalGenerator*>& generators, - std::string& all_target); + bool AddCheckTarget(); + void AddAllTarget(); + std::string StampFile; static std::string TrimQuotes(std::string str); static const char* DEFAULT_BUILD_PROGRAM; + static const char* CHECK_BUILD_SYSTEM_TARGET; bool ComputeTargetBuildOrder(cmGeneratorTarget const* tgt, std::vector<cmGeneratorTarget const*>& build); diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 9ac42a6..e39cdaf 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -2319,7 +2319,7 @@ if(BUILD_TESTING) endmacro() macro(add_test_GhsMulti_rename_install test_name) add_test_GhsMulti( ${test_name} GhsMultiRenameInstall ${test_name} - "-DCMAKE_INSTALL_PREFIX=. -DRUN_TEST=${test_name}" ${CMAKE_CMAKE_COMMAND} --build . --target install) + "-DCMAKE_INSTALL_PREFIX=. -DRUN_TEST=${test_name}" ${CMAKE_CMAKE_COMMAND} --build . --target INSTALL) endmacro() #unset ghs config variables unset(ghs_config_name) diff --git a/Tests/GhsMulti/GhsMultiCompilerOptions/CMakeLists.txt b/Tests/GhsMulti/GhsMultiCompilerOptions/CMakeLists.txt index 4a3f5c2..9250709 100644 --- a/Tests/GhsMulti/GhsMultiCompilerOptions/CMakeLists.txt +++ b/Tests/GhsMulti/GhsMultiCompilerOptions/CMakeLists.txt @@ -27,8 +27,7 @@ try_compile(RESULT message("Output from build:\n${OUTPUT}") if (RUN_TEST STREQUAL "RELEASE_FLAGS") find_file (fileName test_none.gpj - ${CMAKE_CURRENT_BINARY_DIR}/build - ${CMAKE_CURRENT_BINARY_DIR}/build/test_none + ${CMAKE_CURRENT_BINARY_DIR}/build/test_none.dir ) message("Parsing project file: ${fileName}") file(STRINGS ${fileName} fileText) @@ -40,8 +39,7 @@ if (RUN_TEST STREQUAL "RELEASE_FLAGS") else() unset(fileName CACHE) find_file (fileName K1.gpj - ${CMAKE_CURRENT_BINARY_DIR}/build - ${CMAKE_CURRENT_BINARY_DIR}/build/K1 + ${CMAKE_CURRENT_BINARY_DIR}/build/K1.dir ) message("Parsing project file: ${fileName}") file(STRINGS ${fileName} fileText) @@ -53,8 +51,7 @@ else() unset(fileName CACHE) find_file (fileName K2.gpj - ${CMAKE_CURRENT_BINARY_DIR}/build - ${CMAKE_CURRENT_BINARY_DIR}/build/K2 + ${CMAKE_CURRENT_BINARY_DIR}/build/K2.dir ) message("Parsing project file: ${fileName}") file(STRINGS ${fileName} fileText) @@ -66,8 +63,7 @@ else() unset(fileName CACHE) find_file (fileName K3.gpj - ${CMAKE_CURRENT_BINARY_DIR}/build - ${CMAKE_CURRENT_BINARY_DIR}/build/K3 + ${CMAKE_CURRENT_BINARY_DIR}/build/K3.dir ) message("Parsing project file: ${fileName}") file(STRINGS ${fileName} fileText) @@ -79,8 +75,7 @@ else() unset(fileName CACHE) find_file (fileName K4.gpj - ${CMAKE_CURRENT_BINARY_DIR}/build - ${CMAKE_CURRENT_BINARY_DIR}/build/K4 + ${CMAKE_CURRENT_BINARY_DIR}/build/K4.dir ) message("Parsing project file: ${fileName}") file(STRINGS ${fileName} fileText) diff --git a/Tests/GhsMulti/GhsMultiExclude/CMakeLists.txt b/Tests/GhsMulti/GhsMultiExclude/CMakeLists.txt index 0448cf2..575bf50 100644 --- a/Tests/GhsMulti/GhsMultiExclude/CMakeLists.txt +++ b/Tests/GhsMulti/GhsMultiExclude/CMakeLists.txt @@ -14,4 +14,6 @@ set_target_properties( lib1 PROPERTIES EXCLUDE_FROM_ALL yes ) add_library(lib2 EXCLUDE_FROM_ALL lib1.c) +add_library(lib3 lib1.c) + add_executable(exe1 exe1.c) diff --git a/Tests/GhsMulti/GhsMultiExclude/verify.cmake b/Tests/GhsMulti/GhsMultiExclude/verify.cmake index 0467b5a..99cef63 100644 --- a/Tests/GhsMulti/GhsMultiExclude/verify.cmake +++ b/Tests/GhsMulti/GhsMultiExclude/verify.cmake @@ -1,54 +1,56 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. -#test project was generated -unset(fileName CACHE) -find_file (fileName lib1.gpj - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/lib1 - ) - -if (fileName) - message("Found target lib1: ${fileName}") -else() - message(SEND_ERROR "Could not find target lib1: ${fileName}") -endif() - -#test project was built -unset(fileName CACHE) -find_file (fileName lib1.a - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/lib1 - ) - -if (fileName) - message(SEND_ERROR "Found target lib1: ${fileName}") -else() - message("Could not find target lib1: ${fileName}") -endif() - -#test project was generated -unset(fileName CACHE) -find_file (fileName lib2.gpj - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/lib2 - ) - -if (fileName) - message("Found target lib2 ${fileName}") -else() - message(SEND_ERROR "Could not find target lib2: ${fileName}") -endif() - -#test project was built -unset(fileName CACHE) -find_file (fileName lib2.a - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/lib2 - ) - -if (fileName) - message(SEND_ERROR "Found target lib2: ${fileName}") -else() - message("Could not find target lib2: ${fileName}") -endif() +function(verify_skipped_tgt name) + unset(fileName CACHE) + find_file (fileName ${name}.tgt.gpj + ${CMAKE_CURRENT_BINARY_DIR} + ) + + if (fileName) + message("Found target ${name}: ${fileName}") + else() + message(SEND_ERROR "Could not find target ${name}: ${fileName}") + endif() + + #test project was built + unset(fileName CACHE) + find_file (fileName lib${name}.a + ${CMAKE_CURRENT_BINARY_DIR} + ) + + if (fileName) + message(SEND_ERROR "Found target ${name}: ${fileName}") + else() + message("Could not find target ${name}: ${fileName}") + endif() +endfunction() + +function(locate_tgt name) + unset(fileName CACHE) + find_file (fileName ${name}.tgt.gpj + ${CMAKE_CURRENT_BINARY_DIR} + ) + + if (fileName) + message("Found target ${name}: ${fileName}") + else() + message(SEND_ERROR "Could not find target ${name}: ${fileName}") + endif() + + #test project was built + unset(fileName CACHE) + find_file (fileName lib${name}.a + ${CMAKE_CURRENT_BINARY_DIR} + ) + + if (fileName) + message( "Found target ${name}: ${fileName}") + else() + message(SEND_ERROR "Could not find target ${name}: ${fileName}") + endif() +endfunction() + +verify_skipped_tgt(lib1) +verify_skipped_tgt(lib2) +locate_tgt(lib3) diff --git a/Tests/GhsMulti/GhsMultiLinkTest/CMakeLists.txt b/Tests/GhsMulti/GhsMultiLinkTest/CMakeLists.txt index da80b51..2d21bfb 100644 --- a/Tests/GhsMulti/GhsMultiLinkTest/CMakeLists.txt +++ b/Tests/GhsMulti/GhsMultiLinkTest/CMakeLists.txt @@ -38,8 +38,7 @@ if (RUN_TEST STREQUAL "NO_FLAGS") else() unset(fileName CACHE) find_file(fileName exe1.gpj - ${CMAKE_CURRENT_BINARY_DIR}/link_build - ${CMAKE_CURRENT_BINARY_DIR}/link_build/exe1 + ${CMAKE_CURRENT_BINARY_DIR}/link_build/exe1.dir ) message("Parsing project file: ${fileName}") file(STRINGS ${fileName} fileText) @@ -54,13 +53,14 @@ else() string(FIND "${fileText}" "${opt}" opt_found) if ( opt_found EQUAL -1 ) message(SEND_ERROR "Could not find: ${opt}") + else() + message("located: ${opt}") endif() endforeach() unset(fileName CACHE) find_file (fileName lib1.gpj - ${CMAKE_CURRENT_BINARY_DIR}/link_build - ${CMAKE_CURRENT_BINARY_DIR}/link_build/lib1 + ${CMAKE_CURRENT_BINARY_DIR}/link_build/lib1.dir ) message("Parsing project file: ${fileName}") file(STRINGS ${fileName} fileText) @@ -71,13 +71,14 @@ else() string(FIND "${fileText}" "${opt}" opt_found) if (opt_found EQUAL -1) message(SEND_ERROR "Could not find: ${opt}") + else() + message("located: ${opt}") endif() endforeach() unset(fileName CACHE) find_file (fileName lib2.gpj - ${CMAKE_CURRENT_BINARY_DIR}/link_build - ${CMAKE_CURRENT_BINARY_DIR}/link_build/lib2 + ${CMAKE_CURRENT_BINARY_DIR}/link_build/lib2.dir ) message("Parsing project file: ${fileName}") file(STRINGS ${fileName} fileText) @@ -87,6 +88,8 @@ else() string(FIND "${fileText}" "${opt}" opt_found) if ( opt_found EQUAL -1 ) message(SEND_ERROR "Could not find: ${opt}") + else() + message("located: ${opt}") endif() endforeach() endif() diff --git a/Tests/GhsMulti/GhsMultiMultipleProjects/verify.cmake b/Tests/GhsMulti/GhsMultiMultipleProjects/verify.cmake index 3855215..b6af935 100644 --- a/Tests/GhsMulti/GhsMultiMultipleProjects/verify.cmake +++ b/Tests/GhsMulti/GhsMultiMultipleProjects/verify.cmake @@ -1,58 +1,38 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. -#test project was generated -unset(fileName CACHE) -find_file(fileName lib3.gpj - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/lib3 - ${CMAKE_CURRENT_BINARY_DIR}/examples - ) - -if (fileName) - message("Found target lib3: ${fileName}") -else() - message(SEND_ERROR "Could not find target lib3: ${fileName}") -endif() - -#test project was generated -unset(fileName CACHE) -find_file (fileName exe3.gpj - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/exe3 - ${CMAKE_CURRENT_BINARY_DIR}/examples - ) - -if (fileName) - message("Found target exe3: ${fileName}") -else() - message(SEND_ERROR "Could not find target exe3: ${fileName}") -endif() - -#test project was not built -unset(fileName CACHE) -find_file (fileName lib3.a - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/lib3 - ${CMAKE_CURRENT_BINARY_DIR}/examples - ) - -if (fileName) - message(SEND_ERROR "Found target lib3: ${fileName}") -else() - message("Could not find target lib3: ${fileName}") -endif() - -unset(fileName CACHE) -find_file (fileName NAMES exe3.as exe3 - HINTS - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/exe3 - ${CMAKE_CURRENT_BINARY_DIR}/examples - ) - -if (fileName) - message(SEND_ERROR "Found target exe3: ${fileName}") -else() - message("Could not find target exe3: ${fileName}") -endif() +function(verify_project_top name) + unset(fileName CACHE) + find_file (fileName ${name}.top.gpj + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/sub + ${CMAKE_CURRENT_BINARY_DIR}/examples + ) + + if (fileName) + message("Found target ${name}: ${fileName}") + else() + message(SEND_ERROR "Could not find project ${name}: ${fileName}") + endif() +endfunction() + +function(verify_exe_built name) + unset(fileName CACHE) + find_file (fileName ${name} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/sub + ) + + if (fileName) + message("Found target ${name}: ${fileName}") + else() + message(SEND_ERROR "Could not find project ${name}: ${fileName}") + endif() +endfunction() + +#test project top files were generated +verify_project_top(test) +verify_project_top(test2) +verify_project_top(test3) +verify_exe_built(exe1) +verify_exe_built(exe2) diff --git a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/RunCMakeTest.cmake b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/RunCMakeTest.cmake index 349310f..021de41 100644 --- a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/RunCMakeTest.cmake +++ b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/RunCMakeTest.cmake @@ -67,8 +67,8 @@ if ((RunCMake_GENERATOR MATCHES "Makefiles|Ninja|Xcode" if(CMAKE_C_COMPILER_ID STREQUAL "AppleClang" OR (CMAKE_C_COMPILER_ID STREQUAL "MSVC" AND MSVC_VERSION GREATER "1900") OR (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_SYSTEM_NAME STREQUAL "Linux")) - run_cmake(whole_archive) - run_cmake_target(whole_archive link-exe main) + run_cmake(load_archive) + run_cmake_target(load_archive link-exe main) endif() if(CMAKE_C_COMPILER_ID STREQUAL "AppleClang") run_cmake(weak_library) @@ -110,3 +110,13 @@ endif() if (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND CMAKE_C_COMPILER_VERSION GREATER_EQUAL "12") run_cmake_target(apple_library needed_library main-needed_library) endif() + +# WHOLE_ARCHIVE feature +if ((CMAKE_SYSTEM_NAME STREQUAL "Windows" AND + ((DEFINED MSVC_VERSION AND MSVC_VERSION GREATER "1900") OR (CMAKE_C_COMPILER_ID MATCHES "GNU|Clang" AND NOT CMAKE_C_SIMULATE_ID STREQUAL "MSVC"))) + OR (CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND + (NOT CMAKE_C_COMPILER_ID STREQUAL "SunPro" OR CMAKE_C_COMPILER_VERSION GREATER "5.9")) + OR CMAKE_SYSTEM_NAME MATCHES "Darwin|iOS|tvOS|watchOS|Linux|BSD|MSYS|CYGWIN") + run_cmake(feature-WHOLE_ARCHIVE) + run_cmake_target(feature-WHOLE_ARCHIVE link-exe main) +endif() diff --git a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/feature-WHOLE_ARCHIVE.cmake b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/feature-WHOLE_ARCHIVE.cmake new file mode 100644 index 0000000..e525325 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/feature-WHOLE_ARCHIVE.cmake @@ -0,0 +1,11 @@ + +enable_language(C) + +add_library(base STATIC base.c unref.c) +target_compile_definitions(base PUBLIC STATIC_BASE) + +add_library(lib SHARED lib.c) +target_link_libraries(lib PRIVATE "$<LINK_LIBRARY:WHOLE_ARCHIVE,base>") + +add_executable(main main.c) +target_link_libraries(main PRIVATE lib) diff --git a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/load_archive.cmake b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/load_archive.cmake new file mode 100644 index 0000000..a0bbb43 --- /dev/null +++ b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/load_archive.cmake @@ -0,0 +1,34 @@ + +enable_language(C) + +set(CMAKE_C_LINK_LIBRARY_USING_load_archive_SUPPORTED TRUE) +if(CMAKE_C_COMPILER_ID STREQUAL "AppleClang") + set(CMAKE_C_LINK_LIBRARY_USING_load_archive "-force_load <LIB_ITEM>") +elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_SYSTEM_NAME STREQUAL "Linux") + execute_process(COMMAND "${CMAKE_LINKER}" --help + OUTPUT_VARIABLE linker_help + ERROR_VARIABLE linker_help) + if(linker_help MATCHES "--push-state" AND linker_help MATCHES "--pop-state") + set(CMAKE_C_LINK_LIBRARY_USING_load_archive "LINKER:--push-state,--whole-archive" + "<LINK_ITEM>" + "LINKER:--pop-state") + else() + set(CMAKE_C_LINK_LIBRARY_USING_load_archive "LINKER:--whole-archive" + "<LINK_ITEM>" + "LINKER:--no-whole-archive") + endif() +elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC") + set(CMAKE_C_LINK_LIBRARY_USING_load_archive "/WHOLEARCHIVE:<LIBRARY>") +else() + # feature not yet supported for the other environments + set(CMAKE_C_LINK_LIBRARY_USING_load_archive_SUPPORTED FALSE) +endif() + +add_library(base STATIC base.c unref.c) +target_compile_definitions(base PUBLIC STATIC_BASE) + +add_library(lib SHARED lib.c) +target_link_libraries(lib PRIVATE "$<LINK_LIBRARY:load_archive,base>") + +add_executable(main main.c) +target_link_libraries(main PRIVATE lib) diff --git a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/whole_archive.cmake b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/whole_archive.cmake deleted file mode 100644 index 93082a4..0000000 --- a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/whole_archive.cmake +++ /dev/null @@ -1,34 +0,0 @@ - -enable_language(C) - -set(CMAKE_C_LINK_LIBRARY_USING_whole_archive_SUPPORTED TRUE) -if(CMAKE_C_COMPILER_ID STREQUAL "AppleClang") - set(CMAKE_C_LINK_LIBRARY_USING_whole_archive "-force_load <LIB_ITEM>") -elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_SYSTEM_NAME STREQUAL "Linux") - execute_process(COMMAND "${CMAKE_LINKER}" --help - OUTPUT_VARIABLE linker_help - ERROR_VARIABLE linker_help) - if(linker_help MATCHES "--push-state" AND linker_help MATCHES "--pop-state") - set(CMAKE_C_LINK_LIBRARY_USING_whole_archive "LINKER:--push-state,--whole-archive" - "<LINK_ITEM>" - "LINKER:--pop-state") - else() - set(CMAKE_C_LINK_LIBRARY_USING_whole_archive "LINKER:--whole-archive" - "<LINK_ITEM>" - "LINKER:--no-whole-archive") - endif() -elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC") - set(CMAKE_C_LINK_LIBRARY_USING_whole_archive "/WHOLEARCHIVE:<LIBRARY>") -else() - # feature not yet supported for the other environments - set(CMAKE_C_LINK_LIBRARY_USING_whole_archive_SUPPORTED FALSE) -endif() - -add_library(base STATIC base.c unref.c) -target_compile_definitions(base PUBLIC STATIC_BASE) - -add_library(lib SHARED lib.c) -target_link_libraries(lib PRIVATE "$<LINK_LIBRARY:whole_archive,base>") - -add_executable(main main.c) -target_link_libraries(main PRIVATE lib) diff --git a/Utilities/Release/win/x86/Dockerfile b/Utilities/Release/win/x86/Dockerfile index a4f7445..d5a036a 100644 --- a/Utilities/Release/win/x86/Dockerfile +++ b/Utilities/Release/win/x86/Dockerfile @@ -11,8 +11,10 @@ ARG FROM_IMAGE_NAME=kitware/cmake:build-win-x86-deps-2020-04-27 ARG FROM_IMAGE_DIGEST=@sha256:04e229c0c0ba2247855d0e8c0fb87c1686f983adbafa4ce413e61b3905edb76b ARG FROM_IMAGE=$FROM_IMAGE_NAME$FROM_IMAGE_DIGEST -FROM $FROM_IMAGE as build +FROM $FROM_IMAGE as source COPY . C:\cmake\src\cmake + +FROM source as build ARG ARCH="x86_64" ARG TEST="true" RUN \cmake\src\cmake\Utilities\Release\win\x86\build.bat %ARCH% %TEST% |