diff options
41 files changed, 617 insertions, 452 deletions
diff --git a/Help/release/dev/fetchcontent-reduce-boilerplate.rst b/Help/release/dev/fetchcontent-reduce-boilerplate.rst new file mode 100644 index 0000000..6157668 --- /dev/null +++ b/Help/release/dev/fetchcontent-reduce-boilerplate.rst @@ -0,0 +1,8 @@ +fetchcontent-reduce-boilerplate +------------------------------- + +* The FetchContent module gained a new :command:`FetchContent_MakeAvailable` + command. This new command accepts a list of dependency names, which it then + iterates over, populating and adding each one to the main build using the + canonical pattern. This significantly reduces the amount of boilerplate + needed in the project. diff --git a/Help/variable/CMAKE_LANG_COMPILER_ID.rst b/Help/variable/CMAKE_LANG_COMPILER_ID.rst index 033e81c..5323880 100644 --- a/Help/variable/CMAKE_LANG_COMPILER_ID.rst +++ b/Help/variable/CMAKE_LANG_COMPILER_ID.rst @@ -17,6 +17,7 @@ include: Clang = LLVM Clang (clang.llvm.org) Cray = Cray Compiler (cray.com) Embarcadero, Borland = Embarcadero (embarcadero.com) + Flang = Flang LLVM Fortran Compiler G95 = G95 Fortran (g95.org) GNU = GNU Compiler Collection (gcc.gnu.org) GHS = Green Hills Software (www.ghs.com) @@ -28,7 +29,6 @@ include: NVIDIA = NVIDIA CUDA Compiler (nvidia.com) OpenWatcom = Open Watcom (openwatcom.org) PGI = The Portland Group (pgroup.com) - Flang = Flang Fortran Compiler PathScale = PathScale (pathscale.com) SDCC = Small Device C Compiler (sdcc.sourceforge.net) SunPro = Oracle Solaris Studio (oracle.com) diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index c65ae9e..5716b01 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -20,9 +20,12 @@ configure step to use the content in commands like :command:`add_subdirectory`, :command:`include` or :command:`file` operations. Content population details would normally be defined separately from the -command that performs the actual population. Projects should also -check whether the content has already been populated somewhere else in the -project hierarchy. Typical usage would look something like this: +command that performs the actual population. This separation ensures that +all of the dependency details are defined before anything may try to use those +details to populate content. This is particularly important in more complex +project hierarchies where dependencies may be shared between multiple projects. + +The following shows a typical example of declaring content details: .. code-block:: cmake @@ -32,21 +35,37 @@ project hierarchy. Typical usage would look something like this: GIT_TAG release-1.8.0 ) +For most typical cases, populating the content can then be done with a single +command like so: + +.. code-block:: cmake + + FetchContent_MakeAvailable(googletest) + +The above command not only populates the content, it also adds it to the main +build (if possible) so that the main build can use the populated project's +targets, etc. In some cases, the main project may need to have more precise +control over the population or may be required to explicitly define the +population steps (e.g. if CMake versions earlier than 3.14 need to be +supported). The typical pattern of such custom steps looks like this: + +.. code-block:: cmake + FetchContent_GetProperties(googletest) if(NOT googletest_POPULATED) FetchContent_Populate(googletest) add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR}) endif() -When using the above pattern with a hierarchical project arrangement, -projects at higher levels in the hierarchy are able to define or override -the population details of content specified anywhere lower in the project -hierarchy. The ability to detect whether content has already been -populated ensures that even if multiple child projects want certain content -to be available, the first one to populate it wins. The other child project -can simply make use of the already available content instead of repeating -the population for itself. See the -:ref:`Examples <fetch-content-examples>` section which demonstrates +Regardless of which population method is used, when using the +declare-populate pattern with a hierarchical project arrangement, projects at +higher levels in the hierarchy are able to override the population details of +content specified anywhere lower in the project hierarchy. The ability to +detect whether content has already been populated ensures that even if +multiple child projects want certain content to be available, the first one +to populate it wins. The other child project can simply make use of the +already available content instead of repeating the population for itself. +See the :ref:`Examples <fetch-content-examples>` section which demonstrates this scenario. The ``FetchContent`` module also supports defining and populating @@ -113,6 +132,38 @@ Declaring Content Details Populating The Content ^^^^^^^^^^^^^^^^^^^^^^ +For most common scenarios, population means making content available to the +main build according to previously declared details for that dependency. +There are two main patterns for populating content, one based on calling +:command:`FetchContent_GetProperties` and +:command:`FetchContent_Populate` for more precise control and the other on +calling :command:`FetchContent_MakeAvailable` for a simpler, more automated +approach. The former generally follows this canonical pattern: + +.. _`fetch-content-canonical-pattern`: + +.. code-block:: cmake + + # Check if population has already been performed + FetchContent_GetProperties(<name>) + string(TOLOWER "<name>" lcName) + if(NOT ${lcName}_POPULATED) + # Fetch the content using previously declared details + FetchContent_Populate(<name>) + + # Set custom variables, policies, etc. + # ... + + # Bring the populated content into the build + add_subdirectory(${${lcName}_SOURCE_DIR} ${${lcName}_BINARY_DIR}) + endif() + +The above is such a common pattern that, where no custom steps are needed +between the calls to :command:`FetchContent_Populate` and +:command:`add_subdirectory`, equivalent logic can be obtained by calling +:command:`FetchContent_MakeAvailable` instead (and should be preferred where +it meets the needs of the project). + .. command:: FetchContent_Populate .. code-block:: cmake @@ -309,9 +360,6 @@ Populating The Content on the command line invoking the script. -Retrieve Population Properties -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - .. command:: FetchContent_GetProperties When using saved content details, a call to :command:`FetchContent_Populate` @@ -343,28 +391,65 @@ Retrieve Population Properties FetchContent_GetProperties(foobar) if(NOT foobar_POPULATED) FetchContent_Populate(foobar) - - # Set any custom variables, etc. here, then - # populate the content as part of this build - - add_subdirectory(${foobar_SOURCE_DIR} ${foobar_BINARY_DIR}) + ... endif() The above pattern allows other parts of the overall project hierarchy to re-use the same content and ensure that it is only populated once. +.. command:: FetchContent_MakeAvailable + + .. code-block:: cmake + + FetchContent_MakeAvailable( <name1> [<name2>...] ) + + This command implements the common pattern typically needed for most + dependencies. It iterates over each of the named dependencies in turn + and for each one it loosely follows the same + :ref:`canonical pattern <fetch-content-canonical-pattern>` as + presented at the beginning of this section. One small difference to + that pattern is that it will only call :command:`add_subdirectory` on the + populated content if there is a ``CMakeLists.txt`` file in its top level + source directory. This allows the command to be used for dependencies + that make downloaded content available at a known location but which do + not need or support being added directly to the build. + + .. _`fetch-content-examples`: Examples ^^^^^^^^ -Consider a project hierarchy where ``projA`` is the top level project and it -depends on projects ``projB`` and ``projC``. Both ``projB`` and ``projC`` -can be built standalone and they also both depend on another project -``projD``. For simplicity, this example will assume that all four projects -are available on a company git server. The ``CMakeLists.txt`` of each project -might have sections like the following: +This first fairly straightforward example ensures that some popular testing +frameworks are available to the main build: + +.. code-block:: cmake + + include(FetchContent) + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.8.0 + ) + FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v2.5.0 + ) + + # After the following call, the CMake targets defined by googletest and + # Catch2 will be defined and available to the rest of the build + FetchContent_MakeAvailable(googletest Catch2) + + +In more complex project hierarchies, the dependency relationships can be more +complicated. Consider a hierarchy where ``projA`` is the top level project and +it depends directly on projects ``projB`` and ``projC``. Both ``projB`` and +``projC`` can be built standalone and they also both depend on another project +``projD``. ``projB`` additionally depends on ``projE``. This example assumes +that all five projects are available on a company git server. The +``CMakeLists.txt`` of each project might have sections like the following: *projA*: @@ -373,31 +458,27 @@ might have sections like the following: include(FetchContent) FetchContent_Declare( projB - GIT_REPOSITORY git@mycompany.com/git/projB.git + GIT_REPOSITORY git@mycompany.com:git/projB.git GIT_TAG 4a89dc7e24ff212a7b5167bef7ab079d ) FetchContent_Declare( projC - GIT_REPOSITORY git@mycompany.com/git/projC.git + GIT_REPOSITORY git@mycompany.com:git/projC.git GIT_TAG 4ad4016bd1d8d5412d135cf8ceea1bb9 ) FetchContent_Declare( projD - GIT_REPOSITORY git@mycompany.com/git/projD.git + GIT_REPOSITORY git@mycompany.com:git/projD.git GIT_TAG origin/integrationBranch ) + FetchContent_Declare( + projE + GIT_REPOSITORY git@mycompany.com:git/projE.git + GIT_TAG origin/release/2.3-rc1 + ) - FetchContent_GetProperties(projB) - if(NOT projb_POPULATED) - FetchContent_Populate(projB) - add_subdirectory(${projb_SOURCE_DIR} ${projb_BINARY_DIR}) - endif() - - FetchContent_GetProperties(projC) - if(NOT projc_POPULATED) - FetchContent_Populate(projC) - add_subdirectory(${projc_SOURCE_DIR} ${projc_BINARY_DIR}) - endif() + # Order is important, see notes in the discussion further below + FetchContent_MakeAvailable(projD projB projC) *projB*: @@ -406,16 +487,16 @@ might have sections like the following: include(FetchContent) FetchContent_Declare( projD - GIT_REPOSITORY git@mycompany.com/git/projD.git + GIT_REPOSITORY git@mycompany.com:git/projD.git GIT_TAG 20b415f9034bbd2a2e8216e9a5c9e632 ) + FetchContent_Declare( + projE + GIT_REPOSITORY git@mycompany.com:git/projE.git + GIT_TAG 68e20f674a48be38d60e129f600faf7d + ) - FetchContent_GetProperties(projD) - if(NOT projd_POPULATED) - FetchContent_Populate(projD) - add_subdirectory(${projd_SOURCE_DIR} ${projd_BINARY_DIR}) - endif() - + FetchContent_MakeAvailable(projD projE) *projC*: @@ -424,48 +505,77 @@ might have sections like the following: include(FetchContent) FetchContent_Declare( projD - GIT_REPOSITORY git@mycompany.com/git/projD.git + GIT_REPOSITORY git@mycompany.com:git/projD.git GIT_TAG 7d9a17ad2c962aa13e2fbb8043fb6b8a ) + # This particular version of projD requires workarounds FetchContent_GetProperties(projD) if(NOT projd_POPULATED) FetchContent_Populate(projD) + + # Copy an additional/replacement file into the populated source + file(COPY someFile.c DESTINATION ${projd_SOURCE_DIR}/src) + add_subdirectory(${projd_SOURCE_DIR} ${projd_BINARY_DIR}) endif() A few key points should be noted in the above: - ``projB`` and ``projC`` define different content details for ``projD``, - but ``projA`` also defines a set of content details for ``projD`` and - because ``projA`` will define them first, the details from ``projB`` and + but ``projA`` also defines a set of content details for ``projD``. + Because ``projA`` will define them first, the details from ``projB`` and ``projC`` will not be used. The override details defined by ``projA`` are not required to match either of those from ``projB`` or ``projC``, but it is up to the higher level project to ensure that the details it does define still make sense for the child projects. -- While ``projA`` defined content details for ``projD``, it did not need - to explicitly call ``FetchContent_Populate(projD)`` itself. Instead, it - leaves that to a child project to do (in this case it will be ``projB`` - since it is added to the build ahead of ``projC``). If ``projA`` needed to - customize how the ``projD`` content was brought into the build as well - (e.g. define some CMake variables before calling - :command:`add_subdirectory` after populating), it would do the call to - ``FetchContent_Populate()``, etc. just as it did for the ``projB`` and - ``projC`` content. For higher level projects, it is usually enough to - just define the override content details and leave the actual population - to the child projects. This saves repeating the same thing at each level - of the project hierarchy unnecessarily. -- Even though ``projA`` is the top level project in this example, it still - checks whether ``projB`` and ``projC`` have already been populated before - going ahead to do those populations. This makes ``projA`` able to be more - easily incorporated as a child of some other higher level project in the - future if required. Always protect a call to - :command:`FetchContent_Populate` with a check to - :command:`FetchContent_GetProperties`, even in what may be considered a top - level project at the time. - - -The following example demonstrates how one might download and unpack a +- In the ``projA`` call to :command:`FetchContent_MakeAvailable`, ``projD`` + is listed ahead of ``projB`` and ``projC`` to ensure that ``projA`` is in + control of how ``projD`` is populated. +- While ``projA`` defines content details for ``projE``, it does not need + to explicitly call ``FetchContent_MakeAvailable(projE)`` or + ``FetchContent_Populate(projD)`` itself. Instead, it leaves that to the + child ``projB``. For higher level projects, it is often enough to just + define the override content details and leave the actual population to the + child projects. This saves repeating the same thing at each level of the + project hierarchy unnecessarily. + + +Projects don't always need to add the populated content to the build. +Sometimes the project just wants to make the downloaded content available at +a predictable location. The next example ensures that a set of standard +company toolchain files (and potentially even the toolchain binaries +themselves) is available early enough to be used for that same build. + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.14) + + include(FetchContent) + FetchContent_Declare( + mycom_toolchains + URL https://intranet.mycompany.com//toolchains_1.3.2.tar.gz + ) + FetchContent_MakeAvailable(mycom_toolchains) + + project(CrossCompileExample) + +The project could be configured to use one of the downloaded toolchains like +so: + +.. code-block:: shell + + cmake -DCMAKE_TOOLCHAIN_FILE=_deps/mycom_toolchains-src/toolchain_arm.cmake /path/to/src + +When CMake processes the ``CMakeLists.txt`` file, it will download and unpack +the tarball into ``_deps/mycompany_toolchains-src`` relative to the build +directory. The :variable:`CMAKE_TOOLCHAIN_FILE` variable is not used until +the :command:`project` command is reached, at which point CMake looks for the +named toolchain file relative to the build directory. Because the tarball has +already been downloaded and unpacked by then, the toolchain file will be in +place, even the very first time that ``cmake`` is run in the build directory. + +Lastly, the following example demonstrates how one might download and unpack a firmware tarball using CMake's :manual:`script mode <cmake(1)>`. The call to :command:`FetchContent_Populate` specifies all the content details and the unpacked firmware will be placed in a ``firmware`` directory below the @@ -921,3 +1031,31 @@ function(FetchContent_Populate contentName) set(${contentNameLower}_POPULATED True PARENT_SCOPE) endfunction() + +# Arguments are assumed to be the names of dependencies that have been +# declared previously and should be populated. It is not an error if +# any of them have already been populated (they will just be skipped in +# that case). The command is implemented as a macro so that the variables +# defined by the FetchContent_GetProperties() and FetchContent_Populate() +# calls will be available to the caller. +macro(FetchContent_MakeAvailable) + + foreach(contentName IN ITEMS ${ARGV}) + string(TOLOWER ${contentName} contentNameLower) + FetchContent_GetProperties(${contentName}) + if(NOT ${contentNameLower}_POPULATED) + FetchContent_Populate(${contentName}) + + # Only try to call add_subdirectory() if the populated content + # can be treated that way. Protecting the call with the check + # allows this function to be used for projects that just want + # to ensure the content exists, such as to provide content at + # a known location. + if(EXISTS ${${contentNameLower}_SOURCE_DIR}/CMakeLists.txt) + add_subdirectory(${${contentNameLower}_SOURCE_DIR} + ${${contentNameLower}_BINARY_DIR}) + endif() + endif() + endforeach() + +endmacro() diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake index 2bcd28e..5600b4c 100644 --- a/Modules/UseJava.cmake +++ b/Modules/UseJava.cmake @@ -446,7 +446,7 @@ function (__java_copy_file src dest comment) endfunction () function(__java_lcat VAR) - foreach(_line ${ARGN}) + foreach(_line IN LISTS ARGN) string(APPEND ${VAR} "${_line}\n") endforeach() @@ -568,7 +568,7 @@ function(add_jar _TARGET_NAME) set(CMAKE_JAVA_INCLUDE_FLAG_SEP ":") endif() - foreach (JAVA_INCLUDE_DIR ${CMAKE_JAVA_INCLUDE_PATH}) + foreach (JAVA_INCLUDE_DIR IN LISTS CMAKE_JAVA_INCLUDE_PATH) string(APPEND CMAKE_JAVA_INCLUDE_PATH_FINAL "${CMAKE_JAVA_INCLUDE_FLAG_SEP}${JAVA_INCLUDE_DIR}") endforeach() @@ -592,7 +592,7 @@ function(add_jar _TARGET_NAME) set(_JAVA_COMPILE_DEPENDS) set(_JAVA_RESOURCE_FILES) set(_JAVA_RESOURCE_FILES_RELATIVE) - foreach(_JAVA_SOURCE_FILE ${_JAVA_SOURCE_FILES}) + foreach(_JAVA_SOURCE_FILE IN LISTS _JAVA_SOURCE_FILES) get_filename_component(_JAVA_EXT ${_JAVA_SOURCE_FILE} EXT) get_filename_component(_JAVA_FILE ${_JAVA_SOURCE_FILE} NAME_WE) get_filename_component(_JAVA_PATH ${_JAVA_SOURCE_FILE} PATH) @@ -607,7 +607,7 @@ function(add_jar _TARGET_NAME) file(RELATIVE_PATH _JAVA_REL_SOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${_JAVA_FULL}) string(LENGTH ${_JAVA_REL_BINARY_PATH} _BIN_LEN) string(LENGTH ${_JAVA_REL_SOURCE_PATH} _SRC_LEN) - if (${_BIN_LEN} LESS ${_SRC_LEN}) + if (_BIN_LEN LESS _SRC_LEN) set(_JAVA_REL_PATH ${_JAVA_REL_BINARY_PATH}) else () set(_JAVA_REL_PATH ${_JAVA_REL_SOURCE_PATH}) @@ -637,7 +637,7 @@ function(add_jar _TARGET_NAME) endif () endforeach() - foreach(_JAVA_INCLUDE_JAR ${_add_jar_INCLUDE_JARS}) + foreach(_JAVA_INCLUDE_JAR IN LISTS _add_jar_INCLUDE_JARS) if (TARGET ${_JAVA_INCLUDE_JAR}) get_target_property(_JAVA_JAR_PATH ${_JAVA_INCLUDE_JAR} JAR_FILE) if (_JAVA_JAR_PATH) @@ -705,7 +705,7 @@ function(add_jar _TARGET_NAME) # create the jar file set(_JAVA_JAR_OUTPUT_PATH - ${_add_jar_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_NAME}) + "${_add_jar_OUTPUT_DIR}/${_JAVA_TARGET_OUTPUT_NAME}") if (CMAKE_JNI_TARGET) add_custom_command( OUTPUT ${_JAVA_JAR_OUTPUT_PATH} @@ -903,15 +903,15 @@ function (find_jar VARIABLE) set(_state "name") - foreach (arg ${ARGN}) - if (${_state} STREQUAL "name") - if (${arg} STREQUAL "VERSIONS") + foreach (arg IN LISTS ARGN) + if (_state STREQUAL "name") + if (arg STREQUAL "VERSIONS") set(_state "versions") - elseif (${arg} STREQUAL "NAMES") + elseif (arg STREQUAL "NAMES") set(_state "names") - elseif (${arg} STREQUAL "PATHS") + elseif (arg STREQUAL "PATHS") set(_state "paths") - elseif (${arg} STREQUAL "DOC") + elseif (arg STREQUAL "DOC") set(_state "doc") else () set(_jar_names ${arg}) @@ -919,22 +919,22 @@ function (find_jar VARIABLE) set(_jar_doc "Finding ${arg} jar") endif () endif () - elseif (${_state} STREQUAL "versions") - if (${arg} STREQUAL "NAMES") + elseif (_state STREQUAL "versions") + if (arg STREQUAL "NAMES") set(_state "names") - elseif (${arg} STREQUAL "PATHS") + elseif (arg STREQUAL "PATHS") set(_state "paths") - elseif (${arg} STREQUAL "DOC") + elseif (arg STREQUAL "DOC") set(_state "doc") else () set(_jar_versions ${_jar_versions} ${arg}) endif () - elseif (${_state} STREQUAL "names") - if (${arg} STREQUAL "VERSIONS") + elseif (_state STREQUAL "names") + if (arg STREQUAL "VERSIONS") set(_state "versions") - elseif (${arg} STREQUAL "PATHS") + elseif (arg STREQUAL "PATHS") set(_state "paths") - elseif (${arg} STREQUAL "DOC") + elseif (arg STREQUAL "DOC") set(_state "doc") else () set(_jar_names ${_jar_names} ${arg}) @@ -942,22 +942,22 @@ function (find_jar VARIABLE) set(_jar_doc "Finding ${arg} jar") endif () endif () - elseif (${_state} STREQUAL "paths") - if (${arg} STREQUAL "VERSIONS") + elseif (_state STREQUAL "paths") + if (arg STREQUAL "VERSIONS") set(_state "versions") - elseif (${arg} STREQUAL "NAMES") + elseif (arg STREQUAL "NAMES") set(_state "names") - elseif (${arg} STREQUAL "DOC") + elseif (arg STREQUAL "DOC") set(_state "doc") else () set(_jar_paths ${_jar_paths} ${arg}) endif () - elseif (${_state} STREQUAL "doc") - if (${arg} STREQUAL "VERSIONS") + elseif (_state STREQUAL "doc") + if (arg STREQUAL "VERSIONS") set(_state "versions") - elseif (${arg} STREQUAL "NAMES") + elseif (arg STREQUAL "NAMES") set(_state "names") - elseif (${arg} STREQUAL "PATHS") + elseif (arg STREQUAL "PATHS") set(_state "paths") else () set(_jar_doc ${arg}) @@ -969,8 +969,8 @@ function (find_jar VARIABLE) message(FATAL_ERROR "find_jar: No name to search for given") endif () - foreach (jar_name ${_jar_names}) - foreach (version ${_jar_versions}) + foreach (jar_name IN LISTS _jar_names) + foreach (version IN LISTS _jar_versions) set(_jar_files ${_jar_files} ${jar_name}-${version}.jar) endforeach () set(_jar_files ${_jar_files} ${jar_name}.jar) @@ -997,252 +997,252 @@ function(create_javadoc _target) set(_state "package") - foreach (arg ${ARGN}) - if (${_state} STREQUAL "package") - if (${arg} STREQUAL "PACKAGES") + foreach (arg IN LISTS ARGN) + if (_state STREQUAL "package") + if (arg STREQUAL "PACKAGES") set(_state "packages") - elseif (${arg} STREQUAL "FILES") + elseif (arg STREQUAL "FILES") set(_state "files") - elseif (${arg} STREQUAL "SOURCEPATH") + elseif (arg STREQUAL "SOURCEPATH") set(_state "sourcepath") - elseif (${arg} STREQUAL "CLASSPATH") + elseif (arg STREQUAL "CLASSPATH") set(_state "classpath") - elseif (${arg} STREQUAL "INSTALLPATH") + elseif (arg STREQUAL "INSTALLPATH") set(_state "installpath") - elseif (${arg} STREQUAL "DOCTITLE") + elseif (arg STREQUAL "DOCTITLE") set(_state "doctitle") - elseif (${arg} STREQUAL "WINDOWTITLE") + elseif (arg STREQUAL "WINDOWTITLE") set(_state "windowtitle") - elseif (${arg} STREQUAL "AUTHOR") + elseif (arg STREQUAL "AUTHOR") set(_state "author") - elseif (${arg} STREQUAL "USE") + elseif (arg STREQUAL "USE") set(_state "use") - elseif (${arg} STREQUAL "VERSION") + elseif (arg STREQUAL "VERSION") set(_state "version") else () set(_javadoc_packages ${arg}) set(_state "packages") endif () - elseif (${_state} STREQUAL "packages") - if (${arg} STREQUAL "FILES") + elseif (_state STREQUAL "packages") + if (arg STREQUAL "FILES") set(_state "files") - elseif (${arg} STREQUAL "SOURCEPATH") + elseif (arg STREQUAL "SOURCEPATH") set(_state "sourcepath") - elseif (${arg} STREQUAL "CLASSPATH") + elseif (arg STREQUAL "CLASSPATH") set(_state "classpath") - elseif (${arg} STREQUAL "INSTALLPATH") + elseif (arg STREQUAL "INSTALLPATH") set(_state "installpath") - elseif (${arg} STREQUAL "DOCTITLE") + elseif (arg STREQUAL "DOCTITLE") set(_state "doctitle") - elseif (${arg} STREQUAL "WINDOWTITLE") + elseif (arg STREQUAL "WINDOWTITLE") set(_state "windowtitle") - elseif (${arg} STREQUAL "AUTHOR") + elseif (arg STREQUAL "AUTHOR") set(_state "author") - elseif (${arg} STREQUAL "USE") + elseif (arg STREQUAL "USE") set(_state "use") - elseif (${arg} STREQUAL "VERSION") + elseif (arg STREQUAL "VERSION") set(_state "version") else () list(APPEND _javadoc_packages ${arg}) endif () - elseif (${_state} STREQUAL "files") - if (${arg} STREQUAL "PACKAGES") + elseif (_state STREQUAL "files") + if (arg STREQUAL "PACKAGES") set(_state "packages") - elseif (${arg} STREQUAL "SOURCEPATH") + elseif (arg STREQUAL "SOURCEPATH") set(_state "sourcepath") - elseif (${arg} STREQUAL "CLASSPATH") + elseif (arg STREQUAL "CLASSPATH") set(_state "classpath") - elseif (${arg} STREQUAL "INSTALLPATH") + elseif (arg STREQUAL "INSTALLPATH") set(_state "installpath") - elseif (${arg} STREQUAL "DOCTITLE") + elseif (arg STREQUAL "DOCTITLE") set(_state "doctitle") - elseif (${arg} STREQUAL "WINDOWTITLE") + elseif (arg STREQUAL "WINDOWTITLE") set(_state "windowtitle") - elseif (${arg} STREQUAL "AUTHOR") + elseif (arg STREQUAL "AUTHOR") set(_state "author") - elseif (${arg} STREQUAL "USE") + elseif (arg STREQUAL "USE") set(_state "use") - elseif (${arg} STREQUAL "VERSION") + elseif (arg STREQUAL "VERSION") set(_state "version") else () list(APPEND _javadoc_files ${arg}) endif () - elseif (${_state} STREQUAL "sourcepath") - if (${arg} STREQUAL "PACKAGES") + elseif (_state STREQUAL "sourcepath") + if (arg STREQUAL "PACKAGES") set(_state "packages") - elseif (${arg} STREQUAL "FILES") + elseif (arg STREQUAL "FILES") set(_state "files") - elseif (${arg} STREQUAL "CLASSPATH") + elseif (arg STREQUAL "CLASSPATH") set(_state "classpath") - elseif (${arg} STREQUAL "INSTALLPATH") + elseif (arg STREQUAL "INSTALLPATH") set(_state "installpath") - elseif (${arg} STREQUAL "DOCTITLE") + elseif (arg STREQUAL "DOCTITLE") set(_state "doctitle") - elseif (${arg} STREQUAL "WINDOWTITLE") + elseif (arg STREQUAL "WINDOWTITLE") set(_state "windowtitle") - elseif (${arg} STREQUAL "AUTHOR") + elseif (arg STREQUAL "AUTHOR") set(_state "author") - elseif (${arg} STREQUAL "USE") + elseif (arg STREQUAL "USE") set(_state "use") - elseif (${arg} STREQUAL "VERSION") + elseif (arg STREQUAL "VERSION") set(_state "version") else () list(APPEND _javadoc_sourcepath ${arg}) endif () - elseif (${_state} STREQUAL "classpath") - if (${arg} STREQUAL "PACKAGES") + elseif (_state STREQUAL "classpath") + if (arg STREQUAL "PACKAGES") set(_state "packages") - elseif (${arg} STREQUAL "FILES") + elseif (arg STREQUAL "FILES") set(_state "files") - elseif (${arg} STREQUAL "SOURCEPATH") + elseif (arg STREQUAL "SOURCEPATH") set(_state "sourcepath") - elseif (${arg} STREQUAL "INSTALLPATH") + elseif (arg STREQUAL "INSTALLPATH") set(_state "installpath") - elseif (${arg} STREQUAL "DOCTITLE") + elseif (arg STREQUAL "DOCTITLE") set(_state "doctitle") - elseif (${arg} STREQUAL "WINDOWTITLE") + elseif (arg STREQUAL "WINDOWTITLE") set(_state "windowtitle") - elseif (${arg} STREQUAL "AUTHOR") + elseif (arg STREQUAL "AUTHOR") set(_state "author") - elseif (${arg} STREQUAL "USE") + elseif (arg STREQUAL "USE") set(_state "use") - elseif (${arg} STREQUAL "VERSION") + elseif (arg STREQUAL "VERSION") set(_state "version") else () list(APPEND _javadoc_classpath ${arg}) endif () - elseif (${_state} STREQUAL "installpath") - if (${arg} STREQUAL "PACKAGES") + elseif (_state STREQUAL "installpath") + if (arg STREQUAL "PACKAGES") set(_state "packages") - elseif (${arg} STREQUAL "FILES") + elseif (arg STREQUAL "FILES") set(_state "files") - elseif (${arg} STREQUAL "SOURCEPATH") + elseif (arg STREQUAL "SOURCEPATH") set(_state "sourcepath") - elseif (${arg} STREQUAL "DOCTITLE") + elseif (arg STREQUAL "DOCTITLE") set(_state "doctitle") - elseif (${arg} STREQUAL "WINDOWTITLE") + elseif (arg STREQUAL "WINDOWTITLE") set(_state "windowtitle") - elseif (${arg} STREQUAL "AUTHOR") + elseif (arg STREQUAL "AUTHOR") set(_state "author") - elseif (${arg} STREQUAL "USE") + elseif (arg STREQUAL "USE") set(_state "use") - elseif (${arg} STREQUAL "VERSION") + elseif (arg STREQUAL "VERSION") set(_state "version") else () set(_javadoc_installpath ${arg}) endif () - elseif (${_state} STREQUAL "doctitle") + elseif (_state STREQUAL "doctitle") if (${arg} STREQUAL "PACKAGES") set(_state "packages") - elseif (${arg} STREQUAL "FILES") + elseif (arg STREQUAL "FILES") set(_state "files") - elseif (${arg} STREQUAL "SOURCEPATH") + elseif (arg STREQUAL "SOURCEPATH") set(_state "sourcepath") - elseif (${arg} STREQUAL "INSTALLPATH") + elseif (arg STREQUAL "INSTALLPATH") set(_state "installpath") - elseif (${arg} STREQUAL "CLASSPATH") + elseif (arg STREQUAL "CLASSPATH") set(_state "classpath") - elseif (${arg} STREQUAL "WINDOWTITLE") + elseif (arg STREQUAL "WINDOWTITLE") set(_state "windowtitle") - elseif (${arg} STREQUAL "AUTHOR") + elseif (arg STREQUAL "AUTHOR") set(_state "author") - elseif (${arg} STREQUAL "USE") + elseif (arg STREQUAL "USE") set(_state "use") - elseif (${arg} STREQUAL "VERSION") + elseif (arg STREQUAL "VERSION") set(_state "version") else () set(_javadoc_doctitle ${arg}) endif () - elseif (${_state} STREQUAL "windowtitle") + elseif (_state STREQUAL "windowtitle") if (${arg} STREQUAL "PACKAGES") set(_state "packages") - elseif (${arg} STREQUAL "FILES") + elseif (arg STREQUAL "FILES") set(_state "files") - elseif (${arg} STREQUAL "SOURCEPATH") + elseif (arg STREQUAL "SOURCEPATH") set(_state "sourcepath") - elseif (${arg} STREQUAL "CLASSPATH") + elseif (arg STREQUAL "CLASSPATH") set(_state "classpath") - elseif (${arg} STREQUAL "INSTALLPATH") + elseif (arg STREQUAL "INSTALLPATH") set(_state "installpath") - elseif (${arg} STREQUAL "DOCTITLE") + elseif (arg STREQUAL "DOCTITLE") set(_state "doctitle") - elseif (${arg} STREQUAL "AUTHOR") + elseif (arg STREQUAL "AUTHOR") set(_state "author") - elseif (${arg} STREQUAL "USE") + elseif (arg STREQUAL "USE") set(_state "use") - elseif (${arg} STREQUAL "VERSION") + elseif (arg STREQUAL "VERSION") set(_state "version") else () set(_javadoc_windowtitle ${arg}) endif () - elseif (${_state} STREQUAL "author") - if (${arg} STREQUAL "PACKAGES") + elseif (_state STREQUAL "author") + if (arg STREQUAL "PACKAGES") set(_state "packages") - elseif (${arg} STREQUAL "FILES") + elseif (arg STREQUAL "FILES") set(_state "files") - elseif (${arg} STREQUAL "SOURCEPATH") + elseif (arg STREQUAL "SOURCEPATH") set(_state "sourcepath") - elseif (${arg} STREQUAL "CLASSPATH") + elseif (arg STREQUAL "CLASSPATH") set(_state "classpath") - elseif (${arg} STREQUAL "INSTALLPATH") + elseif (arg STREQUAL "INSTALLPATH") set(_state "installpath") - elseif (${arg} STREQUAL "DOCTITLE") + elseif (arg STREQUAL "DOCTITLE") set(_state "doctitle") - elseif (${arg} STREQUAL "WINDOWTITLE") + elseif (arg STREQUAL "WINDOWTITLE") set(_state "windowtitle") - elseif (${arg} STREQUAL "AUTHOR") + elseif (arg STREQUAL "AUTHOR") set(_state "author") - elseif (${arg} STREQUAL "USE") + elseif (arg STREQUAL "USE") set(_state "use") - elseif (${arg} STREQUAL "VERSION") + elseif (arg STREQUAL "VERSION") set(_state "version") else () set(_javadoc_author ${arg}) endif () - elseif (${_state} STREQUAL "use") - if (${arg} STREQUAL "PACKAGES") + elseif (_state STREQUAL "use") + if (arg STREQUAL "PACKAGES") set(_state "packages") - elseif (${arg} STREQUAL "FILES") + elseif (arg STREQUAL "FILES") set(_state "files") - elseif (${arg} STREQUAL "SOURCEPATH") + elseif (arg STREQUAL "SOURCEPATH") set(_state "sourcepath") - elseif (${arg} STREQUAL "CLASSPATH") + elseif (arg STREQUAL "CLASSPATH") set(_state "classpath") - elseif (${arg} STREQUAL "INSTALLPATH") + elseif (arg STREQUAL "INSTALLPATH") set(_state "installpath") - elseif (${arg} STREQUAL "DOCTITLE") + elseif (arg STREQUAL "DOCTITLE") set(_state "doctitle") - elseif (${arg} STREQUAL "WINDOWTITLE") + elseif (arg STREQUAL "WINDOWTITLE") set(_state "windowtitle") - elseif (${arg} STREQUAL "AUTHOR") + elseif (arg STREQUAL "AUTHOR") set(_state "author") - elseif (${arg} STREQUAL "USE") + elseif (arg STREQUAL "USE") set(_state "use") - elseif (${arg} STREQUAL "VERSION") + elseif (arg STREQUAL "VERSION") set(_state "version") else () set(_javadoc_use ${arg}) endif () - elseif (${_state} STREQUAL "version") - if (${arg} STREQUAL "PACKAGES") + elseif (_state STREQUAL "version") + if (arg STREQUAL "PACKAGES") set(_state "packages") - elseif (${arg} STREQUAL "FILES") + elseif (arg STREQUAL "FILES") set(_state "files") - elseif (${arg} STREQUAL "SOURCEPATH") + elseif (arg STREQUAL "SOURCEPATH") set(_state "sourcepath") - elseif (${arg} STREQUAL "CLASSPATH") + elseif (arg STREQUAL "CLASSPATH") set(_state "classpath") - elseif (${arg} STREQUAL "INSTALLPATH") + elseif (arg STREQUAL "INSTALLPATH") set(_state "installpath") - elseif (${arg} STREQUAL "DOCTITLE") + elseif (arg STREQUAL "DOCTITLE") set(_state "doctitle") - elseif (${arg} STREQUAL "WINDOWTITLE") + elseif (arg STREQUAL "WINDOWTITLE") set(_state "windowtitle") - elseif (${arg} STREQUAL "AUTHOR") + elseif (arg STREQUAL "AUTHOR") set(_state "author") - elseif (${arg} STREQUAL "USE") + elseif (arg STREQUAL "USE") set(_state "use") - elseif (${arg} STREQUAL "VERSION") + elseif (arg STREQUAL "VERSION") set(_state "version") else () set(_javadoc_version ${arg}) @@ -1255,7 +1255,7 @@ function(create_javadoc _target) if (_javadoc_sourcepath) set(_start TRUE) - foreach(_path ${_javadoc_sourcepath}) + foreach(_path IN LISTS _javadoc_sourcepath) if (_start) set(_sourcepath ${_path}) set(_start FALSE) @@ -1268,7 +1268,7 @@ function(create_javadoc _target) if (_javadoc_classpath) set(_start TRUE) - foreach(_path ${_javadoc_classpath}) + foreach(_path IN LISTS _javadoc_classpath) if (_start) set(_classpath ${_path}) set(_start FALSE) @@ -1435,7 +1435,7 @@ function(export_jars) # Set content of generated exports file string(REPLACE ";" " " __targets__ "${_export_jars_TARGETS}") set(__targetdefs__ "") - foreach(_target ${_export_jars_TARGETS}) + foreach(_target IN LISTS _export_jars_TARGETS) get_target_property(_jarpath ${_target} JAR_FILE) get_filename_component(_jarpath ${_jarpath} PATH) __java_export_jar(__targetdefs__ ${_target} "${_jarpath}") @@ -1473,7 +1473,7 @@ function(install_jar_exports) endif() # Determine relative path from installed export file to install prefix - if(IS_ABSOLUTE ${_install_jar_exports_DESTINATION}) + if(IS_ABSOLUTE "${_install_jar_exports_DESTINATION}") file(RELATIVE_PATH _relpath ${_install_jar_exports_DESTINATION} ${CMAKE_INSTALL_PREFIX} @@ -1492,7 +1492,7 @@ function(install_jar_exports) # Set content of generated exports file string(REPLACE ";" " " __targets__ "${_install_jar_exports_TARGETS}") set(__targetdefs__ "set(_prefix \${CMAKE_CURRENT_LIST_DIR}/${_relpath})\n\n") - foreach(_target ${_install_jar_exports_TARGETS}) + foreach(_target IN LISTS _install_jar_exports_TARGETS) get_target_property(_dir ${_target} INSTALL_DESTINATION) __java_export_jar(__targetdefs__ ${_target} "\${_prefix}/${_dir}") endforeach() diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 0362d52..9e64efa 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 13) -set(CMake_VERSION_PATCH 20190129) +set(CMake_VERSION_PATCH 20190130) #set(CMake_VERSION_RC 1) diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx index 24d19d9..01e3ea4 100644 --- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx +++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx @@ -286,8 +286,7 @@ protected: content = cmSystemTools::TrimWhitespace(content); std::string source = this->basePath + "/" + content; std::string destination = this->path + "/" + content; - if (!cmSystemTools::CopyFileIfDifferent(source.data(), - destination.data())) { + if (!cmSystemTools::CopyFileIfDifferent(source, destination)) { this->hasErrors = true; } } diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index 80b9ef3..013ad81 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -210,8 +210,7 @@ int cmCPackDragNDropGenerator::PackageFiles() bool cmCPackDragNDropGenerator::CopyFile(std::ostringstream& source, std::ostringstream& target) { - if (!cmSystemTools::CopyFileIfDifferent(source.str().c_str(), - target.str().c_str())) { + if (!cmSystemTools::CopyFileIfDifferent(source.str(), target.str())) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error copying " << source.str() << " to " << target.str() << std::endl); diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 4728f69..57c0545 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -43,12 +43,6 @@ cmCPackGenerator::~cmCPackGenerator() this->MakefileMap = nullptr; } -void cmCPackGeneratorProgress(const char* msg, float prog, void* ptr) -{ - cmCPackGenerator* self = static_cast<cmCPackGenerator*>(ptr); - self->DisplayVerboseOutput(msg, prog); -} - void cmCPackGenerator::DisplayVerboseOutput(const char* msg, float progress) { (void)progress; @@ -392,8 +386,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( std::move(inFileRelative)); } /* If it is not a symlink then do a plain copy */ - else if (!(cmSystemTools::CopyFileIfDifferent(inFile.c_str(), - filePath.c_str()) && + else if (!(cmSystemTools::CopyFileIfDifferent(inFile, filePath) && cmSystemTools::CopyFileTime(inFile.c_str(), filePath.c_str()))) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -696,7 +689,9 @@ int cmCPackGenerator::InstallCMakeProject( cm.SetHomeOutputDirectory(""); cm.GetCurrentSnapshot().SetDefaultDefinitions(); cm.AddCMakePaths(); - cm.SetProgressCallback(cmCPackGeneratorProgress, this); + cm.SetProgressCallback([this](const char* msg, float prog) { + this->DisplayVerboseOutput(msg, prog); + }); cm.SetTrace(this->Trace); cm.SetTraceExpand(this->TraceExpand); cmGlobalGenerator gg(&cm); @@ -1077,8 +1072,7 @@ int cmCPackGenerator::DoPackage() << (tempPackageFileName ? tempPackageFileName : "(NULL)") << " to " << (packageFileName ? packageFileName : "(NULL)") << std::endl); - if (!cmSystemTools::CopyFileIfDifferent(tempPackageFileName, - packageFileName)) { + if (!cmSystemTools::CopyFileIfDifferent(pkgFileName, tmpPF)) { cmCPackLogger( cmCPackLog::LOG_ERROR, "Problem copying the package: " diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index d4c867b..0413422 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -90,12 +90,8 @@ int cpackDefinitionArgument(const char* argument, const char* cValue, return 1; } -static void cpackProgressCallback(const char* message, float progress, - void* clientdata) +static void cpackProgressCallback(const char* message, float /*unused*/) { - (void)progress; - (void)clientdata; - std::cout << "-- " << message << std::endl; } @@ -212,7 +208,7 @@ int main(int argc, char const* const* argv) cmake cminst(cmake::RoleScript, cmState::CPack); cminst.SetHomeDirectory(""); cminst.SetHomeOutputDirectory(""); - cminst.SetProgressCallback(cpackProgressCallback, nullptr); + cminst.SetProgressCallback(cpackProgressCallback); cminst.GetCurrentSnapshot().SetDefaultDefinitions(); cmGlobalGenerator cmgg(&cminst); cmMakefile globalMF(&cmgg, cminst.GetCurrentSnapshot()); diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index 312d126..38aa1b3 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -109,27 +109,6 @@ int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring, return 0; } -void CMakeMessageCallback(const char* m, const char* /*unused*/, - bool& /*unused*/, void* s) -{ - std::string* out = static_cast<std::string*>(s); - *out += m; - *out += "\n"; -} - -void CMakeProgressCallback(const char* msg, float /*unused*/, void* s) -{ - std::string* out = static_cast<std::string*>(s); - *out += msg; - *out += "\n"; -} - -void CMakeOutputCallback(const char* m, size_t len, void* s) -{ - std::string* out = static_cast<std::string*>(s); - out->append(m, len); -} - class cmCTestBuildAndTestCaptureRAII { cmake& CM; @@ -138,17 +117,30 @@ public: cmCTestBuildAndTestCaptureRAII(cmake& cm, std::string& s) : CM(cm) { - cmSystemTools::SetMessageCallback(CMakeMessageCallback, &s); - cmSystemTools::SetStdoutCallback(CMakeOutputCallback, &s); - cmSystemTools::SetStderrCallback(CMakeOutputCallback, &s); - this->CM.SetProgressCallback(CMakeProgressCallback, &s); + cmSystemTools::SetMessageCallback( + [&s](const char* msg, const char* /*unused*/) { + s += msg; + s += "\n"; + }); + + cmSystemTools::SetStdoutCallback( + [&s](const char* m, size_t len) { s.append(m, len); }); + + cmSystemTools::SetStderrCallback( + [&s](const char* m, size_t len) { s.append(m, len); }); + + this->CM.SetProgressCallback([&s](const char* msg, float /*unused*/) { + s += msg; + s += "\n"; + }); } + ~cmCTestBuildAndTestCaptureRAII() { - this->CM.SetProgressCallback(nullptr, nullptr); - cmSystemTools::SetStderrCallback(nullptr, nullptr); - cmSystemTools::SetStdoutCallback(nullptr, nullptr); - cmSystemTools::SetMessageCallback(nullptr, nullptr); + this->CM.SetProgressCallback(nullptr); + cmSystemTools::SetStderrCallback(nullptr); + cmSystemTools::SetStdoutCallback(nullptr); + cmSystemTools::SetMessageCallback(nullptr); } }; diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 84f3652..33b8b4a 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -263,15 +263,6 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg) return retVal; } -static void ctestScriptProgressCallback(const char* m, float /*unused*/, - void* cd) -{ - cmCTest* ctest = static_cast<cmCTest*>(cd); - if (m && *m) { - cmCTestLog(ctest, HANDLER_OUTPUT, "-- " << m << std::endl); - } -} - void cmCTestScriptHandler::CreateCMake() { // create a cmake instance to read the configuration script @@ -297,7 +288,11 @@ void cmCTestScriptHandler::CreateCMake() this->ParentMakefile->GetRecursionDepth()); } - this->CMake->SetProgressCallback(ctestScriptProgressCallback, this->CTest); + this->CMake->SetProgressCallback([this](const char* m, float /*unused*/) { + if (m && *m) { + cmCTestLog(this->CTest, HANDLER_OUTPUT, "-- " << m << std::endl); + } + }); this->AddCTestCommand("ctest_build", new cmCTestBuildCommand); this->AddCTestCommand("ctest_configure", new cmCTestConfigureCommand); diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index dbf4a28..f2982a6 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -65,13 +65,6 @@ void onsig(int /*unused*/) } } -void CMakeMessageHandler(const char* message, const char* title, - bool& /*unused*/, void* clientData) -{ - cmCursesForm* self = static_cast<cmCursesForm*>(clientData); - self->AddError(message, title); -} - int main(int argc, char const* const* argv) { cmsys::Encoding::CommandLineArguments encoding_args = @@ -156,7 +149,10 @@ int main(int argc, char const* const* argv) return 1; } - cmSystemTools::SetMessageCallback(CMakeMessageHandler, myform); + cmSystemTools::SetMessageCallback( + [myform](const char* message, const char* title) { + myform->AddError(message, title); + }); cmCursesForm::CurrentForm = myform; diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx index 188ad69..8ca7802 100644 --- a/Source/CursesDialog/cmCursesMainForm.cxx +++ b/Source/CursesDialog/cmCursesMainForm.cxx @@ -506,12 +506,8 @@ void cmCursesMainForm::UpdateStatusBar(const char* message) pos_form_cursor(this->Form); } -void cmCursesMainForm::UpdateProgress(const char* msg, float prog, void* vp) +void cmCursesMainForm::UpdateProgress(const char* msg, float prog) { - cmCursesMainForm* cm = static_cast<cmCursesMainForm*>(vp); - if (!cm) { - return; - } char tmp[1024]; const char* cmsg = tmp; if (prog >= 0) { @@ -519,8 +515,8 @@ void cmCursesMainForm::UpdateProgress(const char* msg, float prog, void* vp) } else { cmsg = msg; } - cm->UpdateStatusBar(cmsg); - cm->PrintKeys(1); + this->UpdateStatusBar(cmsg); + this->PrintKeys(1); curses_move(1, 1); touchwin(stdscr); refresh(); @@ -536,8 +532,8 @@ int cmCursesMainForm::Configure(int noconfigure) this->PrintKeys(1); touchwin(stdscr); refresh(); - this->CMakeInstance->SetProgressCallback(cmCursesMainForm::UpdateProgress, - this); + this->CMakeInstance->SetProgressCallback( + [this](const char* msg, float prog) { this->UpdateProgress(msg, prog); }); // always save the current gui values to disk this->FillCacheManagerFromUI(); @@ -560,7 +556,7 @@ int cmCursesMainForm::Configure(int noconfigure) } else { retVal = this->CMakeInstance->Configure(); } - this->CMakeInstance->SetProgressCallback(nullptr, nullptr); + this->CMakeInstance->SetProgressCallback(nullptr); keypad(stdscr, true); /* Use key symbols as KEY_DOWN */ @@ -606,8 +602,8 @@ int cmCursesMainForm::Generate() this->PrintKeys(1); touchwin(stdscr); refresh(); - this->CMakeInstance->SetProgressCallback(cmCursesMainForm::UpdateProgress, - this); + this->CMakeInstance->SetProgressCallback( + [this](const char* msg, float prog) { this->UpdateProgress(msg, prog); }); // Get rid of previous errors this->Errors = std::vector<std::string>(); @@ -615,7 +611,7 @@ int cmCursesMainForm::Generate() // run the generate process int retVal = this->CMakeInstance->Generate(); - this->CMakeInstance->SetProgressCallback(nullptr, nullptr); + this->CMakeInstance->SetProgressCallback(nullptr); keypad(stdscr, true); /* Use key symbols as KEY_DOWN */ if (retVal != 0 || !this->Errors.empty()) { diff --git a/Source/CursesDialog/cmCursesMainForm.h b/Source/CursesDialog/cmCursesMainForm.h index 63dbc1b..cc6482f 100644 --- a/Source/CursesDialog/cmCursesMainForm.h +++ b/Source/CursesDialog/cmCursesMainForm.h @@ -102,8 +102,7 @@ public: /** * Progress callback */ - static void UpdateProgressOld(const char* msg, float prog, void*); - static void UpdateProgress(const char* msg, float prog, void*); + void UpdateProgress(const char* msg, float prog); protected: // Copy the cache values from the user interface to the actual diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index 2eecce6..065d610 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -23,16 +23,26 @@ QCMake::QCMake(QObject* p) cmSystemTools::DisableRunCommandOutput(); cmSystemTools::SetRunCommandHideConsole(true); - cmSystemTools::SetMessageCallback(QCMake::messageCallback, this); - cmSystemTools::SetStdoutCallback(QCMake::stdoutCallback, this); - cmSystemTools::SetStderrCallback(QCMake::stderrCallback, this); + + cmSystemTools::SetMessageCallback( + [this](const char* msg, const char* title) { + this->messageCallback(msg, title); + }); + cmSystemTools::SetStdoutCallback( + [this](const char* msg, size_t len) { this->stdoutCallback(msg, len); }); + cmSystemTools::SetStderrCallback( + [this](const char* msg, size_t len) { this->stderrCallback(msg, len); }); this->CMakeInstance = new cmake(cmake::RoleProject, cmState::Project); this->CMakeInstance->SetCMakeEditCommand( cmSystemTools::GetCMakeGUICommand()); - this->CMakeInstance->SetProgressCallback(QCMake::progressCallback, this); + this->CMakeInstance->SetProgressCallback( + [this](const char* msg, float percent) { + this->progressCallback(msg, percent); + }); - cmSystemTools::SetInterruptCallback(QCMake::interruptCallback, this); + cmSystemTools::SetInterruptCallback( + [this] { return this->interruptCallback(); }); std::vector<cmake::GeneratorInfo> generators; this->CMakeInstance->GetRegisteredGenerators( @@ -330,46 +340,40 @@ void QCMake::interrupt() this->InterruptFlag.ref(); } -bool QCMake::interruptCallback(void* cd) +bool QCMake::interruptCallback() { - QCMake* self = reinterpret_cast<QCMake*>(cd); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) - return self->InterruptFlag; + return this->InterruptFlag; #else - return self->InterruptFlag.load(); + return this->InterruptFlag.load(); #endif } -void QCMake::progressCallback(const char* msg, float percent, void* cd) +void QCMake::progressCallback(const char* msg, float percent) { - QCMake* self = reinterpret_cast<QCMake*>(cd); if (percent >= 0) { - emit self->progressChanged(QString::fromLocal8Bit(msg), percent); + emit this->progressChanged(QString::fromLocal8Bit(msg), percent); } else { - emit self->outputMessage(QString::fromLocal8Bit(msg)); + emit this->outputMessage(QString::fromLocal8Bit(msg)); } QCoreApplication::processEvents(); } -void QCMake::messageCallback(const char* msg, const char* /*title*/, - bool& /*stop*/, void* cd) +void QCMake::messageCallback(const char* msg, const char* /*title*/) { - QCMake* self = reinterpret_cast<QCMake*>(cd); - emit self->errorMessage(QString::fromLocal8Bit(msg)); + emit this->errorMessage(QString::fromLocal8Bit(msg)); QCoreApplication::processEvents(); } -void QCMake::stdoutCallback(const char* msg, size_t len, void* cd) +void QCMake::stdoutCallback(const char* msg, size_t len) { - QCMake* self = reinterpret_cast<QCMake*>(cd); - emit self->outputMessage(QString::fromLocal8Bit(msg, int(len))); + emit this->outputMessage(QString::fromLocal8Bit(msg, int(len))); QCoreApplication::processEvents(); } -void QCMake::stderrCallback(const char* msg, size_t len, void* cd) +void QCMake::stderrCallback(const char* msg, size_t len) { - QCMake* self = reinterpret_cast<QCMake*>(cd); - emit self->outputMessage(QString::fromLocal8Bit(msg, int(len))); + emit this->outputMessage(QString::fromLocal8Bit(msg, int(len))); QCoreApplication::processEvents(); } diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h index c84da58..4f22505 100644 --- a/Source/QtDialog/QCMake.h +++ b/Source/QtDialog/QCMake.h @@ -167,12 +167,12 @@ signals: protected: cmake* CMakeInstance; - static bool interruptCallback(void*); - static void progressCallback(const char* msg, float percent, void* cd); - static void messageCallback(const char* msg, const char* title, bool&, - void* cd); - static void stdoutCallback(const char* msg, size_t len, void* cd); - static void stderrCallback(const char* msg, size_t len, void* cd); + bool interruptCallback(); + void progressCallback(const char* msg, float percent); + void messageCallback(const char* msg, const char* title); + void stdoutCallback(const char* msg, size_t len); + void stderrCallback(const char* msg, size_t len); + bool WarnUninitializedMode; bool WarnUnusedMode; bool WarnUnusedAllMode; diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index c2318cd..0f911c1 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -3758,8 +3758,7 @@ bool cmFileCommand::HandleCreateLinkCommand( // Check if copy-on-error is enabled in the arguments. if (!completed && copyOnErrorArg.IsEnabled()) { - completed = - cmSystemTools::cmCopyFile(fileName.c_str(), newFileName.c_str()); + completed = cmSystemTools::cmCopyFile(fileName, newFileName); if (!completed) { result = "Copy failed: " + cmSystemTools::GetLastSystemError(); } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 2b5c98f..386a3f7 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -567,11 +567,6 @@ void cmGlobalGenerator::EnableLanguage( return; } - // Find the native build tool for this generator. - if (!this->FindMakeProgram(mf)) { - return; - } - // Tell the generator about the target system. std::string system = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME"); if (!this->SetSystemName(system, mf)) { @@ -592,6 +587,11 @@ void cmGlobalGenerator::EnableLanguage( cmSystemTools::SetFatalErrorOccured(); return; } + + // Find the native build tool for this generator. + if (!this->FindMakeProgram(mf)) { + return; + } } // Check that the languages are supported by the generator and its diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index e3dd2f9..77be592 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -262,9 +262,8 @@ void cmGlobalVisualStudioGenerator::ConfigureCMakeVisualStudioMacros() // purposes but newer versions distributed with CMake will replace // older versions in user directories. int res; - if (!cmSystemTools::FileTimeCompare(src.c_str(), dst.c_str(), &res) || - res > 0) { - if (!cmSystemTools::CopyFileAlways(src.c_str(), dst.c_str())) { + if (!cmSystemTools::FileTimeCompare(src, dst, &res) || res > 0) { + if (!cmSystemTools::CopyFileAlways(src, dst)) { std::ostringstream oss; oss << "Could not copy from: " << src << std::endl; oss << " to: " << dst << std::endl; diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index bc6b453..12d9304 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -471,6 +471,18 @@ std::string cmGlobalVisualStudioVersionedGenerator::FindMSBuildCommand() // Ask Visual Studio Installer tool. std::string vs; if (vsSetupAPIHelper.GetVSInstanceInfo(vs)) { + std::string const& hostArch = + this->GetPlatformToolsetHostArchitectureString(); + if (hostArch == "x64") { + msbuild = vs + "/MSBuild/Current/Bin/amd64/MSBuild.exe"; + if (cmSystemTools::FileExists(msbuild)) { + return msbuild; + } + msbuild = vs + "/MSBuild/15.0/Bin/amd64/MSBuild.exe"; + if (cmSystemTools::FileExists(msbuild)) { + return msbuild; + } + } msbuild = vs + "/MSBuild/Current/Bin/MSBuild.exe"; if (cmSystemTools::FileExists(msbuild)) { return msbuild; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 3ae8034..ab139c0 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3749,8 +3749,7 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile, } if (copyonly) { - if (!cmSystemTools::CopyFileIfDifferent(sinfile.c_str(), - soutfile.c_str())) { + if (!cmSystemTools::CopyFileIfDifferent(sinfile, soutfile)) { return 0; } } else { @@ -3801,8 +3800,7 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile, // close the files before attempting to copy fin.close(); fout.close(); - if (!cmSystemTools::CopyFileIfDifferent(tempOutputFile.c_str(), - soutfile.c_str())) { + if (!cmSystemTools::CopyFileIfDifferent(tempOutputFile, soutfile)) { res = 0; } else { cmSystemTools::SetPermissions(soutfile, perm); diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx index f7d3879..e740c05 100644 --- a/Source/cmServer.cxx +++ b/Source/cmServer.cxx @@ -96,11 +96,16 @@ void cmServer::ProcessRequest(cmConnection* connection, return; } - cmSystemTools::SetMessageCallback(reportMessage, - const_cast<cmServerRequest*>(&request)); + cmSystemTools::SetMessageCallback( + [&request](const char* msg, const char* title) { + reportMessage(msg, title, request); + }); + if (this->Protocol) { this->Protocol->CMakeInstance()->SetProgressCallback( - reportProgress, const_cast<cmServerRequest*>(&request)); + [&request](const char* msg, float prog) { + reportProgress(msg, prog, request); + }); this->WriteResponse(connection, this->Protocol->Process(request), debug.get()); } else { @@ -150,28 +155,25 @@ void cmServer::PrintHello(cmConnection* connection) const this->WriteJsonObject(connection, hello, nullptr); } -void cmServer::reportProgress(const char* msg, float progress, void* data) +void cmServer::reportProgress(const char* msg, float progress, + const cmServerRequest& request) { - const cmServerRequest* request = static_cast<const cmServerRequest*>(data); - assert(request); if (progress < 0.0f || progress > 1.0f) { - request->ReportMessage(msg, ""); + request.ReportMessage(msg, ""); } else { - request->ReportProgress(0, static_cast<int>(progress * 1000), 1000, msg); + request.ReportProgress(0, static_cast<int>(progress * 1000), 1000, msg); } } void cmServer::reportMessage(const char* msg, const char* title, - bool& /* cancel */, void* data) + const cmServerRequest& request) { - const cmServerRequest* request = static_cast<const cmServerRequest*>(data); - assert(request); assert(msg); std::string titleString; if (title) { titleString = title; } - request->ReportMessage(std::string(msg), titleString); + request.ReportMessage(std::string(msg), titleString); } cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request) diff --git a/Source/cmServer.h b/Source/cmServer.h index d2ffbb3..e1ed27a 100644 --- a/Source/cmServer.h +++ b/Source/cmServer.h @@ -119,9 +119,10 @@ public: void OnConnected(cmConnection* connection) override; private: - static void reportProgress(const char* msg, float progress, void* data); - static void reportMessage(const char* msg, const char* title, bool& cancel, - void* data); + static void reportProgress(const char* msg, float progress, + const cmServerRequest& request); + static void reportMessage(const char* msg, const char* title, + const cmServerRequest& request); // Handle requests: cmServerResponse SetProtocolVersion(const cmServerRequest& request); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index f7de3aa..a9cf0c6 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -76,6 +76,15 @@ # include <malloc.h> /* for malloc/free on QNX */ #endif +namespace { + +cmSystemTools::InterruptCallback s_InterruptCallback; +cmSystemTools::MessageCallback s_MessageCallback; +cmSystemTools::OutputCallback s_StderrCallback; +cmSystemTools::OutputCallback s_StdoutCallback; + +} // namespace + static bool cm_isspace(char c) { return ((c & 0x80) == 0) && isspace(c); @@ -161,15 +170,6 @@ bool cmSystemTools::s_FatalErrorOccured = false; bool cmSystemTools::s_DisableMessages = false; bool cmSystemTools::s_ForceUnixPaths = false; -cmSystemTools::MessageCallback cmSystemTools::s_MessageCallback; -cmSystemTools::OutputCallback cmSystemTools::s_StdoutCallback; -cmSystemTools::OutputCallback cmSystemTools::s_StderrCallback; -cmSystemTools::InterruptCallback cmSystemTools::s_InterruptCallback; -void* cmSystemTools::s_MessageCallbackClientData; -void* cmSystemTools::s_StdoutCallbackClientData; -void* cmSystemTools::s_StderrCallbackClientData; -void* cmSystemTools::s_InterruptCallbackClientData; - // replace replace with with as many times as it shows up in source. // write the result into source. #if defined(_WIN32) && !defined(__CYGWIN__) @@ -277,42 +277,38 @@ void cmSystemTools::Error(const std::string& m) cmSystemTools::Message(message, "Error"); } -void cmSystemTools::SetInterruptCallback(InterruptCallback f, void* clientData) +void cmSystemTools::SetInterruptCallback(InterruptCallback f) { - s_InterruptCallback = f; - s_InterruptCallbackClientData = clientData; + s_InterruptCallback = std::move(f); } bool cmSystemTools::GetInterruptFlag() { if (s_InterruptCallback) { - return (*s_InterruptCallback)(s_InterruptCallbackClientData); + return s_InterruptCallback(); } return false; } -void cmSystemTools::SetMessageCallback(MessageCallback f, void* clientData) +void cmSystemTools::SetMessageCallback(MessageCallback f) { - s_MessageCallback = f; - s_MessageCallbackClientData = clientData; + s_MessageCallback = std::move(f); } -void cmSystemTools::SetStdoutCallback(OutputCallback f, void* clientData) +void cmSystemTools::SetStdoutCallback(OutputCallback f) { - s_StdoutCallback = f; - s_StdoutCallbackClientData = clientData; + s_StdoutCallback = std::move(f); } -void cmSystemTools::SetStderrCallback(OutputCallback f, void* clientData) +void cmSystemTools::SetStderrCallback(OutputCallback f) { - s_StderrCallback = f; - s_StderrCallbackClientData = clientData; + s_StderrCallback = std::move(f); } void cmSystemTools::Stderr(const std::string& s) { if (s_StderrCallback) { - (*s_StderrCallback)(s.c_str(), s.length(), s_StderrCallbackClientData); + s_StderrCallback(s.c_str(), s.length()); } else { std::cerr << s << std::flush; } @@ -321,7 +317,7 @@ void cmSystemTools::Stderr(const std::string& s) void cmSystemTools::Stdout(const std::string& s) { if (s_StdoutCallback) { - (*s_StdoutCallback)(s.c_str(), s.length(), s_StdoutCallbackClientData); + s_StdoutCallback(s.c_str(), s.length()); } else { std::cout << s << std::flush; } @@ -333,8 +329,7 @@ void cmSystemTools::Message(const char* m1, const char* title) return; } if (s_MessageCallback) { - (*s_MessageCallback)(m1, title, s_DisableMessages, - s_MessageCallbackClientData); + s_MessageCallback(m1, title); return; } std::cerr << m1 << std::endl << std::flush; @@ -940,17 +935,12 @@ std::string cmSystemTools::FileExistsInParentDirectories(const char* fname, return ""; } -bool cmSystemTools::cmCopyFile(const char* source, const char* destination) +bool cmSystemTools::cmCopyFile(const std::string& source, + const std::string& destination) { return Superclass::CopyFileAlways(source, destination); } -bool cmSystemTools::CopyFileIfDifferent(const char* source, - const char* destination) -{ - return Superclass::CopyFileIfDifferent(source, destination); -} - #ifdef _WIN32 cmSystemTools::WindowsFileRetry cmSystemTools::GetWindowsFileRetry() { diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 851e77f..a6f68d3 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -10,6 +10,7 @@ #include "cmProcessOutput.h" #include "cmsys/Process.h" #include "cmsys/SystemTools.hxx" // IWYU pragma: export +#include <functional> #include <stddef.h> #include <string> #include <vector> @@ -55,15 +56,13 @@ public: */ static std::string TrimWhitespace(const std::string& s); - typedef void (*MessageCallback)(const char*, const char*, bool&, void*); + using MessageCallback = std::function<void(const char*, const char*)>; /** * Set the function used by GUIs to display error messages * Function gets passed: message as a const char*, - * title as a const char*, and a reference to bool that when - * set to false, will disable further messages (cancel). + * title as a const char*. */ - static void SetMessageCallback(MessageCallback f, - void* clientData = nullptr); + static void SetMessageCallback(MessageCallback f); /** * Display an error message. @@ -81,19 +80,18 @@ public: Message(m.c_str(), title); } - typedef void (*OutputCallback)(const char*, size_t length, void*); + using OutputCallback = std::function<void(const char*, size_t)>; ///! Send a string to stdout static void Stdout(const std::string& s); - static void SetStdoutCallback(OutputCallback, void* clientData = nullptr); + static void SetStdoutCallback(OutputCallback f); ///! Send a string to stderr static void Stderr(const std::string& s); - static void SetStderrCallback(OutputCallback, void* clientData = nullptr); + static void SetStderrCallback(OutputCallback f); - typedef bool (*InterruptCallback)(void*); - static void SetInterruptCallback(InterruptCallback f, - void* clientData = nullptr); + using InterruptCallback = std::function<bool()>; + static void SetInterruptCallback(InterruptCallback f); static bool GetInterruptFlag(); ///! Return true if there was an error at any point. @@ -179,8 +177,8 @@ public: std::vector<std::string>& files, int type = 0); ///! Copy a file. - static bool cmCopyFile(const char* source, const char* destination); - static bool CopyFileIfDifferent(const char* source, const char* destination); + static bool cmCopyFile(const std::string& source, + const std::string& destination); /** Rename a file or directory within a single disk volume (atomic if possible). */ @@ -550,14 +548,6 @@ private: static bool s_FatalErrorOccured; static bool s_DisableMessages; static bool s_DisableRunCommandOutput; - static MessageCallback s_MessageCallback; - static OutputCallback s_StdoutCallback; - static OutputCallback s_StderrCallback; - static InterruptCallback s_InterruptCallback; - static void* s_MessageCallbackClientData; - static void* s_StdoutCallbackClientData; - static void* s_StderrCallbackClientData; - static void* s_InterruptCallbackClientData; }; #endif diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx index 01ef5cb..9648b21 100644 --- a/Source/cmUseMangledMesaCommand.cxx +++ b/Source/cmUseMangledMesaCommand.cxx @@ -100,6 +100,6 @@ void cmUseMangledMesaCommand::CopyAndFullPathMesaHeader(const char* source, // close the files before attempting to copy fin.close(); fout.close(); - cmSystemTools::CopyFileIfDifferent(tempOutputFile.c_str(), outFile.c_str()); + cmSystemTools::CopyFileIfDifferent(tempOutputFile, outFile); cmSystemTools::RemoveFile(tempOutputFile); } diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 70316f1..2b627ff 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -157,8 +157,6 @@ cmake::cmake(Role role, cmState::Mode mode) #endif this->GlobalGenerator = nullptr; - this->ProgressCallback = nullptr; - this->ProgressCallbackClientData = nullptr; this->CurrentWorkingMode = NORMAL_MODE; #ifdef CMAKE_BUILD_WITH_CMAKE @@ -1922,17 +1920,15 @@ bool cmake::DeleteCache(const std::string& path) return this->State->DeleteCache(path); } -void cmake::SetProgressCallback(ProgressCallbackType f, void* cd) +void cmake::SetProgressCallback(ProgressCallbackType f) { - this->ProgressCallback = f; - this->ProgressCallbackClientData = cd; + this->ProgressCallback = std::move(f); } void cmake::UpdateProgress(const char* msg, float prog) { if (this->ProgressCallback && !this->State->GetIsInTryCompile()) { - (*this->ProgressCallback)(msg, prog, this->ProgressCallbackClientData); - return; + this->ProgressCallback(msg, prog); } } @@ -2358,7 +2354,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args) outFile += "/CMakeLists.txt"; // Copy file - if (!cmSystemTools::cmCopyFile(inFile.c_str(), outFile.c_str())) { + if (!cmSystemTools::cmCopyFile(inFile, outFile)) { std::cerr << "Error copying file \"" << inFile << "\" to \"" << outFile << "\".\n"; return 1; diff --git a/Source/cmake.h b/Source/cmake.h index 93a31db..314101e 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -5,6 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <functional> #include <map> #include <memory> // IWYU pragma: keep #include <set> @@ -272,7 +273,7 @@ public: ///! Parse command line arguments that might set cache values bool SetCacheArgs(const std::vector<std::string>&); - typedef void (*ProgressCallbackType)(const char* msg, float progress, void*); + using ProgressCallbackType = std::function<void(const char*, float)>; /** * Set the function used by GUIs to receive progress updates * Function gets passed: message as a const char*, a progress @@ -280,7 +281,7 @@ public: * number provided may be negative in cases where a message is * to be displayed without any progress percentage. */ - void SetProgressCallback(ProgressCallbackType f, void* clientData = nullptr); + void SetProgressCallback(ProgressCallbackType f); ///! this is called by generators to update the progress void UpdateProgress(const char* msg, float prog); @@ -486,7 +487,6 @@ protected: private: ProgressCallbackType ProgressCallback; - void* ProgressCallbackClientData; bool InTryCompile; WorkingMode CurrentWorkingMode; bool DebugOutput; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 0ec2552..890b74e 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -117,9 +117,8 @@ int do_cmake(int ac, char const* const* av); static int do_build(int ac, char const* const* av); static int do_open(int ac, char const* const* av); -static cmMakefile* cmakemainGetMakefile(void* clientdata) +static cmMakefile* cmakemainGetMakefile(cmake* cm) { - cmake* cm = static_cast<cmake*>(clientdata); if (cm && cm->GetDebugOutput()) { cmGlobalGenerator* gg = cm->GetGlobalGenerator(); if (gg) { @@ -129,10 +128,10 @@ static cmMakefile* cmakemainGetMakefile(void* clientdata) return nullptr; } -static std::string cmakemainGetStack(void* clientdata) +static std::string cmakemainGetStack(cmake* cm) { std::string msg; - cmMakefile* mf = cmakemainGetMakefile(clientdata); + cmMakefile* mf = cmakemainGetMakefile(cm); if (mf) { msg = mf->FormatListFileStack(); if (!msg.empty()) { @@ -144,15 +143,14 @@ static std::string cmakemainGetStack(void* clientdata) } static void cmakemainMessageCallback(const char* m, const char* /*unused*/, - bool& /*unused*/, void* clientdata) + cmake* cm) { - std::cerr << m << cmakemainGetStack(clientdata) << std::endl << std::flush; + std::cerr << m << cmakemainGetStack(cm) << std::endl << std::flush; } -static void cmakemainProgressCallback(const char* m, float prog, - void* clientdata) +static void cmakemainProgressCallback(const char* m, float prog, cmake* cm) { - cmMakefile* mf = cmakemainGetMakefile(clientdata); + cmMakefile* mf = cmakemainGetMakefile(cm); std::string dir; if ((mf) && (strstr(m, "Configuring") == m) && (prog < 0)) { dir = " "; @@ -163,8 +161,7 @@ static void cmakemainProgressCallback(const char* m, float prog, } if ((prog < 0) || (!dir.empty())) { - std::cout << "-- " << m << dir << cmakemainGetStack(clientdata) - << std::endl; + std::cout << "-- " << m << dir << cmakemainGetStack(cm) << std::endl; } std::cout.flush(); @@ -322,8 +319,12 @@ int do_cmake(int ac, char const* const* av) cmake cm(role, mode); cm.SetHomeDirectory(""); cm.SetHomeOutputDirectory(""); - cmSystemTools::SetMessageCallback(cmakemainMessageCallback, &cm); - cm.SetProgressCallback(cmakemainProgressCallback, &cm); + cmSystemTools::SetMessageCallback([&cm](const char* msg, const char* title) { + cmakemainMessageCallback(msg, title, &cm); + }); + cm.SetProgressCallback([&cm](const char* msg, float prog) { + cmakemainProgressCallback(msg, prog, &cm); + }); cm.SetWorkingMode(workingMode); int res = cm.Run(args, view_only); @@ -498,8 +499,12 @@ static int do_build(int ac, char const* const* av) } cmake cm(cmake::RoleInternal, cmState::Unknown); - cmSystemTools::SetMessageCallback(cmakemainMessageCallback, &cm); - cm.SetProgressCallback(cmakemainProgressCallback, &cm); + cmSystemTools::SetMessageCallback([&cm](const char* msg, const char* title) { + cmakemainMessageCallback(msg, title, &cm); + }); + cm.SetProgressCallback([&cm](const char* msg, float prog) { + cmakemainProgressCallback(msg, prog, &cm); + }); return cm.Build(jobs, dir, target, config, nativeOptions, clean, verbose); #endif } @@ -536,8 +541,12 @@ static int do_open(int ac, char const* const* av) } cmake cm(cmake::RoleInternal, cmState::Unknown); - cmSystemTools::SetMessageCallback(cmakemainMessageCallback, &cm); - cm.SetProgressCallback(cmakemainProgressCallback, &cm); + cmSystemTools::SetMessageCallback([&cm](const char* msg, const char* title) { + cmakemainMessageCallback(msg, title, &cm); + }); + cm.SetProgressCallback([&cm](const char* msg, float prog) { + cmakemainProgressCallback(msg, prog, &cm); + }); return cm.Open(dir, false) ? 0 : 1; #endif } diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 2a3aedd..d20c5d2 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -482,8 +482,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) // If error occurs we want to continue copying next files. bool return_value = false; for (std::string::size_type cc = 2; cc < args.size() - 1; cc++) { - if (!cmSystemTools::cmCopyFile(args[cc].c_str(), - args.back().c_str())) { + if (!cmSystemTools::cmCopyFile(args[cc], args.back())) { std::cerr << "Error copying file \"" << args[cc] << "\" to \"" << args.back() << "\".\n"; return_value = true; @@ -505,8 +504,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) // If error occurs we want to continue copying next files. bool return_value = false; for (std::string::size_type cc = 2; cc < args.size() - 1; cc++) { - if (!cmSystemTools::CopyFileIfDifferent(args[cc].c_str(), - args.back().c_str())) { + if (!cmSystemTools::CopyFileIfDifferent(args[cc], args.back())) { std::cerr << "Error copying file (if different) from \"" << args[cc] << "\" to \"" << args.back() << "\".\n"; return_value = true; @@ -1304,7 +1302,7 @@ bool cmcmd::SymlinkInternal(std::string const& file, std::string const& link) cmSystemTools::RemoveFile(link); } #if defined(_WIN32) && !defined(__CYGWIN__) - return cmSystemTools::CopyFileAlways(file.c_str(), link.c_str()); + return cmSystemTools::CopyFileAlways(file, link); #else std::string linktext = cmSystemTools::GetFilenameName(file); return cmSystemTools::CreateSymlink(linktext, link); diff --git a/Tests/RunCMake/FetchContent/MakeAvailable-stdout.txt b/Tests/RunCMake/FetchContent/MakeAvailable-stdout.txt new file mode 100644 index 0000000..6e6c730 --- /dev/null +++ b/Tests/RunCMake/FetchContent/MakeAvailable-stdout.txt @@ -0,0 +1,2 @@ +Confirmation project has been added +.*Confirmation script has been called diff --git a/Tests/RunCMake/FetchContent/MakeAvailable.cmake b/Tests/RunCMake/FetchContent/MakeAvailable.cmake new file mode 100644 index 0000000..a93f1f7 --- /dev/null +++ b/Tests/RunCMake/FetchContent/MakeAvailable.cmake @@ -0,0 +1,20 @@ +include(FetchContent) + +FetchContent_Declare( + WithProject + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/WithProject +) +FetchContent_Declare( + WithoutProject + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/WithoutProject +) + +# Order is important and will be verified by test output +FetchContent_MakeAvailable(WithProject WithoutProject) + +get_property(addedWith GLOBAL PROPERTY FetchWithProject SET) +if(NOT addedWith) + message(SEND_ERROR "Subdir with CMakeLists.txt not added") +endif() + +include(${withoutproject_SOURCE_DIR}/confirmMessage.cmake) diff --git a/Tests/RunCMake/FetchContent/MakeAvailableTwice-stdout.txt b/Tests/RunCMake/FetchContent/MakeAvailableTwice-stdout.txt new file mode 100644 index 0000000..8d3b7c0 --- /dev/null +++ b/Tests/RunCMake/FetchContent/MakeAvailableTwice-stdout.txt @@ -0,0 +1,4 @@ +-- Before first[ + ]+-- Confirmation project has been added[ + ]+-- Between both[ + ]+-- After last diff --git a/Tests/RunCMake/FetchContent/MakeAvailableTwice.cmake b/Tests/RunCMake/FetchContent/MakeAvailableTwice.cmake new file mode 100644 index 0000000..a9af020 --- /dev/null +++ b/Tests/RunCMake/FetchContent/MakeAvailableTwice.cmake @@ -0,0 +1,12 @@ +include(FetchContent) + +FetchContent_Declare( + WithProject + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/WithProject +) + +message(STATUS "Before first") +FetchContent_MakeAvailable(WithProject) +message(STATUS "Between both") +FetchContent_MakeAvailable(WithProject) +message(STATUS "After last") diff --git a/Tests/RunCMake/FetchContent/MakeAvailableUndeclared-result.txt b/Tests/RunCMake/FetchContent/MakeAvailableUndeclared-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/FetchContent/MakeAvailableUndeclared-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/FetchContent/MakeAvailableUndeclared-stderr.txt b/Tests/RunCMake/FetchContent/MakeAvailableUndeclared-stderr.txt new file mode 100644 index 0000000..9715b78 --- /dev/null +++ b/Tests/RunCMake/FetchContent/MakeAvailableUndeclared-stderr.txt @@ -0,0 +1 @@ +No content details recorded for NoDetails diff --git a/Tests/RunCMake/FetchContent/MakeAvailableUndeclared.cmake b/Tests/RunCMake/FetchContent/MakeAvailableUndeclared.cmake new file mode 100644 index 0000000..bd57cbe --- /dev/null +++ b/Tests/RunCMake/FetchContent/MakeAvailableUndeclared.cmake @@ -0,0 +1,3 @@ +include(FetchContent) + +FetchContent_MakeAvailable(NoDetails) diff --git a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake index 9c1ab66..e28ae96 100644 --- a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake +++ b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake @@ -11,6 +11,9 @@ run_cmake(VarDefinitions) run_cmake(GetProperties) run_cmake(DirOverrides) run_cmake(UsesTerminalOverride) +run_cmake(MakeAvailable) +run_cmake(MakeAvailableTwice) +run_cmake(MakeAvailableUndeclared) # We need to pass through CMAKE_GENERATOR and CMAKE_MAKE_PROGRAM # to ensure the test can run on machines where the build tool diff --git a/Tests/RunCMake/FetchContent/WithProject/CMakeLists.txt b/Tests/RunCMake/FetchContent/WithProject/CMakeLists.txt new file mode 100644 index 0000000..b6a3750 --- /dev/null +++ b/Tests/RunCMake/FetchContent/WithProject/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.13) +project(WithProject LANGUAGES NONE) + +set_property(GLOBAL PROPERTY FetchWithProject YES) +message(STATUS "Confirmation project has been added") diff --git a/Tests/RunCMake/FetchContent/WithoutProject/confirmMessage.cmake b/Tests/RunCMake/FetchContent/WithoutProject/confirmMessage.cmake new file mode 100644 index 0000000..a2f5c61 --- /dev/null +++ b/Tests/RunCMake/FetchContent/WithoutProject/confirmMessage.cmake @@ -0,0 +1 @@ +message(STATUS "Confirmation script has been called") diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py index 882cdc1..d903dbe 100644 --- a/Utilities/Sphinx/cmake.py +++ b/Utilities/Sphinx/cmake.py @@ -21,6 +21,8 @@ from pygments.lexer import bygroups # - Unix paths are recognized by '/'; support for Windows paths may be added if needed # - (\\.) allows for \-escapes (used in manual/cmake-language.7) # - $<..$<..$>..> nested occurence in cmake-buildsystem +# - Nested variable evaluations are only supported in a limited capacity. Only +# one level of nesting is supported and at most one nested variable can be present. CMakeLexer.tokens["root"] = [ (r'\b(\w+)([ \t]*)(\()', bygroups(Name.Function, Text, Name.Function), '#push'), # fctn( @@ -34,7 +36,8 @@ CMakeLexer.tokens["root"] = [ (r'[<>]=', Punctuation), # used in FindPkgConfig.cmake (r'\$<', Operator, '#push'), # $<...> (r'<[^<|]+?>(\w*\.\.\.)?', Name.Variable), # <expr> - (r'(\$\w*\{)(.+?)(\})', bygroups(Operator, Name.Tag, Operator)), # ${..} $ENV{..} + (r'(\$\w*\{)([^\}\$]*)?(?:(\$\w*\{)([^\}]+?)(\}))?([^\}]*?)(\})', # ${..} $ENV{..}, possibly nested + bygroups(Operator, Name.Tag, Operator, Name.Tag, Operator, Name.Tag, Operator)), (r'([A-Z]+\{)(.+?)(\})', bygroups(Operator, Name.Tag, Operator)), # DATA{ ...} (r'[a-z]+(@|(://))((\\.)|[\w.+-:/\\])+', Name.Attribute), # URL, git@, ... (r'/\w[\w\.\+-/\\]*', Name.Attribute), # absolute path |