diff options
78 files changed, 776 insertions, 558 deletions
diff --git a/Help/command/add_test.rst b/Help/command/add_test.rst index a8c257d..46b9b63 100644 --- a/Help/command/add_test.rst +++ b/Help/command/add_test.rst @@ -55,7 +55,8 @@ file produced by target ``myexe``. CMake will generate tests only if the :command:`enable_testing` command has been invoked. The :module:`CTest` module invokes the - command automatically when the ``BUILD_TESTING`` option is ``ON``. + command automatically unless the ``BUILD_TESTING`` option is turned + ``OFF``. --------------------------------------------------------------------- diff --git a/Help/command/build_command.rst b/Help/command/build_command.rst index b83edaf..6659005 100644 --- a/Help/command/build_command.rst +++ b/Help/command/build_command.rst @@ -14,7 +14,7 @@ This is mainly intended for internal use by the :module:`CTest` module. Sets the given ``<variable>`` to a command-line string of the form:: - <cmake> --build . [--config <config>] [--target <target>] [-- -i] + <cmake> --build . [--config <config>] [--target <target>...] [-- -i] where ``<cmake>`` is the location of the :manual:`cmake(1)` command-line tool, and ``<config>`` and ``<target>`` are the values provided to the diff --git a/Help/command/ctest_submit.rst b/Help/command/ctest_submit.rst index fba03fd..ac9eac1 100644 --- a/Help/command/ctest_submit.rst +++ b/Help/command/ctest_submit.rst @@ -46,7 +46,15 @@ The options are: ``HTTPHEADER <HTTP-header>`` Specify HTTP header to be included in the request to CDash during submission. - This suboption can be repeated several times. + For example, CDash can be configured to only accept submissions from + authenticated clients. In this case, you should provide a bearer token in your + header: + + .. code-block:: cmake + + ctest_submit(HTTPHEADER "Authorization: Bearer <auth-token>") + + This suboption can be repeated several times for multiple headers. ``RETRY_COUNT <count>`` Specify how many times to retry a timed-out submission. diff --git a/Help/command/enable_testing.rst b/Help/command/enable_testing.rst index e2028d2..3ac1a19 100644 --- a/Help/command/enable_testing.rst +++ b/Help/command/enable_testing.rst @@ -7,7 +7,14 @@ Enable testing for current directory and below. enable_testing() -Enables testing for this directory and below. See also the -:command:`add_test` command. Note that ctest expects to find a test file -in the build directory root. Therefore, this command should be in the -source directory root. +Enables testing for this directory and below. + +This command should be in the source directory root +because ctest expects to find a test file in the build +directory root. + +This command is automatically invoked when the :module:`CTest` +module is included, except if the ``BUILD_TESTING`` option is +turned off. + +See also the :command:`add_test` command. diff --git a/Help/command/install.rst b/Help/command/install.rst index 4cef787..a4cee71 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -9,11 +9,11 @@ Synopsis .. parsed-literal:: install(`TARGETS`_ <target>... [...]) - install({`FILES`_ | `PROGRAMS`_} <file>... [DESTINATION <dir>] [...]) - install(`DIRECTORY`_ <dir>... [DESTINATION <dir>] [...]) + install({`FILES`_ | `PROGRAMS`_} <file>... [...]) + install(`DIRECTORY`_ <dir>... [...]) install(`SCRIPT`_ <file> [...]) install(`CODE`_ <code> [...]) - install(`EXPORT`_ <export-name> DESTINATION <dir> [...]) + install(`EXPORT`_ <export-name> [...]) Introduction ^^^^^^^^^^^^ @@ -173,11 +173,20 @@ installation properties apply to all target types. If only one is given then only targets of that type will be installed (which can be used to install just a DLL or just an import library.) -For some target types, the ``DESTINATION`` argument is optional. If no -``DESTINATION`` argument is specified for these target types, the destination -will default to either the appropriate variable from :module:`GNUInstallDirs` -(if it is defined) or a built-in default (if the variable is not defined.) These -defaults are outlined below: +For regular executables, static libraries and shared libraries, the +``DESTINATION`` argument is not required. For these target types, when +``DESTINATION`` is omitted, a default destination will be taken from the +appropriate variable from :module:`GNUInstallDirs`, or set to a built-in +default value if that variable is not defined. The same is true for the +public and private headers associated with the installed targets through the +:prop_tgt:`PUBLIC_HEADER` and :prop_tgt:`PRIVATE_HEADER` target properties. +A destination must always be provided for module libraries, Apple bundles and +frameworks. A destination can be omitted for interface and object libraries, +but they are handled differently (see the discussion of this topic toward the +end of this section). + +The following table shows the target types with their associated variables and +built-in defaults that apply when no destination is given: ================== =============================== ====================== Target Type GNUInstallDirs Variable Built-In Default @@ -189,12 +198,28 @@ defaults are outlined below: ``PUBLIC_HEADER`` ``${CMAKE_INSTALL_INCLUDEDIR}`` ``include`` ================== =============================== ====================== -To make your package compliant with distribution filesystem layout policies, it -is not recommended that you specify a ``DESTINATION`` for a target unless it -must be installed in a nonstandard location. That way, package maintainers can -control the install destination by setting the appropriate cache variables. In -any case, it is recommended that you use the :module:`GNUInstallDirs` variables -in your ``DESTINATION`` arguments whenever possible. +Projects wishing to follow the common practice of installing headers into a +project-specific subdirectory will need to provide a destination rather than +rely on the above. + +To make packages compliant with distribution filesystem layout policies, if +projects must specify a ``DESTINATION``, it is recommended that they use a +path that begins with the appropriate :module:`GNUInstallDirs` variable. +This allows package maintainers to control the install destination by setting +the appropriate cache variables. The following example shows a static library +being installed to the default destination provided by +:module:`GNUInstallDirs`, but with its headers installed to a project-specific +subdirectory that follows the above recommendation: + +.. code-block:: cmake + + add_library(mylib STATIC ...) + set_target_properties(mylib PROPERTIES PUBLIC_HEADER mylib.h) + include(GNUInstallDirs) + install(TARGETS mylib + PUBLIC_HEADER + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/myproj + ) In addition to the common options listed above, each target can accept the following additional arguments: @@ -219,11 +244,9 @@ the following additional arguments: install(TARGETS mylib LIBRARY - DESTINATION lib COMPONENT Libraries NAMELINK_COMPONENT Development PUBLIC_HEADER - DESTINATION include COMPONENT Development ) @@ -321,7 +344,7 @@ targets from other directories are up-to-date. You can use to ensure that such out-of-directory targets are built before the subdirectory-specific install rules are run. -The install destination given to the target install ``DESTINATION`` may +An install destination given as a ``DESTINATION`` argument may use "generator expressions" with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual for available expressions. @@ -335,7 +358,8 @@ Installing Files .. code-block:: cmake - install(<FILES|PROGRAMS> files... [DESTINATION <dir> | TYPE <type>] + install(<FILES|PROGRAMS> files... + TYPE <type> | DESTINATION <dir> [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] @@ -359,12 +383,14 @@ The list of ``files...`` given to ``FILES`` or ``PROGRAMS`` may use However, if any item begins in a generator expression it must evaluate to a full path. -Instead of specifying ``DESTINATION``, you may specify a generic file type -via the ``TYPE`` argument as listed below. If a type is selected and no -destination is specified, the destination will default to either the -appropriate variable from :module:`GNUInstallDirs` (if it is defined) or a -built-in default (if the variable is not defined.) These defaults are outlined -below: +Either a ``TYPE`` or a ``DESTINATION`` must be provided, but not both. +A ``TYPE`` argument specifies the generic file type of the files being +installed. A destination will then be set automatically by taking the +corresponding variable from :module:`GNUInstallDirs`, or by using a +built-in default if that variable is not defined. See the table below for +the supported file types and their corresponding variables and built-in +defaults. Projects can provide a ``DESTINATION`` argument instead of a +file type if they wish to explicitly define the install destination. ======================= ================================== ========================= ``TYPE`` Argument GNUInstallDirs Variable Built-In Default @@ -384,7 +410,9 @@ below: ``DOC`` ``${CMAKE_INSTALL_DOCDIR}`` ``<DATAROOT dir>/doc`` ======================= ================================== ========================= -It is an error to use ``TYPE`` and ``DESTINATION`` arguments together. +Projects wishing to follow the common practice of installing headers into a +project-specific subdirectory will need to provide a destination rather than +rely on the above. Note that some of the types' built-in defaults use the ``DATAROOT`` directory as a prefix. The ``DATAROOT`` prefix is calculated similarly to the types, with @@ -392,15 +420,21 @@ a prefix. The ``DATAROOT`` prefix is calculated similarly to the types, with default. You cannot use ``DATAROOT`` as a ``TYPE`` parameter; please use ``DATA`` instead. -To make your package compliant with distribution filesystem layout policies, it -is recommended that you specify one of the above generic file types, rather than -a ``DESTINATION`` argument, unless the files must be installed in a nonstandard -location. That way, package maintainers can control the install destination by -setting the appropriate cache variables. In any case, it is recommended that you -use the :module:`GNUInstallDirs` variables in your ``DESTINATION`` arguments -whenever possible. +To make packages compliant with distribution filesystem layout policies, if +projects must specify a ``DESTINATION``, it is recommended that they use a +path that begins with the appropriate :module:`GNUInstallDirs` variable. +This allows package maintainers to control the install destination by setting +the appropriate cache variables. The following example shows how to follow +this advice while installing headers to a project-specific subdirectory: -The install destination given to the files install ``DESTINATION`` may +.. code-block:: cmake + + include(GNUInstallDirs) + install(FILES mylib.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/myproj + ) + +An install destination given as a ``DESTINATION`` argument may use "generator expressions" with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual for available expressions. @@ -412,7 +446,8 @@ Installing Directories .. code-block:: cmake - install(DIRECTORY dirs... [DESTINATION <dir> | TYPE <type>] + install(DIRECTORY dirs... + TYPE <type> | DESTINATION <dir> [FILE_PERMISSIONS permissions...] [DIRECTORY_PERMISSIONS permissions...] [USE_SOURCE_PERMISSIONS] [OPTIONAL] [MESSAGE_NEVER] @@ -483,12 +518,15 @@ will install the ``icons`` directory to ``share/myproj/icons`` and the file permissions, the scripts will be given specific permissions, and any ``CVS`` directories will be excluded. -Instead of specifying ``DESTINATION``, you may specify a generic file type -via the ``TYPE`` argument as listed below. If a type is selected and no -destination is specified, the destination will default to either the -appropriate variable from :module:`GNUInstallDirs` (if it is defined) or a -built-in default (if the variable is not defined.) These defaults are outlined -below: +Either a ``TYPE`` or a ``DESTINATION`` must be provided, but not both. +A ``TYPE`` argument specifies the generic file type of the files within the +listed directories being installed. A destination will then be set +automatically by taking the corresponding variable from +:module:`GNUInstallDirs`, or by using a built-in default if that variable +is not defined. See the table below for the supported file types and their +corresponding variables and built-in defaults. Projects can provide a +``DESTINATION`` argument instead of a file type if they wish to explicitly +define the install destination. ======================= ================================== ========================= ``TYPE`` Argument GNUInstallDirs Variable Built-In Default @@ -508,24 +546,20 @@ below: ``DOC`` ``${CMAKE_INSTALL_DOCDIR}`` ``<DATAROOT dir>/doc`` ======================= ================================== ========================= -It is an error to use ``TYPE`` and ``DESTINATION`` arguments together. - Note that some of the types' built-in defaults use the ``DATAROOT`` directory as a prefix. The ``DATAROOT`` prefix is calculated similarly to the types, with ``CMAKE_INSTALL_DATAROOTDIR`` as the variable and ``share`` as the built-in default. You cannot use ``DATAROOT`` as a ``TYPE`` parameter; please use ``DATA`` instead. -To make your package compliant with distribution filesystem layout policies, it -is recommended that you specify one of the above generic file types, rather than -a ``DESTINATION`` argument, unless the files must be installed in a nonstandard -location. That way, package maintainers can control the install destination by -setting the appropriate cache variables. In any case, it is recommended that you -use the :module:`GNUInstallDirs` variables in your ``DESTINATION`` arguments -whenever possible. +To make packages compliant with distribution filesystem layout policies, if +projects must specify a ``DESTINATION``, it is recommended that they use a +path that begins with the appropriate :module:`GNUInstallDirs` variable. +This allows package maintainers to control the install destination by setting +the appropriate cache variables. -The list of ``dirs...`` given to ``DIRECTORY`` and the install destination -given to the directory install ``DESTINATION`` may use "generator expressions" +The list of ``dirs...`` given to ``DIRECTORY`` and an install destination +given as a ``DESTINATION`` argument may use "generator expressions" with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual for available expressions. diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 3d4536b..16c3460 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -352,22 +352,22 @@ Properties on Targets /prop_tgt/XCODE_PRODUCT_TYPE /prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER /prop_tgt/XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN + /prop_tgt/XCODE_SCHEME_ARGUMENTS + /prop_tgt/XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER + /prop_tgt/XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS + /prop_tgt/XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE + /prop_tgt/XCODE_SCHEME_ENVIRONMENT + /prop_tgt/XCODE_SCHEME_EXECUTABLE + /prop_tgt/XCODE_SCHEME_GUARD_MALLOC + /prop_tgt/XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP + /prop_tgt/XCODE_SCHEME_MALLOC_GUARD_EDGES + /prop_tgt/XCODE_SCHEME_MALLOC_SCRIBBLE + /prop_tgt/XCODE_SCHEME_MALLOC_STACK /prop_tgt/XCODE_SCHEME_THREAD_SANITIZER /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_DISABLE_MAIN_THREAD_CHECKER - /prop_tgt/XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP - /prop_tgt/XCODE_SCHEME_MALLOC_SCRIBBLE - /prop_tgt/XCODE_SCHEME_MALLOC_GUARD_EDGES - /prop_tgt/XCODE_SCHEME_GUARD_MALLOC /prop_tgt/XCODE_SCHEME_ZOMBIE_OBJECTS - /prop_tgt/XCODE_SCHEME_MALLOC_STACK - /prop_tgt/XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE - /prop_tgt/XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS - /prop_tgt/XCODE_SCHEME_EXECUTABLE - /prop_tgt/XCODE_SCHEME_ARGUMENTS - /prop_tgt/XCODE_SCHEME_ENVIRONMENT /prop_tgt/XCTEST .. _`Test Properties`: diff --git a/Help/manual/cmake-toolchains.7.rst b/Help/manual/cmake-toolchains.7.rst index d214e4a..ba44b7f 100644 --- a/Help/manual/cmake-toolchains.7.rst +++ b/Help/manual/cmake-toolchains.7.rst @@ -556,6 +556,54 @@ command is sufficient: cmake .. -GXcode -DCMAKE_SYSTEM_NAME=iOS +Variable :variable:`CMAKE_OSX_ARCHITECTURES` can be used to set architectures +for both device and simulator. Variable :variable:`CMAKE_OSX_DEPLOYMENT_TARGET` +can be used to set an iOS/tvOS/watchOS deployment target. + +Next configuration will install fat 5 architectures iOS library +and add the ``-miphoneos-version-min=9.3``/``-mios-simulator-version-min=9.3`` +flags to the compiler: + +.. code-block:: console + + $ cmake -S. -B_builds -GXcode \ + -DCMAKE_SYSTEM_NAME=iOS \ + "-DCMAKE_OSX_ARCHITECTURES=armv7;armv7s;arm64;i386;x86_64" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=9.3 \ + -DCMAKE_INSTALL_PREFIX=`pwd`/_install \ + -DCMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH=NO \ + -DCMAKE_IOS_INSTALL_COMBINED=YES + +Example: + +.. code-block:: cmake + + # CMakeLists.txt + cmake_minimum_required(VERSION 3.14) + project(foo) + add_library(foo foo.cpp) + install(TARGETS foo DESTINATION lib) + +Install: + +.. code-block:: console + + $ cmake --build _builds --config Release --target install + +Check library: + +.. code-block:: console + + $ lipo -info _install/lib/libfoo.a + Architectures in the fat file: _install/lib/libfoo.a are: i386 armv7 armv7s x86_64 arm64 + +.. code-block:: console + + $ otool -l _install/lib/libfoo.a | grep -A2 LC_VERSION_MIN_IPHONEOS + cmd LC_VERSION_MIN_IPHONEOS + cmdsize 16 + version 9.3 + Code Signing ^^^^^^^^^^^^ @@ -592,4 +640,14 @@ Please note that checks made during configuration were performed against the configure-time SDK and might not hold true for other SDKs. Commands like :command:`find_package`, :command:`find_library`, etc. store and use details only for the configured SDK/platform, so they can be problematic -if wanting to switch between device and simulator builds. +if wanting to switch between device and simulator builds. You can follow +the next rules to make device + simulator configuration work: + +- Use explicit ``-l`` linker flag, + e.g. ``target_link_libraries(foo PUBLIC "-lz")`` + +- Use explicit ``-framework`` linker flag, + e.g. ``target_link_libraries(foo PUBLIC "-framework CoreFoundation")`` + +- Use :command:`find_package` only for libraries installed with + :variable:`CMAKE_IOS_INSTALL_COMBINED` feature diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 83c88a5..6bb30cb 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -216,19 +216,19 @@ 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_DISABLE_MAIN_THREAD_CHECKER + /variable/CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS + /variable/CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE + /variable/CMAKE_XCODE_SCHEME_GUARD_MALLOC + /variable/CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP + /variable/CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES + /variable/CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE + /variable/CMAKE_XCODE_SCHEME_MALLOC_STACK /variable/CMAKE_XCODE_SCHEME_THREAD_SANITIZER /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_DISABLE_MAIN_THREAD_CHECKER - /variable/CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP - /variable/CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE - /variable/CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES - /variable/CMAKE_XCODE_SCHEME_GUARD_MALLOC /variable/CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS - /variable/CMAKE_XCODE_SCHEME_MALLOC_STACK - /variable/CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE - /variable/CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS /variable/PackageName_ROOT Variables that Describe the System @@ -259,6 +259,7 @@ Variables that Describe the System /variable/CMAKE_SYSTEM_VERSION /variable/CYGWIN /variable/GHS-MULTI + /variable/IOS /variable/MINGW /variable/MSVC /variable/MSVC10 diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index f3b81ec..e9a08b5 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -276,8 +276,8 @@ following options: The :envvar:`CMAKE_BUILD_PARALLEL_LEVEL` environment variable, if set, specifies a default parallel level when this option is not given. -``--target <tgt>`` - Build ``<tgt>`` instead of default targets. May only be specified once. +``--target <tgt>...`` + Build ``<tgt>`` instead of default targets. May be specified multiple times. ``--config <cfg>`` For multi-configuration tools, choose configuration ``<cfg>``. diff --git a/Help/release/dev/cmake-build-multiply-targets.rst b/Help/release/dev/cmake-build-multiply-targets.rst new file mode 100644 index 0000000..1275ca3 --- /dev/null +++ b/Help/release/dev/cmake-build-multiply-targets.rst @@ -0,0 +1,5 @@ +cmake-build-multiply-targets +---------------------------- + +* The :manual:`cmake(1)` ``--build`` tool ``--target`` parameter gained support for + multiple targets, e.g. ``cmake --build . --target Library1 Library2``. diff --git a/Help/variable/CMAKE_MACOSX_BUNDLE.rst b/Help/variable/CMAKE_MACOSX_BUNDLE.rst index 0badaf0..43ddff5 100644 --- a/Help/variable/CMAKE_MACOSX_BUNDLE.rst +++ b/Help/variable/CMAKE_MACOSX_BUNDLE.rst @@ -5,3 +5,6 @@ Default value for :prop_tgt:`MACOSX_BUNDLE` of targets. This variable is used to initialize the :prop_tgt:`MACOSX_BUNDLE` property on all the targets. See that target property for additional information. + +This variable is set to ``ON`` by default if :variable:`CMAKE_SYSTEM_NAME` +equals to :ref:`iOS, tvOS or watchOS <Cross Compiling for iOS, tvOS, or watchOS>`. diff --git a/Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst b/Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst index ed20bbe..7466784 100644 --- a/Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst +++ b/Help/variable/CMAKE_XCODE_GENERATE_SCHEME.rst @@ -1,15 +1,10 @@ CMAKE_XCODE_GENERATE_SCHEME --------------------------- -If enabled, the Xcode generator will generate schema files. Those are +If enabled, the Xcode generator will generate schema files. These are useful to invoke analyze, archive, build-for-testing and test actions from the command line. -.. note:: - - The Xcode Schema Generator is still experimental and subject to - change. - The following target properties overwrite the default of the corresponding settings on the "Diagnostic" tab for each schema file. Each of those is initialized by the respective ``CMAKE_`` variable @@ -17,23 +12,23 @@ at target creation time. - :prop_tgt:`XCODE_SCHEME_ADDRESS_SANITIZER` - :prop_tgt:`XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN` +- :prop_tgt:`XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER` +- :prop_tgt:`XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS` +- :prop_tgt:`XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE` +- :prop_tgt:`XCODE_SCHEME_GUARD_MALLOC` +- :prop_tgt:`XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP` +- :prop_tgt:`XCODE_SCHEME_MALLOC_GUARD_EDGES` +- :prop_tgt:`XCODE_SCHEME_MALLOC_SCRIBBLE` +- :prop_tgt:`XCODE_SCHEME_MALLOC_STACK` - :prop_tgt:`XCODE_SCHEME_THREAD_SANITIZER` - :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_DISABLE_MAIN_THREAD_CHECKER` -- :prop_tgt:`XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP` -- :prop_tgt:`XCODE_SCHEME_MALLOC_SCRIBBLE` -- :prop_tgt:`XCODE_SCHEME_MALLOC_GUARD_EDGES` -- :prop_tgt:`XCODE_SCHEME_GUARD_MALLOC` - :prop_tgt:`XCODE_SCHEME_ZOMBIE_OBJECTS` -- :prop_tgt:`XCODE_SCHEME_MALLOC_STACK` -- :prop_tgt:`XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE` -- :prop_tgt:`XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS` The following target properties will be applied on the "Info" and "Arguments" tab: -- :prop_tgt:`XCODE_SCHEME_EXECUTABLE` - :prop_tgt:`XCODE_SCHEME_ARGUMENTS` - :prop_tgt:`XCODE_SCHEME_ENVIRONMENT` +- :prop_tgt:`XCODE_SCHEME_EXECUTABLE` diff --git a/Help/variable/IOS.rst b/Help/variable/IOS.rst new file mode 100644 index 0000000..e5cc3f6 --- /dev/null +++ b/Help/variable/IOS.rst @@ -0,0 +1,4 @@ +IOS +--- + +Set to ``1`` when the target system (:variable:`CMAKE_SYSTEM_NAME`) is ``iOS``. diff --git a/Modules/CMakeRCInformation.cmake b/Modules/CMakeRCInformation.cmake index 1227fdf..7bf6567 100644 --- a/Modules/CMakeRCInformation.cmake +++ b/Modules/CMakeRCInformation.cmake @@ -32,7 +32,7 @@ set(CMAKE_INCLUDE_FLAG_RC "-I") # compile a Resource file into an object file if(NOT CMAKE_RC_COMPILE_OBJECT) set(CMAKE_RC_COMPILE_OBJECT - "<CMAKE_RC_COMPILER> <DEFINES> <INCLUDES> <FLAGS> /fo<OBJECT> <SOURCE>") + "<CMAKE_RC_COMPILER> <DEFINES> <INCLUDES> <FLAGS> /fo <OBJECT> <SOURCE>") endif() # set this variable so we can avoid loading this more than once. diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake index 0138b04..ef8272c 100644 --- a/Modules/FindPython/Support.cmake +++ b/Modules/FindPython/Support.cmake @@ -1140,9 +1140,8 @@ if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Inte OUTPUT_STRIP_TRAILING_WHITESPACE) if (NOT _${_PYTHON_PREFIX}_RESULT) find_path(${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR - NAMES arrayobject.h numpyconfig.h + NAMES "numpy/arrayobject.h" "numpy/numpyconfig.h" HINTS "${_${_PYTHON_PREFIX}_NumPy_PATH}" - PATH_SUFFIXES numpy NO_DEFAULT_PATH) endif() if(${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR) diff --git a/Modules/FindThreads.cmake b/Modules/FindThreads.cmake index 919392a..3684f01 100644 --- a/Modules/FindThreads.cmake +++ b/Modules/FindThreads.cmake @@ -38,19 +38,42 @@ This module is not needed for C++11 and later if threading is done using #]=======================================================================] include (CheckLibraryExists) -include (CheckSymbolExists) set(Threads_FOUND FALSE) set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET}) set(CMAKE_REQUIRED_QUIET ${Threads_FIND_QUIETLY}) if(CMAKE_C_COMPILER_LOADED) include (CheckIncludeFile) + include (CheckCSourceCompiles) elseif(CMAKE_CXX_COMPILER_LOADED) include (CheckIncludeFileCXX) + include (CheckCXXSourceCompiles) else() message(FATAL_ERROR "FindThreads only works if either C or CXX language is enabled") endif() +# simple pthread test code +set(PTHREAD_C_CXX_TEST_SOURCE [====[ +#include <pthread.h> + +void* test_func(void* data) +{ + return data; +} + +int main(void) +{ + pthread_t thread; + pthread_create(&thread, NULL, test_func, NULL); + pthread_detach(thread); + pthread_join(thread, NULL); + pthread_atfork(NULL, NULL, NULL); + pthread_exit(NULL); + + return 0; +} +]====]) + # Internal helper macro. # Do NOT even think about using it outside of this file! macro(_check_threads_lib LIBNAME FUNCNAME VARNAME) @@ -109,8 +132,8 @@ if(CMAKE_C_COMPILER_LOADED) else() CHECK_INCLUDE_FILE_CXX("pthread.h" CMAKE_HAVE_PTHREAD_H) endif() -if(CMAKE_HAVE_PTHREAD_H) +if(CMAKE_HAVE_PTHREAD_H) # # We have pthread.h # Let's check for the library now. @@ -118,13 +141,19 @@ if(CMAKE_HAVE_PTHREAD_H) set(CMAKE_HAVE_THREADS_LIBRARY) if(NOT THREADS_HAVE_PTHREAD_ARG) # Check if pthread functions are in normal C library. - CHECK_SYMBOL_EXISTS(pthread_create pthread.h CMAKE_HAVE_LIBC_CREATE) - if(CMAKE_HAVE_LIBC_CREATE) + # We list some pthread functions in PTHREAD_C_CXX_TEST_SOURCE test code. + # If the pthread functions already exist in C library, we could just use + # them instead of linking to the additional pthread library. + if(CMAKE_C_COMPILER_LOADED) + CHECK_C_SOURCE_COMPILES("${PTHREAD_C_CXX_TEST_SOURCE}" CMAKE_HAVE_LIBC_PTHREAD) + elseif(CMAKE_CXX_COMPILER_LOADED) + CHECK_CXX_SOURCE_COMPILES("${PTHREAD_C_CXX_TEST_SOURCE}" CMAKE_HAVE_LIBC_PTHREAD) + endif() + if(CMAKE_HAVE_LIBC_PTHREAD) set(CMAKE_THREAD_LIBS_INIT "") set(CMAKE_HAVE_THREADS_LIBRARY 1) set(Threads_FOUND TRUE) else() - # Check for -pthread first if enabled. This is the recommended # way, but not backwards compatible as one must also pass -pthread # as compiler flag then. @@ -144,7 +173,7 @@ if(CMAKE_HAVE_PTHREAD_H) _check_pthreads_flag() endif() -if(CMAKE_THREAD_LIBS_INIT OR CMAKE_HAVE_LIBC_CREATE) +if(CMAKE_THREAD_LIBS_INIT OR CMAKE_HAVE_LIBC_PTHREAD) set(CMAKE_USE_PTHREADS_INIT 1) set(Threads_FOUND TRUE) endif() diff --git a/Modules/Platform/Android.cmake b/Modules/Platform/Android.cmake index 3d69733..f08f841 100644 --- a/Modules/Platform/Android.cmake +++ b/Modules/Platform/Android.cmake @@ -2,9 +2,11 @@ include(Platform/Linux) set(ANDROID 1) -# Android has soname, but binary names must end in ".so" so we cannot append -# a version number. Also we cannot portably represent symlinks on the host. -set(CMAKE_PLATFORM_NO_VERSIONED_SONAME 1) +# Conventionally Android does not use versioned soname +# But in modern versions it is acceptable +if(NOT DEFINED CMAKE_PLATFORM_NO_VERSIONED_SONAME) + set(CMAKE_PLATFORM_NO_VERSIONED_SONAME 1) +endif() # Android reportedly ignores RPATH, and we cannot predict the install # location anyway. diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index 2daf313..0e11790 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -374,10 +374,12 @@ macro(__windows_compiler_msvc_enable_rc flags) set(CMAKE_RC_COMPILER_INIT rc) endif() if(NOT CMAKE_RC_FLAGS_INIT) - string(APPEND CMAKE_RC_FLAGS_INIT " ${flags}") + # llvm-rc fails when flags are specified with /D and no space after + string(REPLACE " /D" " -D" fixed_flags " ${flags}") + string(APPEND CMAKE_RC_FLAGS_INIT " ${fixed_flags}") endif() if(NOT CMAKE_RC_FLAGS_DEBUG_INIT) - string(APPEND CMAKE_RC_FLAGS_DEBUG_INIT " /D_DEBUG") + string(APPEND CMAKE_RC_FLAGS_DEBUG_INIT " -D_DEBUG") endif() enable_language(RC) diff --git a/Modules/Platform/iOS-Initialize.cmake b/Modules/Platform/iOS-Initialize.cmake index 41399a3..301ca4c 100644 --- a/Modules/Platform/iOS-Initialize.cmake +++ b/Modules/Platform/iOS-Initialize.cmake @@ -4,4 +4,6 @@ if(NOT _CMAKE_OSX_SYSROOT_PATH MATCHES "/iPhone(OS|Simulator)") message(FATAL_ERROR "${CMAKE_OSX_SYSROOT} is not an iOS SDK") endif() +set(IOS 1) + set(_CMAKE_FEATURE_DETECTION_TARGET_TYPE STATIC_LIBRARY) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index c59a119..0a5c247 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 14) -set(CMake_VERSION_PATCH 20190303) +set(CMake_VERSION_PATCH 20190308) #set(CMake_VERSION_RC 1) diff --git a/Source/CMakeVersion.rc.in b/Source/CMakeVersion.rc.in index 22b4a36..762d9bb 100644 --- a/Source/CMakeVersion.rc.in +++ b/Source/CMakeVersion.rc.in @@ -1,25 +1,16 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#define VER_FILEVERSION @CMake_RCVERSION@ -#define VER_FILEVERSION_STR "@CMake_RCVERSION_STR@\0" - -#define VER_PRODUCTVERSION @CMake_RCVERSION@ -#define VER_PRODUCTVERSION_STR "@CMake_RCVERSION_STR@\0" - -/* Version-information resource identifier. */ -#define VS_VERSION_INFO 1 - -VS_VERSION_INFO VERSIONINFO -FILEVERSION VER_FILEVERSION -PRODUCTVERSION VER_PRODUCTVERSION +1 VERSIONINFO +FILEVERSION @CMake_RCVERSION@ +PRODUCTVERSION @CMake_RCVERSION@ BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN - VALUE "FileVersion", VER_FILEVERSION_STR - VALUE "ProductVersion", VER_PRODUCTVERSION_STR + VALUE "FileVersion", "@CMake_RCVERSION_STR@\0" + VALUE "ProductVersion", "@CMake_RCVERSION_STR@\0" END END diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index b2c88df..a7d4455 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -256,7 +256,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) } int retVal = cm.GetGlobalGenerator()->Build( cmake::NO_BUILD_PARALLEL_LEVEL, this->SourceDir, this->BinaryDir, - this->BuildProject, tar, output, this->BuildMakeProgram, config, + this->BuildProject, { tar }, output, this->BuildMakeProgram, config, !this->BuildNoClean, false, false, remainingTime); out << output; // if the build failed then return diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 41d02c5..3bf2087 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -432,32 +432,26 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) this->ProcessOutput.clear(); + this->TestResult.Properties = this->TestProperties; + this->TestResult.ExecutionTime = cmDuration::zero(); + this->TestResult.CompressOutput = false; + this->TestResult.ReturnValue = -1; + this->TestResult.TestCount = this->TestProperties->Index; + this->TestResult.Name = this->TestProperties->Name; + this->TestResult.Path = this->TestProperties->Directory; + // Return immediately if test is disabled if (this->TestProperties->Disabled) { - this->TestResult.Properties = this->TestProperties; - this->TestResult.ExecutionTime = cmDuration::zero(); - this->TestResult.CompressOutput = false; - this->TestResult.ReturnValue = -1; this->TestResult.CompletionStatus = "Disabled"; this->TestResult.Status = cmCTestTestHandler::NOT_RUN; - this->TestResult.TestCount = this->TestProperties->Index; - this->TestResult.Name = this->TestProperties->Name; - this->TestResult.Path = this->TestProperties->Directory; this->TestProcess = cm::make_unique<cmProcess>(*this); this->TestResult.Output = "Disabled"; this->TestResult.FullCommandLine.clear(); return false; } - this->TestResult.Properties = this->TestProperties; - this->TestResult.ExecutionTime = cmDuration::zero(); - this->TestResult.CompressOutput = false; - this->TestResult.ReturnValue = -1; this->TestResult.CompletionStatus = "Failed to start"; this->TestResult.Status = cmCTestTestHandler::BAD_COMMAND; - this->TestResult.TestCount = this->TestProperties->Index; - this->TestResult.Name = this->TestProperties->Name; - this->TestResult.Path = this->TestProperties->Directory; // Check for failed fixture dependencies before we even look at the command // arguments because if we are not going to run the test, the command and @@ -635,9 +629,8 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout, { this->TestProcess = cm::make_unique<cmProcess>(*this); this->TestProcess->SetId(this->Index); - this->TestProcess->SetWorkingDirectory( - this->TestProperties->Directory.c_str()); - this->TestProcess->SetCommand(this->ActualCommand.c_str()); + this->TestProcess->SetWorkingDirectory(this->TestProperties->Directory); + this->TestProcess->SetCommand(this->ActualCommand); this->TestProcess->SetCommandArguments(this->Arguments); // determine how much time we have diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index cd2e2f7..bfe8d70 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -73,7 +73,7 @@ cmProcess::cmProcess(cmCTestRunTest& runner) cmProcess::~cmProcess() = default; -void cmProcess::SetCommand(const char* command) +void cmProcess::SetCommand(std::string const& command) { this->Command = command; } @@ -83,6 +83,11 @@ void cmProcess::SetCommandArguments(std::vector<std::string> const& args) this->Arguments = args; } +void cmProcess::SetWorkingDirectory(std::string const& dir) +{ + this->WorkingDirectory = dir; +} + bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity) { this->ProcessState = cmProcess::State::Error; diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h index e5ca17f..a0a4b6b 100644 --- a/Source/CTest/cmProcess.h +++ b/Source/CTest/cmProcess.h @@ -28,10 +28,9 @@ class cmProcess public: explicit cmProcess(cmCTestRunTest& runner); ~cmProcess(); - const char* GetCommand() { return this->Command.c_str(); } - void SetCommand(const char* command); + void SetCommand(std::string const& command); void SetCommandArguments(std::vector<std::string> const& arg); - void SetWorkingDirectory(const char* dir) { this->WorkingDirectory = dir; } + void SetWorkingDirectory(std::string const& dir); void SetTimeout(cmDuration t) { this->Timeout = t; } void ChangeTimeout(cmDuration t); void ResetStartTime(); diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake index d941c16..fb68ed7 100644 --- a/Source/Checks/cm_cxx_features.cmake +++ b/Source/Checks/cm_cxx_features.cmake @@ -27,7 +27,7 @@ function(cm_check_cxx_feature name) # Filter out xcodebuild warnings. string(REGEX REPLACE "[^\n]* xcodebuild\\[[0-9]*:[0-9]*\\] warning: [^\n]*" "" check_output "${check_output}") # If using the feature causes warnings, treat it as broken/unavailable. - if(check_output MATCHES "[Ww]arning") + if(check_output MATCHES "(^|[ :])[Ww][Aa][Rr][Nn][Ii][Nn][Gg]") set(CMake_HAVE_CXX_${FEATURE} OFF CACHE INTERNAL "TRY_COMPILE" FORCE) endif() if(CMake_HAVE_CXX_${FEATURE}) diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx index 906dd02..028e852 100644 --- a/Source/CursesDialog/cmCursesMainForm.cxx +++ b/Source/CursesDialog/cmCursesMainForm.cxx @@ -669,7 +669,7 @@ void cmCursesMainForm::FillCacheManagerFromUI() this->CMakeInstance->GetState()->GetCacheEntryValue(cacheKey); if (existingValue) { std::string oldValue = existingValue; - std::string newValue = entry->GetValue(); + std::string newValue = entry->Entry->GetValue(); std::string fixedOldValue; std::string fixedNewValue; cmStateEnums::CacheEntryType t = diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx index c2eb583..281d371 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.cxx +++ b/Source/cmGlobalBorlandMakefileGenerator.cxx @@ -53,15 +53,16 @@ void cmGlobalBorlandMakefileGenerator::GetDocumentation( entry.Brief = "Generates Borland makefiles."; } -void cmGlobalBorlandMakefileGenerator::GenerateBuildCommand( - GeneratedMakeCommand& makeCommand, const std::string& makeProgram, - const std::string& projectName, const std::string& projectDir, - const std::string& targetName, const std::string& config, bool fast, - int /*jobs*/, bool verbose, std::vector<std::string> const& makeOptions) +std::vector<cmGlobalGenerator::GeneratedMakeCommand> +cmGlobalBorlandMakefileGenerator::GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& projectDir, std::vector<std::string> const& targetNames, + const std::string& config, bool fast, int /*jobs*/, bool verbose, + std::vector<std::string> const& makeOptions) { - this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( - makeCommand, makeProgram, projectName, projectDir, targetName, config, - fast, cmake::NO_BUILD_PARALLEL_LEVEL, verbose, makeOptions); + return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( + makeProgram, projectName, projectDir, targetNames, config, fast, + cmake::NO_BUILD_PARALLEL_LEVEL, verbose, makeOptions); } void cmGlobalBorlandMakefileGenerator::PrintBuildCommandAdvice( diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h index ca04b7b..02d0d5f 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.h +++ b/Source/cmGlobalBorlandMakefileGenerator.h @@ -46,15 +46,12 @@ public: bool AllowDeleteOnError() const override { return false; } protected: - void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, - const std::string& makeProgram, - const std::string& projectName, - const std::string& projectDir, - const std::string& targetName, - const std::string& config, bool fast, int jobs, - bool verbose, - std::vector<std::string> const& makeOptions = - std::vector<std::string>()) override; + std::vector<GeneratedMakeCommand> GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& projectDir, std::vector<std::string> const& targetNames, + const std::string& config, bool fast, int jobs, bool verbose, + std::vector<std::string> const& makeOptions = + std::vector<std::string>()) override; void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override; }; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index c7b3591..6964b62 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1763,20 +1763,9 @@ int cmGlobalGenerator::TryCompile(int jobs, const std::string& srcdir, this->FirstTimeProgress); } - std::string newTarget; + std::vector<std::string> newTarget = {}; if (!target.empty()) { - newTarget += target; -#if 0 -# if defined(_WIN32) || defined(__CYGWIN__) - std::string tmp = target; - // if the target does not already end in . something - // then assume .exe - if(tmp.size() < 4 || tmp[tmp.size()-4] != '.') - { - newTarget += ".exe"; - } -# endif // WIN32 -#endif + newTarget = { target }; } std::string config = mf->GetSafeDefinition("CMAKE_TRY_COMPILE_CONFIGURATION"); @@ -1784,14 +1773,16 @@ int cmGlobalGenerator::TryCompile(int jobs, const std::string& srcdir, config, false, fast, false, this->TryCompileTimeout); } -void cmGlobalGenerator::GenerateBuildCommand( - GeneratedMakeCommand& makeCommand, const std::string& /*unused*/, - const std::string& /*unused*/, const std::string& /*unused*/, +std::vector<cmGlobalGenerator::GeneratedMakeCommand> +cmGlobalGenerator::GenerateBuildCommand( const std::string& /*unused*/, const std::string& /*unused*/, - bool /*unused*/, int /*unused*/, bool /*unused*/, - std::vector<std::string> const& /*unused*/) + const std::string& /*unused*/, std::vector<std::string> const& /*unused*/, + const std::string& /*unused*/, bool /*unused*/, int /*unused*/, + bool /*unused*/, std::vector<std::string> const& /*unused*/) { - makeCommand.add("cmGlobalGenerator::GenerateBuildCommand not implemented"); + GeneratedMakeCommand makeCommand; + makeCommand.Add("cmGlobalGenerator::GenerateBuildCommand not implemented"); + return { std::move(makeCommand) }; } void cmGlobalGenerator::PrintBuildCommandAdvice(std::ostream& /*os*/, @@ -1801,15 +1792,13 @@ void cmGlobalGenerator::PrintBuildCommandAdvice(std::ostream& /*os*/, // they do not support certain build command line options } -int cmGlobalGenerator::Build(int jobs, const std::string& /*unused*/, - const std::string& bindir, - const std::string& projectName, - const std::string& target, std::string& output, - const std::string& makeCommandCSTR, - const std::string& config, bool clean, bool fast, - bool verbose, cmDuration timeout, - cmSystemTools::OutputOption outputflag, - std::vector<std::string> const& nativeOptions) +int cmGlobalGenerator::Build( + int jobs, const std::string& /*unused*/, const std::string& bindir, + const std::string& projectName, const std::vector<std::string>& targets, + std::string& output, const std::string& makeCommandCSTR, + const std::string& config, bool clean, bool fast, bool verbose, + cmDuration timeout, cmSystemTools::OutputOption outputflag, + std::vector<std::string> const& nativeOptions) { bool hideconsole = cmSystemTools::GetRunCommandHideConsole(); @@ -1830,32 +1819,37 @@ int cmGlobalGenerator::Build(int jobs, const std::string& /*unused*/, return 1; } - int retVal; + int retVal = 0; cmSystemTools::SetRunCommandHideConsole(true); std::string outputBuffer; std::string* outputPtr = &outputBuffer; - GeneratedMakeCommand makeCommand; - this->GenerateBuildCommand(makeCommand, makeCommandCSTR, projectName, bindir, - target, config, fast, jobs, verbose, - nativeOptions); + std::vector<GeneratedMakeCommand> makeCommand = + this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir, targets, + config, fast, jobs, verbose, nativeOptions); // Workaround to convince some commands to produce output. if (outputflag == cmSystemTools::OUTPUT_PASSTHROUGH && - makeCommand.RequiresOutputForward) { + makeCommand.back().RequiresOutputForward) { outputflag = cmSystemTools::OUTPUT_FORWARD; } // should we do a clean first? if (clean) { - GeneratedMakeCommand cleanCommand; - this->GenerateBuildCommand(cleanCommand, makeCommandCSTR, projectName, - bindir, "clean", config, fast, jobs, verbose); + std::vector<GeneratedMakeCommand> cleanCommand = + this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir, + { "clean" }, config, fast, jobs, verbose); output += "\nRun Clean Command:"; - output += cleanCommand.printable(); + output += cleanCommand.front().Printable(); output += "\n"; - - if (!cmSystemTools::RunSingleCommand(cleanCommand.PrimaryCommand, + if (cleanCommand.size() != 1) { + this->GetCMakeInstance()->IssueMessage(MessageType::INTERNAL_ERROR, + "The generator did not produce " + "exactly one command for the " + "'clean' target"); + return 1; + } + if (!cmSystemTools::RunSingleCommand(cleanCommand.front().PrimaryCommand, outputPtr, outputPtr, &retVal, nullptr, outputflag, timeout)) { cmSystemTools::SetRunCommandHideConsole(hideconsole); @@ -1869,25 +1863,33 @@ int cmGlobalGenerator::Build(int jobs, const std::string& /*unused*/, } // now build - std::string makeCommandStr = makeCommand.printable(); + std::string makeCommandStr; output += "\nRun Build Command(s):"; - output += makeCommandStr; - output += "\n"; - if (!cmSystemTools::RunSingleCommand(makeCommand.PrimaryCommand, outputPtr, - outputPtr, &retVal, nullptr, outputflag, - timeout)) { - cmSystemTools::SetRunCommandHideConsole(hideconsole); - cmSystemTools::Error( - "Generator: execution of make failed. Make command was: " + - makeCommandStr); - output += *outputPtr; - output += "\nGenerator: execution of make failed. Make command was: " + - makeCommandStr + "\n"; + for (auto command = makeCommand.begin(); command != makeCommand.end(); + ++command) { + makeCommandStr = command->Printable(); + if (command != makeCommand.end()) { + makeCommandStr += " && "; + } - return 1; + output += makeCommandStr; + if (!cmSystemTools::RunSingleCommand(command->PrimaryCommand, outputPtr, + outputPtr, &retVal, nullptr, + outputflag, timeout)) { + cmSystemTools::SetRunCommandHideConsole(hideconsole); + cmSystemTools::Error( + "Generator: execution of make failed. Make command was: " + + makeCommandStr); + output += *outputPtr; + output += "\nGenerator: execution of make failed. Make command was: " + + makeCommandStr + "\n"; + + return 1; + } + output += *outputPtr; } - output += *outputPtr; + output += "\n"; cmSystemTools::SetRunCommandHideConsole(hideconsole); // The OpenWatcom tools do not return an error code when a link diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index ac01326..17eb340 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -13,6 +13,7 @@ #include <utility> #include <vector> +#include "cmAlgorithms.h" #include "cmCustomCommandLines.h" #include "cmDuration.h" #include "cmExportSetMap.h" @@ -56,33 +57,20 @@ struct GeneratedMakeCommand { // Add each argument as a separate element to the vector template <typename... T> - void add(T&&... args) + void Add(T&&... args) { // iterate the args and append each one AppendStrs(PrimaryCommand, std::forward<T>(args)...); } // Add each value in the iterators as a separate element to the vector - void add(std::vector<std::string>::const_iterator start, + void Add(std::vector<std::string>::const_iterator start, std::vector<std::string>::const_iterator end) { PrimaryCommand.insert(PrimaryCommand.end(), start, end); } - std::string printable() const - { - std::size_t size = PrimaryCommand.size(); - for (auto&& i : PrimaryCommand) { - size += i.size(); - } - std::string buffer; - buffer.reserve(size); - for (auto&& i : PrimaryCommand) { - buffer.append(i); - buffer.append(1, ' '); - } - return buffer; - } + std::string Printable() const { return cmJoin(PrimaryCommand, " "); } std::vector<std::string> PrimaryCommand; bool RequiresOutputForward = false; @@ -216,10 +204,10 @@ public: */ int Build( int jobs, const std::string& srcdir, const std::string& bindir, - const std::string& projectName, const std::string& targetName, - std::string& output, const std::string& makeProgram, - const std::string& config, bool clean, bool fast, bool verbose, - cmDuration timeout, + const std::string& projectName, + std::vector<std::string> const& targetNames, std::string& output, + const std::string& makeProgram, const std::string& config, bool clean, + bool fast, bool verbose, cmDuration timeout, cmSystemTools::OutputOption outputflag = cmSystemTools::OUTPUT_NONE, std::vector<std::string> const& nativeOptions = std::vector<std::string>()); @@ -234,11 +222,10 @@ public: { }; - virtual void GenerateBuildCommand( - GeneratedMakeCommand& makeCommand, const std::string& makeProgram, - const std::string& projectName, const std::string& projectDir, - const std::string& targetName, const std::string& config, bool fast, - int jobs, bool verbose, + virtual std::vector<GeneratedMakeCommand> GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& projectDir, std::vector<std::string> const& targetNames, + const std::string& config, bool fast, int jobs, bool verbose, std::vector<std::string> const& makeOptions = std::vector<std::string>()); virtual void PrintBuildCommandAdvice(std::ostream& os, int jobs) const; diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index 746ddad..4f1d06a 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -369,24 +369,26 @@ void cmGlobalGhsMultiGenerator::OutputTopLevelProject( fout.Close(); } -void cmGlobalGhsMultiGenerator::GenerateBuildCommand( - GeneratedMakeCommand& makeCommand, const std::string& makeProgram, - const std::string& projectName, const std::string& projectDir, - const std::string& targetName, const std::string& /*config*/, bool /*fast*/, - int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions) +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*/, bool /*fast*/, int jobs, bool /*verbose*/, + std::vector<std::string> const& makeOptions) { + GeneratedMakeCommand makeCommand = {}; const char* gbuild = this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM"); - makeCommand.add(this->SelectMakeProgram(makeProgram, (std::string)gbuild)); + makeCommand.Add(this->SelectMakeProgram(makeProgram, (std::string)gbuild)); if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) { - makeCommand.add("-parallel"); + makeCommand.Add("-parallel"); if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) { - makeCommand.add(std::to_string(jobs)); + makeCommand.Add(std::to_string(jobs)); } } - makeCommand.add(makeOptions.begin(), makeOptions.end()); + makeCommand.Add(makeOptions.begin(), makeOptions.end()); /* determine which top-project file to use */ std::string proj = projectName + ".top" + FILE_EXTENSION; @@ -399,18 +401,24 @@ void cmGlobalGhsMultiGenerator::GenerateBuildCommand( } } - makeCommand.add("-top", proj); - if (!targetName.empty()) { - if (targetName == "clean") { - makeCommand.add("-clean"); + makeCommand.Add("-top", proj); + if (!targetNames.empty()) { + if (std::find(targetNames.begin(), targetNames.end(), "clean") != + targetNames.end()) { + makeCommand.Add("-clean"); } else { - if (targetName.compare(targetName.size() - 4, 4, ".gpj") == 0) { - makeCommand.add(targetName); - } else { - makeCommand.add(targetName + ".gpj"); + for (const auto& tname : targetNames) { + if (!tname.empty()) { + if (tname.compare(tname.size() - 4, 4, ".gpj") == 0) { + makeCommand.Add(tname); + } else { + makeCommand.Add(tname + ".gpj"); + } + } } } } + return { makeCommand }; } void cmGlobalGhsMultiGenerator::WriteMacros(std::ostream& fout) diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index bc2b199..c39f40f 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -88,15 +88,12 @@ public: protected: void Generate() override; - void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, - const std::string& makeProgram, - const std::string& projectName, - const std::string& projectDir, - const std::string& targetName, - const std::string& config, bool fast, int jobs, - bool verbose, - std::vector<std::string> const& makeOptions = - std::vector<std::string>()) override; + std::vector<GeneratedMakeCommand> GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& projectDir, std::vector<std::string> const& targetNames, + const std::string& config, bool fast, int jobs, bool verbose, + std::vector<std::string> const& makeOptions = + std::vector<std::string>()) override; private: void GetToolset(cmMakefile* mf, std::string& tsd, const std::string& ts); diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx index 2b7f486..43c9666 100644 --- a/Source/cmGlobalJOMMakefileGenerator.cxx +++ b/Source/cmGlobalJOMMakefileGenerator.cxx @@ -54,11 +54,12 @@ void cmGlobalJOMMakefileGenerator::PrintCompilerAdvice( this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar); } -void cmGlobalJOMMakefileGenerator::GenerateBuildCommand( - GeneratedMakeCommand& makeCommand, const std::string& makeProgram, - const std::string& projectName, const std::string& projectDir, - const std::string& targetName, const std::string& config, bool fast, - int jobs, bool verbose, std::vector<std::string> const& makeOptions) +std::vector<cmGlobalGenerator::GeneratedMakeCommand> +cmGlobalJOMMakefileGenerator::GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& projectDir, std::vector<std::string> const& targetNames, + const std::string& config, bool fast, int jobs, bool verbose, + std::vector<std::string> const& makeOptions) { std::vector<std::string> jomMakeOptions; @@ -75,7 +76,7 @@ void cmGlobalJOMMakefileGenerator::GenerateBuildCommand( jobs = cmake::NO_BUILD_PARALLEL_LEVEL; } - cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( - makeCommand, makeProgram, projectName, projectDir, targetName, config, - fast, jobs, verbose, jomMakeOptions); + return cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( + makeProgram, projectName, projectDir, targetNames, config, fast, jobs, + verbose, jomMakeOptions); } diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h index aa8b5fb..341b2dd 100644 --- a/Source/cmGlobalJOMMakefileGenerator.h +++ b/Source/cmGlobalJOMMakefileGenerator.h @@ -40,15 +40,12 @@ public: bool optional) override; protected: - void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, - const std::string& makeProgram, - const std::string& projectName, - const std::string& projectDir, - const std::string& targetName, - const std::string& config, bool fast, int jobs, - bool verbose, - std::vector<std::string> const& makeOptions = - std::vector<std::string>()) override; + std::vector<GeneratedMakeCommand> GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& projectDir, std::vector<std::string> const& targetNames, + const std::string& config, bool fast, int jobs, bool verbose, + std::vector<std::string> const& makeOptions = + std::vector<std::string>()) override; private: void PrintCompilerAdvice(std::ostream& os, std::string const& lang, diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index ffe95f9..a4838bc 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/Source/cmGlobalNMakeMakefileGenerator.cxx @@ -54,11 +54,12 @@ void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice( this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar); } -void cmGlobalNMakeMakefileGenerator::GenerateBuildCommand( - GeneratedMakeCommand& makeCommand, const std::string& makeProgram, - const std::string& projectName, const std::string& projectDir, - const std::string& targetName, const std::string& config, bool fast, - int /*jobs*/, bool verbose, std::vector<std::string> const& makeOptions) +std::vector<cmGlobalGenerator::GeneratedMakeCommand> +cmGlobalNMakeMakefileGenerator::GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& projectDir, std::vector<std::string> const& targetNames, + const std::string& config, bool fast, int /*jobs*/, bool verbose, + std::vector<std::string> const& makeOptions) { std::vector<std::string> nmakeMakeOptions; @@ -68,9 +69,9 @@ void cmGlobalNMakeMakefileGenerator::GenerateBuildCommand( nmakeMakeOptions.insert(nmakeMakeOptions.end(), makeOptions.begin(), makeOptions.end()); - this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( - makeCommand, makeProgram, projectName, projectDir, targetName, config, - fast, cmake::NO_BUILD_PARALLEL_LEVEL, verbose, nmakeMakeOptions); + return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( + makeProgram, projectName, projectDir, targetNames, config, fast, + cmake::NO_BUILD_PARALLEL_LEVEL, verbose, nmakeMakeOptions); } void cmGlobalNMakeMakefileGenerator::PrintBuildCommandAdvice(std::ostream& os, diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index 06c48e2..1fc2f9c 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -45,15 +45,12 @@ public: bool optional) override; protected: - void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, - const std::string& makeProgram, - const std::string& projectName, - const std::string& projectDir, - const std::string& targetName, - const std::string& config, bool fast, int jobs, - bool verbose, - std::vector<std::string> const& makeOptions = - std::vector<std::string>()) override; + std::vector<GeneratedMakeCommand> GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& projectDir, std::vector<std::string> const& targetNames, + const std::string& config, bool fast, int jobs, bool verbose, + std::vector<std::string> const& makeOptions = + std::vector<std::string>()) override; void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override; diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index d21fd35..841587c 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -677,31 +677,37 @@ void cmGlobalNinjaGenerator::EnableLanguage( // cmGlobalXCodeGenerator // Called by: // cmGlobalGenerator::Build() -void cmGlobalNinjaGenerator::GenerateBuildCommand( - GeneratedMakeCommand& makeCommand, const std::string& makeProgram, - const std::string& /*projectName*/, const std::string& /*projectDir*/, - const std::string& targetName, const std::string& /*config*/, bool /*fast*/, - int jobs, bool verbose, std::vector<std::string> const& makeOptions) +std::vector<cmGlobalGenerator::GeneratedMakeCommand> +cmGlobalNinjaGenerator::GenerateBuildCommand( + const std::string& makeProgram, const std::string& /*projectName*/, + const std::string& /*projectDir*/, + std::vector<std::string> const& targetNames, const std::string& /*config*/, + bool /*fast*/, int jobs, bool verbose, + std::vector<std::string> const& makeOptions) { - makeCommand.add(this->SelectMakeProgram(makeProgram)); + GeneratedMakeCommand makeCommand; + makeCommand.Add(this->SelectMakeProgram(makeProgram)); if (verbose) { - makeCommand.add("-v"); + makeCommand.Add("-v"); } if ((jobs != cmake::NO_BUILD_PARALLEL_LEVEL) && (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL)) { - makeCommand.add("-j", std::to_string(jobs)); + makeCommand.Add("-j", std::to_string(jobs)); } - makeCommand.add(makeOptions.begin(), makeOptions.end()); - if (!targetName.empty()) { - if (targetName == "clean") { - makeCommand.add("-t", "clean"); - } else { - makeCommand.add(targetName); + makeCommand.Add(makeOptions.begin(), makeOptions.end()); + for (const auto& tname : targetNames) { + if (!tname.empty()) { + if (tname == "clean") { + makeCommand.Add("-t", "clean"); + } else { + makeCommand.Add(tname); + } } } + return { std::move(makeCommand) }; } // Non-virtual public methods. diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 69210ec..efd1d8f 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -200,15 +200,12 @@ public: void EnableLanguage(std::vector<std::string> const& languages, cmMakefile* mf, bool optional) override; - void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, - const std::string& makeProgram, - const std::string& projectName, - const std::string& projectDir, - const std::string& targetName, - const std::string& config, bool fast, int jobs, - bool verbose, - std::vector<std::string> const& makeOptions = - std::vector<std::string>()) override; + std::vector<GeneratedMakeCommand> GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& projectDir, std::vector<std::string> const& targetNames, + const std::string& config, bool fast, int jobs, bool verbose, + std::vector<std::string> const& makeOptions = + std::vector<std::string>()) override; // Setup target names const char* GetAllTargetName() const override { return "all"; } diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index dac6ea6..3381c81 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -494,11 +494,13 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2( this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", true, true); } -void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( - GeneratedMakeCommand& makeCommand, const std::string& makeProgram, - const std::string& /*projectName*/, const std::string& /*projectDir*/, - const std::string& targetName, const std::string& /*config*/, bool fast, - int jobs, bool verbose, std::vector<std::string> const& makeOptions) +std::vector<cmGlobalGenerator::GeneratedMakeCommand> +cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( + const std::string& makeProgram, const std::string& /*projectName*/, + const std::string& /*projectDir*/, + std::vector<std::string> const& targetNames, const std::string& /*config*/, + bool fast, int jobs, bool verbose, + std::vector<std::string> const& makeOptions) { std::unique_ptr<cmMakefile> mfu; cmMakefile* mf; @@ -515,34 +517,38 @@ void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( mf = mfu.get(); } + GeneratedMakeCommand makeCommand; + // Make it possible to set verbosity also from command line if (verbose) { - makeCommand.add(cmSystemTools::GetCMakeCommand()); - makeCommand.add("-E"); - makeCommand.add("env"); - makeCommand.add("VERBOSE=1"); + makeCommand.Add(cmSystemTools::GetCMakeCommand()); + makeCommand.Add("-E"); + makeCommand.Add("env"); + makeCommand.Add("VERBOSE=1"); } - makeCommand.add(this->SelectMakeProgram(makeProgram)); + makeCommand.Add(this->SelectMakeProgram(makeProgram)); if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) { - makeCommand.add("-j"); + makeCommand.Add("-j"); if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) { - makeCommand.add(std::to_string(jobs)); + makeCommand.Add(std::to_string(jobs)); } } - makeCommand.add(makeOptions.begin(), makeOptions.end()); - if (!targetName.empty()) { - std::string tname = targetName; - if (fast) { - tname += "/fast"; + makeCommand.Add(makeOptions.begin(), makeOptions.end()); + for (auto tname : targetNames) { + if (!tname.empty()) { + if (fast) { + tname += "/fast"; + } + tname = + mf->GetStateSnapshot().GetDirectory().ConvertToRelPathIfNotContained( + mf->GetState()->GetBinaryDirectory(), tname); + cmSystemTools::ConvertToOutputSlashes(tname); + makeCommand.Add(std::move(tname)); } - tname = - mf->GetStateSnapshot().GetDirectory().ConvertToRelPathIfNotContained( - mf->GetState()->GetBinaryDirectory(), tname); - cmSystemTools::ConvertToOutputSlashes(tname); - makeCommand.add(std::move(tname)); } + return { std::move(makeCommand) }; } void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 8a80acc..496104d 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -127,15 +127,12 @@ public: std::string GetEmptyRuleHackDepends() { return this->EmptyRuleHackDepends; } // change the build command for speed - void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, - const std::string& makeProgram, - const std::string& projectName, - const std::string& projectDir, - const std::string& targetName, - const std::string& config, bool fast, int jobs, - bool verbose, - std::vector<std::string> const& makeOptions = - std::vector<std::string>()) override; + std::vector<GeneratedMakeCommand> GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& projectDir, std::vector<std::string> const& targetNames, + const std::string& config, bool fast, int jobs, bool verbose, + std::vector<std::string> const& makeOptions = + std::vector<std::string>()) override; /** Record per-target progress information. */ void RecordTargetProgress(cmMakefileTargetGenerator* tg); diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index f872de5..26fd62b 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -878,12 +878,14 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf) return true; } -void cmGlobalVisualStudio10Generator::GenerateBuildCommand( - GeneratedMakeCommand& makeCommand, const std::string& makeProgram, - const std::string& projectName, const std::string& projectDir, - const std::string& targetName, const std::string& config, bool fast, - int jobs, bool verbose, std::vector<std::string> const& makeOptions) +std::vector<cmGlobalGenerator::GeneratedMakeCommand> +cmGlobalVisualStudio10Generator::GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& projectDir, std::vector<std::string> const& targetNames, + const std::string& config, bool fast, int jobs, bool verbose, + std::vector<std::string> const& makeOptions) { + std::vector<GeneratedMakeCommand> makeCommands; // Select the caller- or user-preferred make program, else MSBuild. std::string makeProgramSelected = this->SelectMakeProgram(makeProgram, this->GetMSBuildCommand()); @@ -895,7 +897,7 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand( makeProgramLower.find("vcexpress") != std::string::npos); // Workaround to convince VCExpress.exe to produce output. - makeCommand.RequiresOutputForward = + const bool requiresOutputForward = (makeProgramLower.find("vcexpress") != std::string::npos); // MSBuild is preferred (and required for VS Express), but if the .sln has @@ -926,62 +928,71 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand( } if (useDevEnv) { // Use devenv to build solutions containing Intel Fortran projects. - cmGlobalVisualStudio7Generator::GenerateBuildCommand( - makeCommand, makeProgram, projectName, projectDir, targetName, config, - fast, jobs, verbose, makeOptions); - return; - } + return cmGlobalVisualStudio7Generator::GenerateBuildCommand( + makeProgram, projectName, projectDir, targetNames, config, fast, jobs, + verbose, makeOptions); + } + + std::vector<std::string> realTargetNames = targetNames; + if (targetNames.empty() || + ((targetNames.size() == 1) && targetNames.front().empty())) { + realTargetNames = { "ALL_BUILD" }; + } + for (const auto& tname : realTargetNames) { + // msbuild.exe CxxOnly.sln /t:Build /p:Configuration=Debug + // /target:ALL_BUILD + // /m + if (tname.empty()) { + continue; + } - makeCommand.add(makeProgramSelected); + GeneratedMakeCommand makeCommand; + makeCommand.RequiresOutputForward = requiresOutputForward; + makeCommand.Add(makeProgramSelected); - std::string realTarget = targetName; - // msbuild.exe CxxOnly.sln /t:Build /p:Configuration=Debug /target:ALL_BUILD - // /m - if (realTarget.empty()) { - realTarget = "ALL_BUILD"; - } - if (realTarget == "clean") { - makeCommand.add(std::string(projectName) + ".sln"); - makeCommand.add("/t:Clean"); - } else { - std::string targetProject(realTarget); - targetProject += ".vcxproj"; - if (targetProject.find('/') == std::string::npos) { - // it might be in a subdir - if (cmSlnProjectEntry const* proj = - slnData.GetProjectByName(realTarget)) { - targetProject = proj->GetRelativePath(); - cmSystemTools::ConvertToUnixSlashes(targetProject); + if (tname == "clean") { + makeCommand.Add(std::string(projectName) + ".sln"); + makeCommand.Add("/t:Clean"); + } else { + std::string targetProject(tname); + targetProject += ".vcxproj"; + if (targetProject.find('/') == std::string::npos) { + // it might be in a subdir + if (cmSlnProjectEntry const* proj = slnData.GetProjectByName(tname)) { + targetProject = proj->GetRelativePath(); + cmSystemTools::ConvertToUnixSlashes(targetProject); + } } + makeCommand.Add(std::move(targetProject)); } - makeCommand.add(std::move(targetProject)); - } - std::string configArg = "/p:Configuration="; - if (!config.empty()) { - configArg += config; - } else { - configArg += "Debug"; - } - makeCommand.add(configArg); - makeCommand.add(std::string("/p:Platform=") + this->GetPlatformName()); - makeCommand.add(std::string("/p:VisualStudioVersion=") + - this->GetIDEVersion()); - - if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) { - if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) { - makeCommand.add("/m"); + std::string configArg = "/p:Configuration="; + if (!config.empty()) { + configArg += config; } else { - makeCommand.add(std::string("/m:") + std::to_string(jobs)); + configArg += "Debug"; + } + makeCommand.Add(configArg); + makeCommand.Add(std::string("/p:Platform=") + this->GetPlatformName()); + makeCommand.Add(std::string("/p:VisualStudioVersion=") + + this->GetIDEVersion()); + + if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) { + if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) { + makeCommand.Add("/m"); + } else { + makeCommand.Add(std::string("/m:") + std::to_string(jobs)); + } + // Having msbuild.exe and cl.exe using multiple jobs is discouraged + makeCommand.Add("/p:CL_MPCount=1"); } - // Having msbuild.exe and cl.exe using multiple jobs is discouraged - makeCommand.add("/p:CL_MPCount=1"); - } - - // Respect the verbosity: 'n' normal will show build commands - // 'm' minimal only the build step's title - makeCommand.add(std::string("/v:") + ((verbose) ? "n" : "m")); - makeCommand.add(makeOptions.begin(), makeOptions.end()); + // Respect the verbosity: 'n' normal will show build commands + // 'm' minimal only the build step's title + makeCommand.Add(std::string("/v:") + ((verbose) ? "n" : "m")); + makeCommand.Add(makeOptions.begin(), makeOptions.end()); + makeCommands.emplace_back(std::move(makeCommand)); + } + return makeCommands; } bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf) diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 3ef7abf..26db929 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -22,15 +22,12 @@ public: bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override; bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override; - void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, - const std::string& makeProgram, - const std::string& projectName, - const std::string& projectDir, - const std::string& targetName, - const std::string& config, bool fast, int jobs, - bool verbose, - std::vector<std::string> const& makeOptions = - std::vector<std::string>()) override; + std::vector<GeneratedMakeCommand> GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& projectDir, std::vector<std::string> const& targetNames, + const std::string& config, bool fast, int jobs, bool verbose, + std::vector<std::string> const& makeOptions = + std::vector<std::string>()) override; ///! create the correct local generator cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override; diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index d457f60..c694902 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -190,11 +190,14 @@ const char* cmGlobalVisualStudio7Generator::ExternalProjectType( } return "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942"; } -void cmGlobalVisualStudio7Generator::GenerateBuildCommand( - GeneratedMakeCommand& makeCommand, const std::string& makeProgram, - const std::string& projectName, const std::string& /*projectDir*/, - const std::string& targetName, const std::string& config, bool /*fast*/, - int /*jobs*/, bool /*verbose*/, std::vector<std::string> const& makeOptions) + +std::vector<cmGlobalGenerator::GeneratedMakeCommand> +cmGlobalVisualStudio7Generator::GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& /*projectDir*/, + std::vector<std::string> const& targetNames, const std::string& config, + bool /*fast*/, int /*jobs*/, bool /*verbose*/, + std::vector<std::string> const& makeOptions) { // Select the caller- or user-preferred make program, else devenv. std::string makeProgramSelected = @@ -210,24 +213,39 @@ void cmGlobalVisualStudio7Generator::GenerateBuildCommand( } // Workaround to convince VCExpress.exe to produce output. - makeCommand.RequiresOutputForward = + const bool requiresOutputForward = (makeProgramLower.find("vcexpress") != std::string::npos); + std::vector<GeneratedMakeCommand> makeCommands; - makeCommand.add(makeProgramSelected); - - makeCommand.add(std::string(projectName) + ".sln"); - std::string realTarget = targetName; - bool clean = false; - if (realTarget == "clean") { - clean = true; - realTarget = "ALL_BUILD"; + std::vector<std::string> realTargetNames = targetNames; + if (targetNames.empty() || + ((targetNames.size() == 1) && targetNames.front().empty())) { + realTargetNames = { "ALL_BUILD" }; } - - makeCommand.add((clean ? "/clean" : "/build")); - makeCommand.add((config.empty() ? "Debug" : config)); - makeCommand.add("/project"); - makeCommand.add((realTarget.empty() ? "ALL_BUILD" : realTarget)); - makeCommand.add(makeOptions.begin(), makeOptions.end()); + for (const auto& tname : realTargetNames) { + std::string realTarget; + if (!tname.empty()) { + realTarget = tname; + } else { + continue; + } + bool clean = false; + if (realTarget == "clean") { + clean = true; + realTarget = "ALL_BUILD"; + } + GeneratedMakeCommand makeCommand; + makeCommand.RequiresOutputForward = requiresOutputForward; + makeCommand.Add(makeProgramSelected); + makeCommand.Add(std::string(projectName) + ".sln"); + makeCommand.Add((clean ? "/clean" : "/build")); + makeCommand.Add((config.empty() ? "Debug" : config)); + makeCommand.Add("/project"); + makeCommand.Add(realTarget); + makeCommand.Add(makeOptions.begin(), makeOptions.end()); + makeCommands.emplace_back(std::move(makeCommand)); + } + return makeCommands; } ///! Create a local generator appropriate to this Global Generator diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 3f1c173..954d1d3 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -52,15 +52,12 @@ public: * Try running cmake and building a file. This is used for dynamically * loaded commands, not as part of the usual build process. */ - void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, - const std::string& makeProgram, - const std::string& projectName, - const std::string& projectDir, - const std::string& targetName, - const std::string& config, bool fast, int jobs, - bool verbose, - std::vector<std::string> const& makeOptions = - std::vector<std::string>()) override; + std::vector<GeneratedMakeCommand> GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& projectDir, std::vector<std::string> const& targetNames, + const std::string& config, bool fast, int jobs, bool verbose, + std::vector<std::string> const& makeOptions = + std::vector<std::string>()) override; /** * Generate the DSW workspace file. diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 45927c9..bc40a5c 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -834,6 +834,10 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly( if (linkLang && *linkLang) { languages.insert(linkLang); } + + // Intel Fortran .vfproj files do support the resource compiler. + languages.erase("RC"); + return languages.size() == 1 && *languages.begin() == "Fortran"; } diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index 2f9eb3f..94f6b68 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -206,8 +206,8 @@ class cmGlobalVisualStudioVersionedGenerator::Factory16 : public cmGlobalGeneratorFactory { public: - virtual cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const + cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, + cmake* cm) const override { std::string genName; const char* p = cmVS16GenName(name, genName); @@ -221,7 +221,7 @@ public: return 0; } - virtual void GetDocumentation(cmDocumentationEntry& entry) const + void GetDocumentation(cmDocumentationEntry& entry) const override { entry.Name = std::string(vs16generatorName); entry.Brief = "Generates Visual Studio 2019 project files. " diff --git a/Source/cmGlobalWatcomWMakeGenerator.cxx b/Source/cmGlobalWatcomWMakeGenerator.cxx index c02c471..8a27384 100644 --- a/Source/cmGlobalWatcomWMakeGenerator.cxx +++ b/Source/cmGlobalWatcomWMakeGenerator.cxx @@ -3,6 +3,7 @@ #include "cmGlobalWatcomWMakeGenerator.h" #include "cmDocumentationEntry.h" +#include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmState.h" #include "cmake.h" @@ -50,15 +51,16 @@ void cmGlobalWatcomWMakeGenerator::GetDocumentation( entry.Brief = "Generates Watcom WMake makefiles."; } -void cmGlobalWatcomWMakeGenerator::GenerateBuildCommand( - GeneratedMakeCommand& makeCommand, const std::string& makeProgram, - const std::string& projectName, const std::string& projectDir, - const std::string& targetName, const std::string& config, bool fast, - int /*jobs*/, bool verbose, std::vector<std::string> const& makeOptions) +std::vector<cmGlobalGenerator::GeneratedMakeCommand> +cmGlobalWatcomWMakeGenerator::GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& projectDir, std::vector<std::string> const& targetNames, + const std::string& config, bool fast, int /*jobs*/, bool verbose, + std::vector<std::string> const& makeOptions) { - this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( - makeCommand, makeProgram, projectName, projectDir, targetName, config, - fast, cmake::NO_BUILD_PARALLEL_LEVEL, verbose, makeOptions); + return this->cmGlobalUnixMakefileGenerator3::GenerateBuildCommand( + makeProgram, projectName, projectDir, targetNames, config, fast, + cmake::NO_BUILD_PARALLEL_LEVEL, verbose, makeOptions); } void cmGlobalWatcomWMakeGenerator::PrintBuildCommandAdvice(std::ostream& os, diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h index 6680b19..c96dc72 100644 --- a/Source/cmGlobalWatcomWMakeGenerator.h +++ b/Source/cmGlobalWatcomWMakeGenerator.h @@ -50,15 +50,12 @@ public: bool AllowDeleteOnError() const override { return false; } protected: - void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, - const std::string& makeProgram, - const std::string& projectName, - const std::string& projectDir, - const std::string& targetName, - const std::string& config, bool fast, int jobs, - bool verbose, - std::vector<std::string> const& makeOptions = - std::vector<std::string>()) override; + std::vector<GeneratedMakeCommand> GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& projectDir, std::vector<std::string> const& targetNames, + const std::string& config, bool fast, int jobs, bool verbose, + std::vector<std::string> const& makeOptions = + std::vector<std::string>()) override; void PrintBuildCommandAdvice(std::ostream& os, int jobs) const override; }; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 11cc98e..53baed5 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -334,46 +334,58 @@ bool cmGlobalXCodeGenerator::Open(const std::string& bindir, return ret; } -void cmGlobalXCodeGenerator::GenerateBuildCommand( - GeneratedMakeCommand& makeCommand, const std::string& makeProgram, - const std::string& projectName, const std::string& /*projectDir*/, - const std::string& targetName, const std::string& config, bool /*fast*/, - int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions) -{ +std::vector<cmGlobalGenerator::GeneratedMakeCommand> +cmGlobalXCodeGenerator::GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& /*projectDir*/, + std::vector<std::string> const& targetNames, const std::string& config, + bool /*fast*/, int jobs, bool /*verbose*/, + std::vector<std::string> const& makeOptions) +{ + GeneratedMakeCommand makeCommand; // now build the test - makeCommand.add( + makeCommand.Add( this->SelectMakeProgram(makeProgram, this->GetXcodeBuildCommand())); if (!projectName.empty()) { - makeCommand.add("-project"); + makeCommand.Add("-project"); std::string projectArg = projectName; projectArg += ".xcode"; projectArg += "proj"; - makeCommand.add(projectArg); + makeCommand.Add(projectArg); } - - bool clean = false; - std::string realTarget = targetName; - if (realTarget == "clean") { - clean = true; - realTarget = "ALL_BUILD"; + if (std::find(targetNames.begin(), targetNames.end(), "clean") != + targetNames.end()) { + makeCommand.Add("clean"); + makeCommand.Add("-target", "ALL_BUILD"); + } else { + makeCommand.Add("build"); + if (targetNames.empty() || + ((targetNames.size() == 1) && targetNames.front().empty())) { + makeCommand.Add("-target", "ALL_BUILD"); + } else { + for (const auto& tname : targetNames) { + if (!tname.empty()) { + makeCommand.Add("-target", tname); + } + } + } } - makeCommand.add((clean ? "clean" : "build")); - makeCommand.add("-target", (realTarget.empty() ? "ALL_BUILD" : realTarget)); - makeCommand.add("-configuration", (config.empty() ? "Debug" : config)); + makeCommand.Add("-configuration", (config.empty() ? "Debug" : config)); if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) { - makeCommand.add("-jobs"); + makeCommand.Add("-jobs"); if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) { - makeCommand.add(std::to_string(jobs)); + makeCommand.Add(std::to_string(jobs)); } } if (this->XcodeVersion >= 70) { - makeCommand.add("-hideShellScriptEnvironment"); + makeCommand.Add("-hideShellScriptEnvironment"); } - makeCommand.add(makeOptions.begin(), makeOptions.end()); + makeCommand.Add(makeOptions.begin(), makeOptions.end()); + return { std::move(makeCommand) }; } ///! Create a local generator appropriate to this Global Generator diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index e1e412d..95db852 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -66,15 +66,12 @@ public: * Try running cmake and building a file. This is used for dynalically * loaded commands, not as part of the usual build process. */ - void GenerateBuildCommand(GeneratedMakeCommand& makeCommand, - const std::string& makeProgram, - const std::string& projectName, - const std::string& projectDir, - const std::string& targetName, - const std::string& config, bool fast, int jobs, - bool verbose, - std::vector<std::string> const& makeOptions = - std::vector<std::string>()) override; + std::vector<GeneratedMakeCommand> GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& projectDir, std::vector<std::string> const& targetNames, + const std::string& config, bool fast, int jobs, bool verbose, + std::vector<std::string> const& makeOptions = + std::vector<std::string>()) override; /** Append the subdirectory for the given configuration. */ void AppendDirectoryForConfig(const std::string& prefix, diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 8ef6441..20d1a31 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -402,7 +402,11 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) cmTarget* target = this->Makefile->FindLocalNonAliasTarget(tgt); if (!target) { // If no local target has been found, find it in the global scope. - target = this->Makefile->GetGlobalGenerator()->FindTarget(tgt, true); + cmTarget* const global_target = + this->Makefile->GetGlobalGenerator()->FindTarget(tgt, true); + if (global_target && !global_target->IsImported()) { + target = global_target; + } } if (target) { // Found the target. Check its type. diff --git a/Source/cmLocalGhsMultiGenerator.h b/Source/cmLocalGhsMultiGenerator.h index d5bec42..2584fd3 100644 --- a/Source/cmLocalGhsMultiGenerator.h +++ b/Source/cmLocalGhsMultiGenerator.h @@ -23,7 +23,7 @@ public: /** * Generate the makefile for this directory. */ - virtual void Generate(); + void Generate() override; std::string GetTargetDirectory( cmGeneratorTarget const* target) const override; diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 2fb6fdf..ef8fe73 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -594,7 +594,7 @@ bool cmQtAutoGenInitializer::InitRcc() if (this->QtVersion.Major == 5 || this->QtVersion.Major == 6) { if (stdOut.find("--list") != std::string::npos) { this->Rcc.ListOptions.emplace_back("--list"); - } else { + } else if (stdOut.find("-list") != std::string::npos) { this->Rcc.ListOptions.emplace_back("-list"); } } @@ -1581,6 +1581,10 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, print_err(prop + " evaluates to an empty value"); return false; } + + // Check if the provided executable already exists (it's possible for it + // not to exist when building Qt itself). + genVars.ExecutableExists = cmSystemTools::FileExists(genVars.Executable); return true; } } @@ -1630,6 +1634,7 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, print_err(err); return false; } + genVars.ExecutableExists = true; } return true; @@ -1648,7 +1653,7 @@ bool cmQtAutoGenInitializer::RccListInputs(std::string const& fileName, error += "\n"; return false; } - if (!this->Rcc.ListOptions.empty()) { + if (this->Rcc.ExecutableExists && !this->Rcc.ListOptions.empty()) { // Use rcc for file listing if (this->Rcc.Executable.empty()) { error = "rcc executable not available"; diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 700f16b..1f4087f 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -68,6 +68,7 @@ public: std::string ExecutableTargetName; cmGeneratorTarget* ExecutableTarget = nullptr; std::string Executable; + bool ExecutableExists = false; /// @brief Constructor GenVarsT(GenT gen, std::string const& genName, diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index b655815..5c9f25e 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -35,6 +35,7 @@ static std::string cmVS10EscapeAttr(std::string arg) cmSystemTools::ReplaceString(arg, "<", "<"); cmSystemTools::ReplaceString(arg, ">", ">"); cmSystemTools::ReplaceString(arg, "\"", """); + cmSystemTools::ReplaceString(arg, "\n", " "); return arg; } diff --git a/Source/cmake.cxx b/Source/cmake.cxx index f6f0a95..08e284e 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -116,10 +116,8 @@ typedef std::unordered_map<std::string, Json::Value> JsonValueMapType; } // namespace -static bool cmakeCheckStampFile(const std::string& stampName, - bool verbose = true); -static bool cmakeCheckStampList(const std::string& stampList, - bool verbose = true); +static bool cmakeCheckStampFile(const std::string& stampName); +static bool cmakeCheckStampList(const std::string& stampList); void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/, void* ctx, const char* /*unused*/, @@ -2410,7 +2408,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args) return 0; } -static bool cmakeCheckStampFile(const std::string& stampName, bool verbose) +static bool cmakeCheckStampFile(const std::string& stampName) { // The stamp file does not exist. Use the stamp dependencies to // determine whether it is really out of date. This works in @@ -2462,13 +2460,7 @@ static bool cmakeCheckStampFile(const std::string& stampName, bool verbose) stamp << "# CMake generation timestamp file for this directory.\n"; } if (cmSystemTools::RenameFile(stampTemp, stampName)) { - if (verbose) { - // Notify the user why CMake is not re-running. It is safe to - // just print to stdout here because this code is only reachable - // through an undocumented flag used by the VS generator. - std::cout << "CMake does not need to re-run because " << stampName - << " is up-to-date.\n"; - } + // CMake does not need to re-run because the stamp file is up-to-date. return true; } cmSystemTools::RemoveFile(stampTemp); @@ -2476,7 +2468,7 @@ static bool cmakeCheckStampFile(const std::string& stampName, bool verbose) return false; } -static bool cmakeCheckStampList(const std::string& stampList, bool verbose) +static bool cmakeCheckStampList(const std::string& stampList) { // If the stamp list does not exist CMake must rerun to generate it. if (!cmSystemTools::FileExists(stampList)) { @@ -2494,7 +2486,7 @@ static bool cmakeCheckStampList(const std::string& stampList, bool verbose) // Check each stamp. std::string stampName; while (cmSystemTools::GetLineFromStream(fin, stampName)) { - if (!cmakeCheckStampFile(stampName, verbose)) { + if (!cmakeCheckStampFile(stampName)) { return false; } } @@ -2529,7 +2521,8 @@ cmMessenger* cmake::GetMessenger() const return this->Messenger; } -int cmake::Build(int jobs, const std::string& dir, const std::string& target, +int cmake::Build(int jobs, const std::string& dir, + const std::vector<std::string>& targets, const std::string& config, const std::vector<std::string>& nativeOptions, bool clean, bool verbose) @@ -2615,7 +2608,7 @@ int cmake::Build(int jobs, const std::string& dir, const std::string& target, } } - if (!cmakeCheckStampList(stampList, false)) { + if (!cmakeCheckStampList(stampList)) { // Correctly initialize the home (=source) and home output (=binary) // directories, which is required for running the generation step. std::string homeOrig = this->GetHomeDirectory(); @@ -2648,9 +2641,8 @@ int cmake::Build(int jobs, const std::string& dir, const std::string& target, #endif gen->PrintBuildCommandAdvice(std::cerr, jobs); - - return gen->Build(jobs, "", dir, projName, target, output, "", config, clean, - false, verbose, cmDuration::zero(), + return gen->Build(jobs, "", dir, projName, targets, output, "", config, + clean, false, verbose, cmDuration::zero(), cmSystemTools::OUTPUT_PASSTHROUGH, nativeOptions); } diff --git a/Source/cmake.h b/Source/cmake.h index 6fa2d3a..1ffeabc 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -424,8 +424,8 @@ public: cmListFileBacktrace const& backtrace = cmListFileBacktrace()) const; ///! run the --build option - int Build(int jobs, const std::string& dir, const std::string& target, - const std::string& config, + int Build(int jobs, const std::string& dir, + const std::vector<std::string>& targets, const std::string& config, const std::vector<std::string>& nativeOptions, bool clean, bool verbose); diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index e6f4021..1c56bcd 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -63,11 +63,10 @@ static const char* cmDocumentationUsageNote[][2] = { "option\n" \ " is not given.\n" \ " --target <tgt> = Build <tgt> instead of default targets.\n" \ - " May only be specified once.\n" \ + " May be specified multiple times.\n" \ " --config <cfg> = For multi-configuration tools, choose <cfg>.\n" \ " --clean-first = Build target 'clean' first, then build.\n" \ " (To clean only, use --target 'clean'.)\n" \ - " --use-stderr = Ignored. Behavior is default in CMake >= 3.0.\n" \ " -v --verbose = Enable verbose output - if supported - including\n" \ " the build commands to be executed. \n" \ " -- = Pass remaining options to the native tool.\n" @@ -395,13 +394,14 @@ static int do_build(int ac, char const* const* av) return -1; #else int jobs = cmake::NO_BUILD_PARALLEL_LEVEL; - std::string target; + std::vector<std::string> targets; std::string config = "Debug"; std::string dir; std::vector<std::string> nativeOptions; - bool clean = false; + bool cleanFirst = false; + bool foundClean = false; + bool foundNonClean = false; bool verbose = cmSystemTools::HasEnv("VERBOSE"); - bool hasTarget = false; enum Doing { @@ -421,25 +421,20 @@ static int do_build(int ac, char const* const* av) if (jobs < 0) { dir.clear(); } + doing = DoingNone; } else if (cmHasLiteralPrefix(av[i], "--parallel")) { const char* nextArg = ((i + 1 < ac) ? av[i + 1] : nullptr); jobs = extract_job_number(i, av[i], nextArg, sizeof("--parallel") - 1); if (jobs < 0) { dir.clear(); } + doing = DoingNone; } else if (strcmp(av[i], "--target") == 0) { - if (!hasTarget) { - doing = DoingTarget; - hasTarget = true; - } else { - std::cerr << "'--target' may not be specified more than once.\n\n"; - dir.clear(); - break; - } + doing = DoingTarget; } else if (strcmp(av[i], "--config") == 0) { doing = DoingConfig; } else if (strcmp(av[i], "--clean-first") == 0) { - clean = true; + cleanFirst = true; doing = DoingNone; } else if ((strcmp(av[i], "--verbose") == 0) || (strcmp(av[i], "-v") == 0)) { @@ -456,8 +451,23 @@ static int do_build(int ac, char const* const* av) doing = DoingNone; break; case DoingTarget: - target = av[i]; - doing = DoingNone; + if (strlen(av[i]) == 0) { + std::cerr << "Warning: Argument number " << i + << " after --target option is empty." << std::endl; + } else { + targets.emplace_back(av[i]); + if (strcmp(av[i], "clean") == 0) { + foundClean = true; + } else { + foundNonClean = true; + } + } + if (foundClean && foundNonClean) { + std::cerr << "Error: Building 'clean' and other targets together " + "is not supported." + << std::endl; + dir.clear(); + } break; case DoingConfig: config = av[i]; @@ -508,7 +518,8 @@ static int do_build(int ac, char const* const* av) cm.SetProgressCallback([&cm](const std::string& msg, float prog) { cmakemainProgressCallback(msg, prog, &cm); }); - return cm.Build(jobs, dir, target, config, nativeOptions, clean, verbose); + return cm.Build(jobs, dir, targets, config, nativeOptions, cleanFirst, + verbose); #endif } diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx index 1a10666..19d0d38 100644 --- a/Source/cmcldeps.cxx +++ b/Source/cmcldeps.cxx @@ -276,7 +276,7 @@ int main() std::string clrest = rest; // rc: /fo x.dir\x.rc.res -> cl: /out:x.dir\x.rc.res.dep.obj - clrest = replace(clrest, "/fo", "/out:"); + clrest = replace(clrest, "/fo ", "/out:"); clrest = replace(clrest, objfile, objfile + ".dep.obj "); cl = "\"" + cl + "\" /P /DRC_INVOKED /TC "; diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 6e1a27c..cefac7a 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1831,7 +1831,8 @@ int cmVSLink::LinkIncremental() // Compile the resource file. std::vector<std::string> rcCommand; rcCommand.push_back(this->RcPath.empty() ? "rc" : this->RcPath); - rcCommand.push_back("/fo" + this->ManifestFileRes); + rcCommand.emplace_back("/fo"); + rcCommand.push_back(this->ManifestFileRes); rcCommand.push_back(this->ManifestFileRC); if (!RunCommand("RC Pass 1", rcCommand, this->Verbose, FORMAT_DECIMAL)) { return -1; diff --git a/Tests/FindPython/NumPy/arraytest.c b/Tests/FindPython/NumPy/arraytest.c index 135877d..db259e5 100644 --- a/Tests/FindPython/NumPy/arraytest.c +++ b/Tests/FindPython/NumPy/arraytest.c @@ -1,7 +1,7 @@ #include "Python.h" #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION -#include "arrayobject.h" +#include "numpy/arrayobject.h" #include <math.h> diff --git a/Tests/FortranOnly/CMakeLists.txt b/Tests/FortranOnly/CMakeLists.txt index 77f6041..45372dd 100644 --- a/Tests/FortranOnly/CMakeLists.txt +++ b/Tests/FortranOnly/CMakeLists.txt @@ -12,6 +12,12 @@ add_executable(FortranOnly1 testf.f) set_property(TARGET FortranOnly1 PROPERTY OUTPUT_NAME FortranOnly) target_link_libraries(FortranOnly1 FortranOnlylib) +# Test that Fortran+RC work together. +# FIXME: Add .rc in more cases. +if(CMAKE_GENERATOR MATCHES "Visual Studio") + set(test_rc testRC.rc) +endif() + # create a custom command that runs FortranOnly1 and puts # the output into the file testfhello.txt add_custom_command(OUTPUT ${FortranOnly_BINARY_DIR}/testfhello.txt @@ -20,7 +26,7 @@ add_custom_command(OUTPUT ${FortranOnly_BINARY_DIR}/testfhello.txt # create a second executable FortranOnly2 that has # testfhello.txt has an source file so that it will # run the above custom command. -add_executable(FortranOnly2 testfhello.txt testf.f) +add_executable(FortranOnly2 testfhello.txt testf.f ${test_rc}) target_link_libraries(FortranOnly2 FortranOnlylib) # create a custom target to check the content of testfhello.txt # by running the cmake script checktestf2.cmake diff --git a/Tests/FortranOnly/testRC.rc b/Tests/FortranOnly/testRC.rc new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/FortranOnly/testRC.rc diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-jobs-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-jobs-stderr.txt new file mode 100644 index 0000000..3c2c808 --- /dev/null +++ b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-jobs-stderr.txt @@ -0,0 +1 @@ +(^$|^Warning: .* does not support parallel builds\. Ignoring parallel build command line option\.) diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-stderr.txt deleted file mode 100644 index f2cbaa6..0000000 --- a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-stderr.txt +++ /dev/null @@ -1,3 +0,0 @@ -^'--target' may not be specified more than once\. -+ -Usage: cmake --build <dir> \[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-result.txt b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-result.txt +++ b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-result.txt diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-stderr.txt new file mode 100644 index 0000000..40d9bec --- /dev/null +++ b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-first-stderr.txt @@ -0,0 +1,2 @@ +^Error: Building 'clean' and other targets together is not supported\. +Usage: cmake --build <dir> \[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-result.txt b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-stderr.txt b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-stderr.txt new file mode 100644 index 0000000..40d9bec --- /dev/null +++ b/Tests/RunCMake/CommandLine/BuildDir--build-multiple-targets-with-clean-second-stderr.txt @@ -0,0 +1,2 @@ +^Error: Building 'clean' and other targets together is not supported\. +Usage: cmake --build <dir> \[options\] \[-- \[native-options\]\] diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 23fb9ef..ff2a8a5 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -107,6 +107,12 @@ function(run_BuildDir) ${CMAKE_COMMAND} --build BuildDir-build --target CustomTarget) run_cmake_command(BuildDir--build-multiple-targets ${CMAKE_COMMAND} -E chdir .. ${CMAKE_COMMAND} --build BuildDir-build --target CustomTarget2 --target CustomTarget3) + run_cmake_command(BuildDir--build-multiple-targets-jobs ${CMAKE_COMMAND} -E chdir .. + ${CMAKE_COMMAND} --build BuildDir-build --target CustomTarget CustomTarget2 -j2 --target CustomTarget3) + run_cmake_command(BuildDir--build-multiple-targets-with-clean-first ${CMAKE_COMMAND} -E chdir .. + ${CMAKE_COMMAND} --build BuildDir-build --target clean CustomTarget) + run_cmake_command(BuildDir--build-multiple-targets-with-clean-second ${CMAKE_COMMAND} -E chdir .. + ${CMAKE_COMMAND} --build BuildDir-build --target CustomTarget clean) run_cmake_command(BuildDir--build-jobs-bad-number ${CMAKE_COMMAND} -E chdir .. ${CMAKE_COMMAND} --build BuildDir-build -j 12ab) run_cmake_command(BuildDir--build-jobs-good-number ${CMAKE_COMMAND} -E chdir .. diff --git a/Tests/RunCMake/XcodeProject/XcodeIOSInstallCombined.cmake b/Tests/RunCMake/XcodeProject/XcodeIOSInstallCombined.cmake index 7f31d94..f6c00b1 100644 --- a/Tests/RunCMake/XcodeProject/XcodeIOSInstallCombined.cmake +++ b/Tests/RunCMake/XcodeProject/XcodeIOSInstallCombined.cmake @@ -6,6 +6,10 @@ if(XCODE_VERSION VERSION_GREATER_EQUAL 9) set(CMAKE_OSX_DEPLOYMENT_TARGET 10) endif() +if(NOT IOS) + message(FATAL_ERROR "IOS variable is not set") +endif() + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf") set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE "NO") diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index 28e8ec4..c637db1 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -66,6 +66,7 @@ run_cmake(CMP0062-WARN) run_cmake(CMP0087-OLD) run_cmake(CMP0087-NEW) run_cmake(CMP0087-WARN) +run_cmake(TARGETS-ImportedGlobal) run_cmake(TARGETS-NAMELINK_COMPONENT-bad-all) run_cmake(TARGETS-NAMELINK_COMPONENT-bad-exc) run_cmake(FILES-DESTINATION-TYPE) diff --git a/Tests/RunCMake/install/TARGETS-ImportedGlobal-result.txt b/Tests/RunCMake/install/TARGETS-ImportedGlobal-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-ImportedGlobal-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/TARGETS-ImportedGlobal-stderr.txt b/Tests/RunCMake/install/TARGETS-ImportedGlobal-stderr.txt new file mode 100644 index 0000000..d67802b --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-ImportedGlobal-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at TARGETS-ImportedGlobal.cmake:[0-9]+ \(install\): + install TARGETS given target "imported_global" which does not exist. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/install/TARGETS-ImportedGlobal.cmake b/Tests/RunCMake/install/TARGETS-ImportedGlobal.cmake new file mode 100644 index 0000000..08c20bd --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-ImportedGlobal.cmake @@ -0,0 +1,3 @@ +add_library(imported_global STATIC IMPORTED GLOBAL) +set_property(TARGET imported_global PROPERTY IMPORTED_LOCATION /does_not_exist) +install(TARGETS imported_global DESTINATION bin) diff --git a/Utilities/Release/win32_release.cmake b/Utilities/Release/win32_release.cmake index c03c665..1e4421c 100644 --- a/Utilities/Release/win32_release.cmake +++ b/Utilities/Release/win32_release.cmake @@ -8,12 +8,16 @@ set(CPACK_BINARY_GENERATORS "WIX ZIP") set(CPACK_SOURCE_GENERATORS "ZIP") set(MAKE_PROGRAM "ninja") set(MAKE "${MAKE_PROGRAM} -j16") -set(qt_prefix "c:/Qt/5.6.3/msvc2017-32-xp-mt") +set(qt_prefix "c:/Qt/5.12.1/msvc2017-32-w7-mt") set(qt_win_libs ${qt_prefix}/plugins/platforms/qwindows.lib - ${qt_prefix}/lib/Qt5PlatformSupport.lib + ${qt_prefix}/lib/Qt5EventDispatcherSupport.lib + ${qt_prefix}/lib/Qt5FontDatabaseSupport.lib + ${qt_prefix}/lib/Qt5ThemeSupport.lib ${qt_prefix}/lib/qtfreetype.lib + ${qt_prefix}/lib/qtlibpng.lib imm32.lib + wtsapi32.lib ) set(INITIAL_CACHE "CMAKE_BUILD_TYPE:STRING=Release CMAKE_DOC_DIR:STRING=doc/cmake @@ -31,7 +35,7 @@ CMAKE_PREFIX_PATH:STRING=${qt_prefix} CMake_TEST_Qt4:BOOL=OFF CMake_TEST_Qt5:BOOL=OFF ") -set(ppflags "-D_WIN32_WINNT=0x601 -DNTDDI_VERSION=0x06010000 -D_USING_V110_SDK71_") +set(ppflags "-D_WIN32_WINNT=0x601 -DNTDDI_VERSION=0x06010000") set(CFLAGS "${ppflags}") set(CXXFLAGS "${ppflags}") set(ENV ". ~/rel/env32") diff --git a/Utilities/Release/win64_release.cmake b/Utilities/Release/win64_release.cmake index 8417206..98eaf19 100644 --- a/Utilities/Release/win64_release.cmake +++ b/Utilities/Release/win64_release.cmake @@ -8,12 +8,16 @@ set(CPACK_BINARY_GENERATORS "WIX ZIP") set(CPACK_SOURCE_GENERATORS "") set(MAKE_PROGRAM "ninja") set(MAKE "${MAKE_PROGRAM} -j16") -set(qt_prefix "c:/Qt/5.6.3/msvc2017-64-xp-mt") +set(qt_prefix "c:/Qt/5.12.1/msvc2017-64-w7-mt") set(qt_win_libs ${qt_prefix}/plugins/platforms/qwindows.lib - ${qt_prefix}/lib/Qt5PlatformSupport.lib + ${qt_prefix}/lib/Qt5EventDispatcherSupport.lib + ${qt_prefix}/lib/Qt5FontDatabaseSupport.lib + ${qt_prefix}/lib/Qt5ThemeSupport.lib ${qt_prefix}/lib/qtfreetype.lib + ${qt_prefix}/lib/qtlibpng.lib imm32.lib + wtsapi32.lib ) set(INITIAL_CACHE "CMAKE_BUILD_TYPE:STRING=Release CMAKE_DOC_DIR:STRING=doc/cmake @@ -31,7 +35,7 @@ CMAKE_PREFIX_PATH:STRING=${qt_prefix} CMake_TEST_Qt4:BOOL=OFF CMake_TEST_Qt5:BOOL=OFF ") -set(ppflags "-D_WIN32_WINNT=0x601 -DNTDDI_VERSION=0x06010000 -D_USING_V110_SDK71_") +set(ppflags "-D_WIN32_WINNT=0x601 -DNTDDI_VERSION=0x06010000") set(CFLAGS "${ppflags}") set(CXXFLAGS "${ppflags}") set(ENV ". ~/rel/env64") |