diff options
80 files changed, 1474 insertions, 582 deletions
diff --git a/Help/command/cmake_host_system_information.rst b/Help/command/cmake_host_system_information.rst index 2b902a9..998e146 100644 --- a/Help/command/cmake_host_system_information.rst +++ b/Help/command/cmake_host_system_information.rst @@ -13,46 +13,236 @@ queried. The list of queried values is stored in ``<variable>``. ``<key>`` can be one of the following values: -============================= ================================================ -Key Description -============================= ================================================ -``NUMBER_OF_LOGICAL_CORES`` Number of logical cores -``NUMBER_OF_PHYSICAL_CORES`` Number of physical cores -``HOSTNAME`` Hostname -``FQDN`` Fully qualified domain name -``TOTAL_VIRTUAL_MEMORY`` Total virtual memory in MiB [#mebibytes]_ -``AVAILABLE_VIRTUAL_MEMORY`` Available virtual memory in MiB [#mebibytes]_ -``TOTAL_PHYSICAL_MEMORY`` Total physical memory in MiB [#mebibytes]_ -``AVAILABLE_PHYSICAL_MEMORY`` Available physical memory in MiB [#mebibytes]_ -============================= ================================================ - -.. versionadded:: 3.10 - Additional ``<key>`` values are available: - -============================= ================================================ -Key Description -============================= ================================================ -``IS_64BIT`` One if processor is 64Bit -``HAS_FPU`` One if processor has floating point unit -``HAS_MMX`` One if processor supports MMX instructions -``HAS_MMX_PLUS`` One if processor supports Ext. MMX instructions -``HAS_SSE`` One if processor supports SSE instructions -``HAS_SSE2`` One if processor supports SSE2 instructions -``HAS_SSE_FP`` One if processor supports SSE FP instructions -``HAS_SSE_MMX`` One if processor supports SSE MMX instructions -``HAS_AMD_3DNOW`` One if processor supports 3DNow instructions -``HAS_AMD_3DNOW_PLUS`` One if processor supports 3DNow+ instructions -``HAS_IA64`` One if IA64 processor emulating x86 -``HAS_SERIAL_NUMBER`` One if processor has serial number -``PROCESSOR_SERIAL_NUMBER`` Processor serial number -``PROCESSOR_NAME`` Human readable processor name -``PROCESSOR_DESCRIPTION`` Human readable full processor description -``OS_NAME`` See :variable:`CMAKE_HOST_SYSTEM_NAME` -``OS_RELEASE`` The OS sub-type e.g. on Windows ``Professional`` -``OS_VERSION`` The OS build ID -``OS_PLATFORM`` See :variable:`CMAKE_HOST_SYSTEM_PROCESSOR` -============================= ================================================ +``NUMBER_OF_LOGICAL_CORES`` + Number of logical cores + +``NUMBER_OF_PHYSICAL_CORES`` + Number of physical cores + +``HOSTNAME`` + Hostname + +``FQDN`` + Fully qualified domain name + +``TOTAL_VIRTUAL_MEMORY`` + Total virtual memory in MiB [#mebibytes]_ + +``AVAILABLE_VIRTUAL_MEMORY`` + Available virtual memory in MiB [#mebibytes]_ + +``TOTAL_PHYSICAL_MEMORY`` + Total physical memory in MiB [#mebibytes]_ + +``AVAILABLE_PHYSICAL_MEMORY`` + Available physical memory in MiB [#mebibytes]_ + +``IS_64BIT`` + .. versionadded:: 3.10 + + One if processor is 64Bit + +``HAS_FPU`` + .. versionadded:: 3.10 + + One if processor has floating point unit + +``HAS_MMX`` + .. versionadded:: 3.10 + + One if processor supports MMX instructions + +``HAS_MMX_PLUS`` + .. versionadded:: 3.10 + + One if processor supports Ext. MMX instructions + +``HAS_SSE`` + .. versionadded:: 3.10 + + One if processor supports SSE instructions + +``HAS_SSE2`` + .. versionadded:: 3.10 + + One if processor supports SSE2 instructions + +``HAS_SSE_FP`` + .. versionadded:: 3.10 + + One if processor supports SSE FP instructions + +``HAS_SSE_MMX`` + .. versionadded:: 3.10 + + One if processor supports SSE MMX instructions + +``HAS_AMD_3DNOW`` + .. versionadded:: 3.10 + + One if processor supports 3DNow instructions + +``HAS_AMD_3DNOW_PLUS`` + .. versionadded:: 3.10 + + One if processor supports 3DNow+ instructions + +``HAS_IA64`` + .. versionadded:: 3.10 + + One if IA64 processor emulating x86 + +``HAS_SERIAL_NUMBER`` + .. versionadded:: 3.10 + + One if processor has serial number + +``PROCESSOR_SERIAL_NUMBER`` + .. versionadded:: 3.10 + + Processor serial number + +``PROCESSOR_NAME`` + .. versionadded:: 3.10 + + Human readable processor name + +``PROCESSOR_DESCRIPTION`` + .. versionadded:: 3.10 + + Human readable full processor description + +``OS_NAME`` + .. versionadded:: 3.10 + + See :variable:`CMAKE_HOST_SYSTEM_NAME` + +``OS_RELEASE`` + .. versionadded:: 3.10 + + The OS sub-type e.g. on Windows ``Professional`` + +``OS_VERSION`` + .. versionadded:: 3.10 + + The OS build ID + +``OS_PLATFORM`` + .. versionadded:: 3.10 + + See :variable:`CMAKE_HOST_SYSTEM_PROCESSOR` + +``DISTRIB_INFO`` + .. versionadded:: 3.22 + + Read :file:`/etc/os-release` file and define the given ``<variable>`` + into a list of read variables + +``DISTRIB_<name>`` + .. versionadded:: 3.22 + + Get the ``<name>`` variable (see `man 5 os-release`_) if it exists in the + :file:`/etc/os-release` file + + Example: + + .. code-block:: cmake + + cmake_host_system_information(RESULT PRETTY_NAME QUERY DISTRIB_PRETTY_NAME) + message(STATUS "${PRETTY_NAME}") + + cmake_host_system_information(RESULT DISTRO QUERY DISTRIB_INFO) + + foreach(VAR IN LISTS DISTRO) + message(STATUS "${VAR}=`${${VAR}}`") + endforeach() + + + Output:: + + -- Ubuntu 20.04.2 LTS + -- DISTRO_BUG_REPORT_URL=`https://bugs.launchpad.net/ubuntu/` + -- DISTRO_HOME_URL=`https://www.ubuntu.com/` + -- DISTRO_ID=`ubuntu` + -- DISTRO_ID_LIKE=`debian` + -- DISTRO_NAME=`Ubuntu` + -- DISTRO_PRETTY_NAME=`Ubuntu 20.04.2 LTS` + -- DISTRO_PRIVACY_POLICY_URL=`https://www.ubuntu.com/legal/terms-and-policies/privacy-policy` + -- DISTRO_SUPPORT_URL=`https://help.ubuntu.com/` + -- DISTRO_UBUNTU_CODENAME=`focal` + -- DISTRO_VERSION=`20.04.2 LTS (Focal Fossa)` + -- DISTRO_VERSION_CODENAME=`focal` + -- DISTRO_VERSION_ID=`20.04` + +If :file:`/etc/os-release` file is not found, the command tries to gather OS +identification via fallback scripts. The fallback script can use `various +distribution-specific files`_ to collect OS identification data and map it +into `man 5 os-release`_ variables. + +Fallback Interface Variables +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. variable:: CMAKE_GET_OS_RELEASE_FALLBACK_SCRIPTS + + In addition to the scripts shipped with CMake, a user may append full + paths to his script(s) to the this list. The script filename has the + following format: ``NNN-<name>.cmake``, where ``NNN`` is three digits + used to apply collected scripts in a specific order. + +.. variable:: CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_<varname> + + Variables collected by the user provided fallback script + ought to be assigned to CMake variables using this naming + convention. Example, the ``ID`` variable from the manual becomes + ``CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID``. + +.. variable:: CMAKE_GET_OS_RELEASE_FALLBACK_RESULT + + The fallback script ought to store names of all assigned + ``CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_<varname>`` variables in this list. + +Example: + +.. code-block:: cmake + + # Try to detect some old distribution + # See also + # - http://linuxmafia.com/faq/Admin/release-files.html + # + if(NOT EXISTS "${CMAKE_SYSROOT}/etc/foobar-release") + return() + endif() + # Get the first string only + file( + STRINGS "${CMAKE_SYSROOT}/etc/foobar-release" CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT + LIMIT_COUNT 1 + ) + # + # Example: + # + # Foobar distribution release 1.2.3 (server) + # + if(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT MATCHES "Foobar distribution release ([0-9\.]+) .*") + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME Foobar) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME "${CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT}") + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID foobar) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION ${CMAKE_MATCH_1}) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID ${CMAKE_MATCH_1}) + list( + APPEND CMAKE_GET_OS_RELEASE_FALLBACK_RESULT + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID + ) + endif() + unset(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT) + .. rubric:: Footnotes .. [#mebibytes] One MiB (mebibyte) is equal to 1024x1024 bytes. + +.. _man 5 os-release: https://www.freedesktop.org/software/systemd/man/os-release.html +.. _various distribution-specific files: http://linuxmafia.com/faq/Admin/release-files.html diff --git a/Help/command/get_property.rst b/Help/command/get_property.rst index f77d8af..46da285 100644 --- a/Help/command/get_property.rst +++ b/Help/command/get_property.rst @@ -9,7 +9,7 @@ Get a property. <GLOBAL | DIRECTORY [<dir>] | TARGET <target> | - SOURCE <source> | + SOURCE <source> [DIRECTORY <dir> | TARGET_DIRECTORY <target>] | INSTALL <file> | TEST <test> | diff --git a/Help/command/set_property.rst b/Help/command/set_property.rst index bf437b4..555520d 100644 --- a/Help/command/set_property.rst +++ b/Help/command/set_property.rst @@ -9,8 +9,8 @@ Set a named property in a given scope. DIRECTORY [<dir>] | TARGET [<target1> ...] | SOURCE [<src1> ...] - [DIRECTORY <dirs> ...] | - [TARGET_DIRECTORY <targets> ...] + [DIRECTORY <dirs> ...] + [TARGET_DIRECTORY <targets> ...] | INSTALL [<file1> ...] | TEST [<test1> ...] | CACHE [<entry1> ...] > diff --git a/Help/release/dev/os-release.rst b/Help/release/dev/os-release.rst new file mode 100644 index 0000000..cce6aee --- /dev/null +++ b/Help/release/dev/os-release.rst @@ -0,0 +1,6 @@ +os-release +---------- + +* The :command:`cmake_host_system_information` command query operating system + identification `variables <https://www.freedesktop.org/software/systemd/man/os-release.html>`_ + from the :file:`/etc/os-release` file. diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index d0beac6..bb97f4a 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -165,9 +165,9 @@ else() # Prepend toolchain-specific names. if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL Clang) if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC") - set(_CMAKE_LINKER_NAMES "lld-link") + list(PREPEND _CMAKE_LINKER_NAMES "lld-link") else() - set(_CMAKE_LINKER_NAMES "ld.lld") + list(PREPEND _CMAKE_LINKER_NAMES "ld.lld") endif() list(PREPEND _CMAKE_AR_NAMES "llvm-ar") list(PREPEND _CMAKE_RANLIB_NAMES "llvm-ranlib") diff --git a/Modules/CheckCXXSymbolExists.cmake b/Modules/CheckCXXSymbolExists.cmake index b4da4fa..7b13c3a 100644 --- a/Modules/CheckCXXSymbolExists.cmake +++ b/Modules/CheckCXXSymbolExists.cmake @@ -25,7 +25,7 @@ Check if a symbol exists as a function, variable, or macro in ``C++``. as a function or variable then the symbol must also be available for linking. If the symbol is a type, enum value, or C++ template it will not be recognized: consider using the :module:`CheckTypeSize` - or :module:`CheckCXXSourceCompiles` module instead. + or :module:`CheckSourceCompiles` module instead. .. note:: diff --git a/Modules/CheckFortranFunctionExists.cmake b/Modules/CheckFortranFunctionExists.cmake index ad72e2f..8f1ca9d 100644 --- a/Modules/CheckFortranFunctionExists.cmake +++ b/Modules/CheckFortranFunctionExists.cmake @@ -20,6 +20,12 @@ Check if a Fortran function exists. ``<result>`` variable to store the result; will be created as an internal cache variable. +.. note:: + + This command does not detect functions in Fortran modules. In general it is + recommended to use :module:`CheckSourceCompiles` instead to determine if a + Fortran function or subroutine is available. + The following variables may be set before calling this macro to modify the way the check is run: diff --git a/Modules/CheckLanguage.cmake b/Modules/CheckLanguage.cmake index 928881c..559c103 100644 --- a/Modules/CheckLanguage.cmake +++ b/Modules/CheckLanguage.cmake @@ -36,6 +36,9 @@ Example: include_guard(GLOBAL) +cmake_policy(PUSH) +cmake_policy(SET CMP0126 NEW) + macro(check_language lang) if(NOT DEFINED CMAKE_${lang}_COMPILER) set(_desc "Looking for a ${lang} compiler") @@ -110,3 +113,5 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\" endif() endmacro() + +cmake_policy(POP) diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake index f8ca584..48ee3c4 100644 --- a/Modules/CheckSymbolExists.cmake +++ b/Modules/CheckSymbolExists.cmake @@ -24,7 +24,7 @@ available and assumed to work. If the header files declare the symbol as a function or variable then the symbol must also be available for linking (so intrinsics may not be detected). If the symbol is a type, enum value, or intrinsic it will not be recognized -(consider using :module:`CheckTypeSize` or :module:`CheckCSourceCompiles`). +(consider using :module:`CheckTypeSize` or :module:`CheckSourceCompiles`). If the check needs to be done in C++, consider using :module:`CheckCXXSymbolExists` instead. diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index bd82a90..5ea8b2a 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -21,13 +21,14 @@ supported by the :module:`ExternalProject` module. Whereas 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. 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. +Content population details should be defined separately from the command that +performs the actual population. This separation ensures that all the +dependency details are defined before anything might try to use them 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: +The following shows a typical example of declaring content details for some +dependencies and then ensuring they are populated with a separate call: .. code-block:: cmake @@ -36,57 +37,67 @@ The following shows a typical example of declaring content details: GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG 703bd9caab50b139428cea1aaff9974ebee5742e # release-1.10.0 ) + FetchContent_Declare( + myCompanyIcons + URL https://intranet.mycompany.com/assets/iconset_1.12.tar.gz + URL_HASH MD5=5588a7b18261c20068beabfb4f530b87 + ) + + FetchContent_MakeAvailable(googletest secret_sauce) + +The :command:`FetchContent_MakeAvailable` command ensures the named +dependencies have been populated, either by an earlier call or by populating +them itself. When performing the population, it will also add them to the +main build, if possible, so that the main build can use the populated +projects' targets, etc. See the command's documentation for how these steps +are performed. + +When using a hierarchical project arrangement, projects at higher levels in +the hierarchy are able to override the declared details of content specified +anywhere lower in the project hierarchy. The first details to be declared +for a given dependency take precedence, regardless of where in the project +hierarchy that occurs. Similarly, the first call that tries to populate a +dependency "wins", with subsequent populations reusing the result of the +first instead of repeating the population again. +See the :ref:`Examples <fetch-content-examples>` which demonstrate +this scenario. -For most typical cases, populating the content can then be done with a single -command like so: +In some cases, the main project may need to have more precise control over +the population, or it may be required to explicitly define the population +steps in a way that cannot be captured by the declared details alone. +For such situations, the lower level :command:`FetchContent_GetProperties` and +:command:`FetchContent_Populate` commands can be used. These lack the richer +features provided by :command:`FetchContent_MakeAvailable` though, so their +direct use should be considered a last resort. The typical pattern of such +custom steps looks like this: .. code-block:: cmake - FetchContent_MakeAvailable(googletest) + # NOTE: Where possible, prefer to use FetchContent_MakeAvailable() + # instead of custom logic like this -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: + # Check if population has already been performed + FetchContent_GetProperties(depname) + if(NOT depname_POPULATED) + # Fetch the content using previously declared details + FetchContent_Populate(depname) -.. code-block:: cmake + # Set custom variables, policies, etc. + # ... - FetchContent_GetProperties(googletest) - if(NOT googletest_POPULATED) - FetchContent_Populate(googletest) - add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR}) + # Bring the populated content into the build + add_subdirectory(${depname_SOURCE_DIR} ${depname_BINARY_DIR}) endif() -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 content in a single call, with no check for whether the content has been -populated elsewhere in the project already. This is a more low level -operation and would not normally be the way the module is used, but it is -sometimes useful as part of implementing some higher level feature or to -populate some content in CMake's script mode. - -.. versionchanged:: 3.14 - ``FetchContent`` commands can access the terminal. This is necessary - for password prompts and real-time progress displays to work. +populated elsewhere already. This should not be done in projects, but may +be appropriate for populating content in CMake's script mode. +See :command:`FetchContent_Populate` for details. Commands ^^^^^^^^ -Declaring Content Details -""""""""""""""""""""""""" - .. command:: FetchContent_Declare .. code-block:: cmake @@ -94,7 +105,7 @@ Declaring Content Details FetchContent_Declare(<name> <contentOptions>...) The ``FetchContent_Declare()`` function records the options that describe - how to populate the specified content, but if such details have already + how to populate the specified content. If such details have already been recorded earlier in this project (regardless of where in the project hierarchy), this and all later calls for the same content ``<name>`` are ignored. This "first to record, wins" approach is what allows hierarchical @@ -110,7 +121,7 @@ Declaring Content Details projects needing that same content will use the same name, leading to the content being populated multiple times. - The ``<contentOptions>`` can be any of the download or update/patch options + The ``<contentOptions>`` can be any of the download, update or patch options that the :command:`ExternalProject_Add` command understands. The configure, build, install and test steps are explicitly disabled and therefore options related to them will be ignored. The ``SOURCE_SUBDIR`` option is an @@ -146,47 +157,88 @@ Declaring Content Details than a branch or tag name. A commit hash is more secure and helps to confirm that the downloaded contents are what you expected. -Populating The Content -"""""""""""""""""""""" + .. versionchanged:: 3.14 + Commands for the download, update or patch steps can access the terminal. + This may be needed for things like password prompts or real-time display + of command progress. -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: +.. command:: FetchContent_MakeAvailable -.. _`fetch-content-canonical-pattern`: + .. versionadded:: 3.14 -.. code-block:: cmake + .. 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>) + FetchContent_MakeAvailable(<name1> [<name2>...]) + + This command ensures that each of the named dependencies are populated and + potentially added to the build by the time it returns. It iterates over + the list, and for each dependency, the following logic is applied: + + * If the dependency has already been populated earlier in this run, set + the ``<lowercaseName>_POPULATED``, ``<lowercaseName>_SOURCE_DIR`` and + ``<lowercaseName>_BINARY_DIR`` variables in the same way as a call to + :command:`FetchContent_GetProperties`, then skip the remaining steps + below and move on to the next dependency in the list. + + * Call :command:`FetchContent_Populate` to populate the dependency using + the details recorded by an earlier call to :command:`FetchContent_Declare`. + Halt with a fatal error if no such details have been recorded. + :variable:`FETCHCONTENT_SOURCE_DIR_<uppercaseName>` can be used to override + the declared details and use content provided at the specified location + instead. + + * If the top directory of the populated content contains a ``CMakeLists.txt`` + file, call :command:`add_subdirectory` to add it to the main build. + It is not an error for there to be no ``CMakeLists.txt`` file, which + 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. + + .. versionadded:: 3.18 + The ``SOURCE_SUBDIR`` option can be given in the declared details to + look somewhere below the top directory instead (i.e. the same way that + ``SOURCE_SUBDIR`` is used by the :command:`ExternalProject_Add` + command). The path provided with ``SOURCE_SUBDIR`` must be relative + and will be treated as relative to the top directory. It can also + point to a directory that does not contain a ``CMakeLists.txt`` file + or even to a directory that doesn't exist. This can be used to avoid + adding a project that contains a ``CMakeLists.txt`` file in its top + directory. + + Projects should aim to declare the details of all dependencies they might + use before they call ``FetchContent_MakeAvailable()`` for any of them. + This ensures that if any of the dependencies are also sub-dependencies of + one or more of the others, the main project still controls the details + that will be used (because it will declare them first before the + dependencies get a chance to). In the following code samples, assume that + the ``uses_other`` dependency also uses ``FetchContent`` to add the ``other`` + dependency internally: - # Set custom variables, policies, etc. - # ... + .. code-block:: cmake - # Bring the populated content into the build - add_subdirectory(${${lcName}_SOURCE_DIR} ${${lcName}_BINARY_DIR}) - endif() + # WRONG: Should declare all details first + FetchContent_Declare(uses_other ...) + FetchContent_MakeAvailable(uses_other) + + FetchContent_Declare(other ...) # Will be ignored, uses_other beat us to it + FetchContent_MakeAvailable(other) # Would use details declared by uses_other -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. Where it meets the needs of -the project, :command:`FetchContent_MakeAvailable` should be preferred, as it -is simpler and provides additional features over the pattern above. + .. code-block:: cmake + + # CORRECT: All details declared first, so they will take priority + FetchContent_Declare(uses_other ...) + FetchContent_Declare(other ...) + FetchContent_MakeAvailable(uses_other other) .. command:: FetchContent_Populate + .. note:: + Where possible, prefer to use :command:`FetchContent_MakeAvailable` + instead of implementing population manually with this command. + .. code-block:: cmake - FetchContent_Populate( <name> ) + FetchContent_Populate(<name>) In most cases, the only argument given to ``FetchContent_Populate()`` is the ``<name>``. When used this way, the command assumes the content details have @@ -211,88 +263,29 @@ is simpler and provides additional features over the pattern above. ``FetchContent_Populate()``. ``FetchContent_Populate()`` will set three variables in the scope of the - caller; ``<lcName>_POPULATED``, ``<lcName>_SOURCE_DIR`` and - ``<lcName>_BINARY_DIR``, where ``<lcName>`` is the lowercased ``<name>``. - ``<lcName>_POPULATED`` will always be set to ``True`` by the call. - ``<lcName>_SOURCE_DIR`` is the location where the - content can be found upon return (it will have already been populated), while - ``<lcName>_BINARY_DIR`` is a directory intended for use as a corresponding - build directory. The main use case for the two directory variables is to - call :command:`add_subdirectory` immediately after population, i.e.: + caller: + + ``<lowercaseName>_POPULATED`` + This will always be set to ``TRUE`` by the call. + + ``<lowercaseName>_SOURCE_DIR`` + The location where the populated content can be found upon return. + + ``<lowercaseName>_BINARY_DIR`` + A directory intended for use as a corresponding build directory. + + The main use case for the ``<lowercaseName>_SOURCE_DIR`` and + ``<lowercaseName>_BINARY_DIR`` variables is to call + :command:`add_subdirectory` immediately after population: .. code-block:: cmake - FetchContent_Populate(FooBar ...) + FetchContent_Populate(FooBar) add_subdirectory(${foobar_SOURCE_DIR} ${foobar_BINARY_DIR}) The values of the three variables can also be retrieved from anywhere in the project hierarchy using the :command:`FetchContent_GetProperties` command. - A number of cache variables influence the behavior of all content population - performed using details saved from a :command:`FetchContent_Declare` call: - - ``FETCHCONTENT_BASE_DIR`` - In most cases, the saved details do not specify any options relating to the - directories to use for the internal sub-build, final source and build areas. - It is generally best to leave these decisions up to the ``FetchContent`` - module to handle on the project's behalf. The ``FETCHCONTENT_BASE_DIR`` - cache variable controls the point under which all content population - directories are collected, but in most cases developers would not need to - change this. The default location is ``${CMAKE_BINARY_DIR}/_deps``, but if - developers change this value, they should aim to keep the path short and - just below the top level of the build tree to avoid running into path - length problems on Windows. - - ``FETCHCONTENT_QUIET`` - The logging output during population can be quite verbose, making the - configure stage quite noisy. This cache option (``ON`` by default) hides - all population output unless an error is encountered. If experiencing - problems with hung downloads, temporarily switching this option off may - help diagnose which content population is causing the issue. - - ``FETCHCONTENT_FULLY_DISCONNECTED`` - When this option is enabled, no attempt is made to download or update - any content. It is assumed that all content has already been populated in - a previous run or the source directories have been pointed at existing - contents the developer has provided manually (using options described - further below). When the developer knows that no changes have been made to - any content details, turning this option ``ON`` can significantly speed up - the configure stage. It is ``OFF`` by default. - - ``FETCHCONTENT_UPDATES_DISCONNECTED`` - This is a less severe download/update control compared to - ``FETCHCONTENT_FULLY_DISCONNECTED``. Instead of bypassing all download and - update logic, the ``FETCHCONTENT_UPDATES_DISCONNECTED`` only disables the - update stage. Therefore, if content has not been downloaded previously, - it will still be downloaded when this option is enabled. This can speed up - the configure stage, but not as much as - ``FETCHCONTENT_FULLY_DISCONNECTED``. It is ``OFF`` by default. - - In addition to the above cache variables, the following cache variables are - also defined for each content name (``<ucName>`` is the uppercased value of - ``<name>``): - - ``FETCHCONTENT_SOURCE_DIR_<ucName>`` - If this is set, no download or update steps are performed for the specified - content and the ``<lcName>_SOURCE_DIR`` variable returned to the caller is - pointed at this location. This gives developers a way to have a separate - checkout of the content that they can modify freely without interference - from the build. The build simply uses that existing source, but it still - defines ``<lcName>_BINARY_DIR`` to point inside its own build area. - Developers are strongly encouraged to use this mechanism rather than - editing the sources populated in the default location, as changes to - sources in the default location can be lost when content population details - are changed by the project. - - ``FETCHCONTENT_UPDATES_DISCONNECTED_<ucName>`` - This is the per-content equivalent of - ``FETCHCONTENT_UPDATES_DISCONNECTED``. If the global option or this option - is ``ON``, then updates will be disabled for the named content. - Disabling updates for individual content can be useful for content whose - details rarely change, while still leaving other frequently changing - content with updates enabled. - - The ``FetchContent_Populate()`` command also supports a syntax allowing the content details to be specified directly rather than using any saved details. This is more low-level and use of this form is generally to be @@ -303,7 +296,8 @@ is simpler and provides additional features over the pattern above. .. code-block:: cmake - FetchContent_Populate( <name> + FetchContent_Populate( + <name> [QUIET] [SUBBUILD_DIR <subBuildDir>] [SOURCE_DIR <srcDir>] @@ -325,16 +319,17 @@ is simpler and provides additional features over the pattern above. - The ``FETCHCONTENT_FULLY_DISCONNECTED`` and ``FETCHCONTENT_UPDATES_DISCONNECTED`` cache variables are ignored. - The ``<lcName>_SOURCE_DIR`` and ``<lcName>_BINARY_DIR`` variables are still - returned to the caller, but since these locations are not stored as global - properties when this form is used, they are only available to the calling - scope and below rather than the entire project hierarchy. No - ``<lcName>_POPULATED`` variable is set in the caller's scope with this form. + The ``<lowercaseName>_SOURCE_DIR`` and ``<lowercaseName>_BINARY_DIR`` + variables are still returned to the caller, but since these locations are + not stored as global properties when this form is used, they are only + available to the calling scope and below rather than the entire project + hierarchy. No ``<lowercaseName>_POPULATED`` variable is set in the caller's + scope with this form. The supported options for ``FetchContent_Populate()`` are the same as those for :command:`FetchContent_Declare()`. Those few options shown just above are either specific to ``FetchContent_Populate()`` or their behavior is - slightly modified from how :command:`ExternalProject_Add` treats them. + slightly modified from how :command:`ExternalProject_Add` treats them: ``QUIET`` The ``QUIET`` option can be given to hide the output associated with @@ -347,9 +342,9 @@ is simpler and provides additional features over the pattern above. ``SUBBUILD_DIR`` The ``SUBBUILD_DIR`` argument can be provided to change the location of the sub-build created to perform the population. The default value is - ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-subbuild`` and it would be unusual - to need to override this default. If a relative path is specified, it will - be interpreted as relative to :variable:`CMAKE_CURRENT_BINARY_DIR`. + ``${CMAKE_CURRENT_BINARY_DIR}/<lowercaseName>-subbuild`` and it would be + unusual to need to override this default. If a relative path is specified, + it will be interpreted as relative to :variable:`CMAKE_CURRENT_BINARY_DIR`. This option should not be confused with the ``SOURCE_SUBDIR`` option which only affects the :command:`FetchContent_MakeAvailable` command. @@ -357,9 +352,9 @@ is simpler and provides additional features over the pattern above. The ``SOURCE_DIR`` and ``BINARY_DIR`` arguments are supported by :command:`ExternalProject_Add`, but different default values are used by ``FetchContent_Populate()``. ``SOURCE_DIR`` defaults to - ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-src`` and ``BINARY_DIR`` defaults to - ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-build``. If a relative path is - specified, it will be interpreted as relative to + ``${CMAKE_CURRENT_BINARY_DIR}/<lowercaseName>-src`` and ``BINARY_DIR`` + defaults to ``${CMAKE_CURRENT_BINARY_DIR}/<lowercaseName>-build``. + If a relative path is specified, it will be interpreted as relative to :variable:`CMAKE_CURRENT_BINARY_DIR`. In addition to the above explicit options, any other unrecognized options are @@ -380,11 +375,12 @@ is simpler and provides additional features over the pattern above. on the command line invoking the script. .. versionadded:: 3.18 - Added support for ``DOWNLOAD_NO_EXTRACT`` and ``SOURCE_SUBDIR`` options. + Added support for the ``DOWNLOAD_NO_EXTRACT`` option. .. command:: FetchContent_GetProperties - When using saved content details, a call to :command:`FetchContent_Populate` + When using saved content details, a call to + :command:`FetchContent_MakeAvailable` or :command:`FetchContent_Populate` records information in global properties which can be queried at any time. This information includes the source and binary directories associated with the content and also whether or not the content population has been processed @@ -392,7 +388,8 @@ is simpler and provides additional features over the pattern above. .. code-block:: cmake - FetchContent_GetProperties( <name> + FetchContent_GetProperties( + <name> [SOURCE_DIR <srcDirVar>] [BINARY_DIR <binDirVar>] [POPULATED <doneVar>] @@ -403,49 +400,104 @@ is simpler and provides additional features over the pattern above. which is the name of the variable in which to store that property. Most of the time though, only ``<name>`` is given, in which case the call will then set the same variables as a call to - :command:`FetchContent_Populate(name) <FetchContent_Populate>`. This allows - the following canonical pattern to be used, which ensures that the relevant - variables will always be defined regardless of whether or not the population - has been performed elsewhere in the project already: - - .. code-block:: cmake - - FetchContent_GetProperties(foobar) - if(NOT foobar_POPULATED) - FetchContent_Populate(foobar) - ... - endif() + :command:`FetchContent_MakeAvailable(name) <FetchContent_MakeAvailable>` or + :command:`FetchContent_Populate(name) <FetchContent_Populate>`. - 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 + This command is rarely needed when using + :command:`FetchContent_MakeAvailable`. It is more commonly used as part of + implementing the following pattern with :command:`FetchContent_Populate`, + which ensures that the relevant variables will always be defined regardless + of whether or not the population has been performed elsewhere in the project + already: .. code-block:: cmake - FetchContent_MakeAvailable( <name1> [<name2>...] ) + # Check if population has already been performed + FetchContent_GetProperties(depname) + if(NOT depname_POPULATED) + # Fetch the content using previously declared details + FetchContent_Populate(depname) - .. versionadded:: 3.14 + # Set custom variables, policies, etc. + # ... - 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 - :ref:`canonical pattern <fetch-content-canonical-pattern>` as - presented at the beginning of this section. An important difference is - that :command:`add_subdirectory` will only be called 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. - - The ``SOURCE_SUBDIR`` option can be given in the declared details to - instruct ``FetchContent_MakeAvailable()`` to look for a ``CMakeLists.txt`` - file in a subdirectory below the top level (i.e. the same way that - ``SOURCE_SUBDIR`` is used by the :command:`ExternalProject_Add` command). - ``SOURCE_SUBDIR`` must always be a relative path. See the next section - for an example of this option. + # Bring the populated content into the build + add_subdirectory(${depname_SOURCE_DIR} ${depname_BINARY_DIR}) + endif() +Variables +^^^^^^^^^ + +A number of cache variables can influence the behavior where details from a +:command:`FetchContent_Declare` call are used to populate content. +The variables are all intended for the developer to customize behavior and +should not normally be set by the project. + +.. variable:: FETCHCONTENT_BASE_DIR + + In most cases, the saved details do not specify any options relating to the + directories to use for the internal sub-build, final source and build areas. + It is generally best to leave these decisions up to the ``FetchContent`` + module to handle on the project's behalf. The ``FETCHCONTENT_BASE_DIR`` + cache variable controls the point under which all content population + directories are collected, but in most cases, developers would not need to + change this. The default location is ``${CMAKE_BINARY_DIR}/_deps``, but if + developers change this value, they should aim to keep the path short and + just below the top level of the build tree to avoid running into path + length problems on Windows. + +.. variable:: FETCHCONTENT_QUIET + + The logging output during population can be quite verbose, making the + configure stage quite noisy. This cache option (``ON`` by default) hides + all population output unless an error is encountered. If experiencing + problems with hung downloads, temporarily switching this option off may + help diagnose which content population is causing the issue. + +.. variable:: FETCHCONTENT_FULLY_DISCONNECTED + + When this option is enabled, no attempt is made to download or update + any content. It is assumed that all content has already been populated in + a previous run or the source directories have been pointed at existing + contents the developer has provided manually (using options described + further below). When the developer knows that no changes have been made to + any content details, turning this option ``ON`` can significantly speed up + the configure stage. It is ``OFF`` by default. + +.. variable:: FETCHCONTENT_UPDATES_DISCONNECTED + + This is a less severe download/update control compared to + :variable:`FETCHCONTENT_FULLY_DISCONNECTED`. Instead of bypassing all + download and update logic, ``FETCHCONTENT_UPDATES_DISCONNECTED`` only + disables the update stage. Therefore, if content has not been downloaded + previously, it will still be downloaded when this option is enabled. + This can speed up the configure stage, but not as much as + :variable:`FETCHCONTENT_FULLY_DISCONNECTED`. It is ``OFF`` by default. + +In addition to the above cache variables, the following cache variables are +also defined for each content name: + +.. variable:: FETCHCONTENT_SOURCE_DIR_<uppercaseName> + + If this is set, no download or update steps are performed for the specified + content and the ``<lowercaseName>_SOURCE_DIR`` variable returned to the + caller is pointed at this location. This gives developers a way to have a + separate checkout of the content that they can modify freely without + interference from the build. The build simply uses that existing source, + but it still defines ``<lowercaseName>_BINARY_DIR`` to point inside its own + build area. Developers are strongly encouraged to use this mechanism rather + than editing the sources populated in the default location, as changes to + sources in the default location can be lost when content population details + are changed by the project. + +.. variable:: FETCHCONTENT_UPDATES_DISCONNECTED_<uppercaseName> + + This is the per-content equivalent of + :variable:`FETCHCONTENT_UPDATES_DISCONNECTED`. If the global option or + this option is ``ON``, then updates will be disabled for the named content. + Disabling updates for individual content can be useful for content whose + details rarely change, while still leaving other frequently changing content + with updates enabled. .. _`fetch-content-examples`: @@ -470,7 +522,7 @@ frameworks are available to the main build: ) # After the following call, the CMake targets defined by googletest and - # Catch2 will be defined and available to the rest of the build + # Catch2 will be available to the rest of the build FetchContent_MakeAvailable(googletest Catch2) If the sub-project's ``CMakeLists.txt`` file is not at the top level of its diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index f64c4b8..d4b4a34 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -649,7 +649,8 @@ function (_MPI_interrogate_compiler LANG) # we won't match the accompanying --param-ssp-size and -Wp,-D_FORTIFY_SOURCE flags and therefore # produce inconsistent results with the regularly flags. # Similarly, aliasing flags do not belong into our flag array. - if(NOT "${_MPI_COMPILE_OPTION}" MATCHES "^-f((no-|)(stack-protector|strict-aliasing)|PI[CE]|pi[ce])") + # Also strip out `-framework` flags. + if(NOT "${_MPI_COMPILE_OPTION}" MATCHES "^-f((no-|)(stack-protector|strict-aliasing)|PI[CE]|pi[ce]|ramework)") list(APPEND MPI_COMPILE_OPTIONS_WORK "${_MPI_COMPILE_OPTION}") endif() endforeach() diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index a28f6bc..4de5331 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -97,10 +97,18 @@ set(PKG_CONFIG_FOUND "${PKGCONFIG_FOUND}") # Unsets the given variables macro(_pkgconfig_unset var) + # Clear normal variable (possibly set by project code). + unset(${var}) + # Store as cache variable. + # FIXME: Add a policy to switch to a normal variable. set(${var} "" CACHE INTERNAL "") endmacro() macro(_pkgconfig_set var value) + # Clear normal variable (possibly set by project code). + unset(${var}) + # Store as cache variable. + # FIXME: Add a policy to switch to a normal variable. set(${var} ${value} CACHE INTERNAL "") endmacro() diff --git a/Modules/Internal/OSRelease/010-TryOldCentOS.cmake b/Modules/Internal/OSRelease/010-TryOldCentOS.cmake new file mode 100644 index 0000000..ff35897 --- /dev/null +++ b/Modules/Internal/OSRelease/010-TryOldCentOS.cmake @@ -0,0 +1,41 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# Author: Alex Turbov + +if(NOT EXISTS "${CMAKE_SYSROOT}/etc/centos-release") + return() +endif() + +# Get the first string only +file( + STRINGS "${CMAKE_SYSROOT}/etc/centos-release" CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT + LIMIT_COUNT 1 + ) + +# +# Example: +# CentOS release 6.10 (Final) +# +if(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT MATCHES "CentOS release ([0-9\.]+) .*") + + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME CentOS) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME "${CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT}") + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID centos) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID_LIKE rhel) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION ${CMAKE_MATCH_1}) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID ${CMAKE_MATCH_1}) + + list( + APPEND CMAKE_GET_OS_RELEASE_FALLBACK_RESULT + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID_LIKE + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID + ) + +endif() + +unset(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT) diff --git a/Modules/Internal/OSRelease/020-TryDebianVersion.cmake b/Modules/Internal/OSRelease/020-TryDebianVersion.cmake new file mode 100644 index 0000000..8ebe19a --- /dev/null +++ b/Modules/Internal/OSRelease/020-TryDebianVersion.cmake @@ -0,0 +1,38 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# Author: Alex Turbov + +if(NOT EXISTS "${CMAKE_SYSROOT}/etc/debian_version") + return() +endif() + +# Get the first string only +file( + STRINGS "${CMAKE_SYSROOT}/etc/debian_version" CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT + LIMIT_COUNT 1 + ) + +# +# Example: +# 6.0.10 # Old debian +# wheezy/sid # Ubuntu +# +if(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT MATCHES "[0-9]+(\.[0-9]+)*") + + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME Debian) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID debian) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION ${CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT}) + set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID ${CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT}) + + list( + APPEND CMAKE_GET_OS_RELEASE_FALLBACK_RESULT + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID + ) + +endif() + +unset(CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT) diff --git a/Modules/Platform/Android-Determine.cmake b/Modules/Platform/Android-Determine.cmake index 2d2cd5c..7b67f83 100644 --- a/Modules/Platform/Android-Determine.cmake +++ b/Modules/Platform/Android-Determine.cmake @@ -267,7 +267,7 @@ endif() if(CMAKE_ANDROID_NDK) # Identify the host platform. if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") - if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64") + if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "64") set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "darwin-x86_64") else() set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "darwin-x86") diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 791871e..7e37141 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -399,8 +399,6 @@ set(SRCS cmQtAutoMocUic.h cmQtAutoRcc.cxx cmQtAutoRcc.h - cmQtAutoUicHelpers.cxx - cmQtAutoUicHelpers.h cmRST.cxx cmRST.h cmRuntimeDependencyArchive.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d13d285..d10822f 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210819) +set(CMake_VERSION_PATCH 20210824) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 5f0f153..829cef4 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -192,7 +192,13 @@ bool DebGenerator::generateDataTar() const cmArchiveWrite data_tar(fileStream_data_tar, this->TarCompressionType, this->DebianArchiveType, 0, static_cast<int>(this->NumThreads)); - data_tar.Open(); + if (!data_tar.Open()) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error opening the archive \"" + << filename_data_tar + << "\", ERROR = " << data_tar.GetError() << std::endl); + return false; + } // uid/gid should be the one of the root user, and this root user has // always uid/gid equal to 0. @@ -317,7 +323,13 @@ bool DebGenerator::generateControlTar(std::string const& md5Filename) const cmArchiveWrite control_tar(fileStream_control_tar, cmArchiveWrite::CompressGZip, this->DebianArchiveType); - control_tar.Open(); + if (!control_tar.Open()) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error opening the archive \"" + << filename_control_tar + << "\", ERROR = " << control_tar.GetError() << std::endl); + return false; + } // sets permissions and uid/gid for the files control_tar.SetUIDAndGID(0u, 0u); @@ -457,7 +469,13 @@ bool DebGenerator::generateDeb() const cmGeneratedFileStream debStream; debStream.Open(outputPath, false, true); cmArchiveWrite deb(debStream, cmArchiveWrite::CompressNone, "arbsd"); - deb.Open(); + if (!deb.Open()) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error opening the archive \"" + << outputPath << "\", ERROR = " << deb.GetError() + << std::endl); + return false; + } // uid/gid should be the one of the root user, and this root user has // always uid/gid equal to 0. diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index 54b2998..9e0d80c 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -250,6 +250,9 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c, bool cmArchiveWrite::Open() { + if (!this->Error.empty()) { + return false; + } if (archive_write_open( this->Archive, this, nullptr, reinterpret_cast<archive_write_callback*>(&Callback::Write), diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 0550568..74071ff 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -2,214 +2,510 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCMakeHostSystemInformationCommand.h" -#include <cstddef> +#include <algorithm> +#include <cassert> +#include <cctype> +#include <initializer_list> +#include <map> +#include <string> +#include <type_traits> +#include <utility> +#include <cm/optional> +#include <cm/string_view> +#include <cmext/string_view> + +#include "cmsys/FStream.hxx" +#include "cmsys/Glob.hxx" #include "cmsys/SystemInformation.hxx" #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" -#if defined(_WIN32) +#ifdef _WIN32 # include "cmAlgorithms.h" # include "cmGlobalGenerator.h" # include "cmGlobalVisualStudioVersionedGenerator.h" -# include "cmSystemTools.h" # include "cmVSSetupHelper.h" # define HAVE_VS_SETUP_HELPER #endif namespace { -bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info, - std::string const& key, std::string& value); -std::string ValueToString(size_t value); -std::string ValueToString(const char* value); -std::string ValueToString(std::string const& value); -} +std::string const DELIM[2] = { {}, ";" }; -// cmCMakeHostSystemInformation -bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, - cmExecutionStatus& status) +// BEGIN Private functions +std::string ValueToString(std::size_t const value) { - size_t current_index = 0; - - if (args.size() < (current_index + 2) || args[current_index] != "RESULT") { - status.SetError("missing RESULT specification."); - return false; - } - - std::string const& variable = args[current_index + 1]; - current_index += 2; - - if (args.size() < (current_index + 2) || args[current_index] != "QUERY") { - status.SetError("missing QUERY specification"); - return false; - } - - cmsys::SystemInformation info; - info.RunCPUCheck(); - info.RunOSCheck(); - info.RunMemoryCheck(); - - std::string result_list; - for (size_t i = current_index + 1; i < args.size(); ++i) { - std::string const& key = args[i]; - if (i != current_index + 1) { - result_list += ";"; - } - std::string value; - if (!GetValue(status, info, key, value)) { - return false; - } - result_list += value; - } - - status.GetMakefile().AddDefinition(variable, result_list); + return std::to_string(value); +} - return true; +std::string ValueToString(const char* const value) +{ + return value ? value : std::string{}; } -namespace { +std::string ValueToString(std::string const& value) +{ + return value; +} -bool GetValue(cmExecutionStatus& status, cmsys::SystemInformation& info, - std::string const& key, std::string& value) +cm::optional<std::string> GetValue(cmsys::SystemInformation& info, + std::string const& key) { - if (key == "NUMBER_OF_LOGICAL_CORES") { - value = ValueToString(info.GetNumberOfLogicalCPU()); - } else if (key == "NUMBER_OF_PHYSICAL_CORES") { - value = ValueToString(info.GetNumberOfPhysicalCPU()); - } else if (key == "HOSTNAME") { - value = ValueToString(info.GetHostname()); - } else if (key == "FQDN") { - value = ValueToString(info.GetFullyQualifiedDomainName()); - } else if (key == "TOTAL_VIRTUAL_MEMORY") { - value = ValueToString(info.GetTotalVirtualMemory()); - } else if (key == "AVAILABLE_VIRTUAL_MEMORY") { - value = ValueToString(info.GetAvailableVirtualMemory()); - } else if (key == "TOTAL_PHYSICAL_MEMORY") { - value = ValueToString(info.GetTotalPhysicalMemory()); - } else if (key == "AVAILABLE_PHYSICAL_MEMORY") { - value = ValueToString(info.GetAvailablePhysicalMemory()); - } else if (key == "IS_64BIT") { - value = ValueToString(info.Is64Bits()); - } else if (key == "HAS_FPU") { - value = ValueToString( + if (key == "NUMBER_OF_LOGICAL_CORES"_s) { + return ValueToString(info.GetNumberOfLogicalCPU()); + } + if (key == "NUMBER_OF_PHYSICAL_CORES"_s) { + return ValueToString(info.GetNumberOfPhysicalCPU()); + } + if (key == "HOSTNAME"_s) { + return ValueToString(info.GetHostname()); + } + if (key == "FQDN"_s) { + return ValueToString(info.GetFullyQualifiedDomainName()); + } + if (key == "TOTAL_VIRTUAL_MEMORY"_s) { + return ValueToString(info.GetTotalVirtualMemory()); + } + if (key == "AVAILABLE_VIRTUAL_MEMORY"_s) { + return ValueToString(info.GetAvailableVirtualMemory()); + } + if (key == "TOTAL_PHYSICAL_MEMORY"_s) { + return ValueToString(info.GetTotalPhysicalMemory()); + } + if (key == "AVAILABLE_PHYSICAL_MEMORY"_s) { + return ValueToString(info.GetAvailablePhysicalMemory()); + } + if (key == "IS_64BIT"_s) { + return ValueToString(info.Is64Bits()); + } + if (key == "HAS_FPU"_s) { + return ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_FPU)); - } else if (key == "HAS_MMX") { - value = ValueToString( + } + if (key == "HAS_MMX"_s) { + return ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_MMX)); - } else if (key == "HAS_MMX_PLUS") { - value = ValueToString(info.DoesCPUSupportFeature( + } + if (key == "HAS_MMX_PLUS"_s) { + return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_MMX_PLUS)); - } else if (key == "HAS_SSE") { - value = ValueToString( + } + if (key == "HAS_SSE"_s) { + return ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE)); - } else if (key == "HAS_SSE2") { - value = ValueToString( + } + if (key == "HAS_SSE2"_s) { + return ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_SSE2)); - } else if (key == "HAS_SSE_FP") { - value = ValueToString(info.DoesCPUSupportFeature( + } + if (key == "HAS_SSE_FP"_s) { + return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_SSE_FP)); - } else if (key == "HAS_SSE_MMX") { - value = ValueToString(info.DoesCPUSupportFeature( + } + if (key == "HAS_SSE_MMX"_s) { + return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_SSE_MMX)); - } else if (key == "HAS_AMD_3DNOW") { - value = ValueToString(info.DoesCPUSupportFeature( + } + if (key == "HAS_AMD_3DNOW"_s) { + return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW)); - } else if (key == "HAS_AMD_3DNOW_PLUS") { - value = ValueToString(info.DoesCPUSupportFeature( + } + if (key == "HAS_AMD_3DNOW_PLUS"_s) { + return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_AMD_3DNOW_PLUS)); - } else if (key == "HAS_IA64") { - value = ValueToString( + } + if (key == "HAS_IA64"_s) { + return ValueToString( info.DoesCPUSupportFeature(cmsys::SystemInformation::CPU_FEATURE_IA64)); - } else if (key == "HAS_SERIAL_NUMBER") { - value = ValueToString(info.DoesCPUSupportFeature( + } + if (key == "HAS_SERIAL_NUMBER"_s) { + return ValueToString(info.DoesCPUSupportFeature( cmsys::SystemInformation::CPU_FEATURE_SERIALNUMBER)); - } else if (key == "PROCESSOR_NAME") { - value = ValueToString(info.GetExtendedProcessorName()); - } else if (key == "PROCESSOR_DESCRIPTION") { - value = info.GetCPUDescription(); - } else if (key == "PROCESSOR_SERIAL_NUMBER") { - value = ValueToString(info.GetProcessorSerialNumber()); - } else if (key == "OS_NAME") { - value = ValueToString(info.GetOSName()); - } else if (key == "OS_RELEASE") { - value = ValueToString(info.GetOSRelease()); - } else if (key == "OS_VERSION") { - value = ValueToString(info.GetOSVersion()); - } else if (key == "OS_PLATFORM") { - value = ValueToString(info.GetOSPlatform()); -#ifdef HAVE_VS_SETUP_HELPER - } else if (key == "VS_15_DIR") { - // If generating for the VS 15 IDE, use the same instance. - cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator(); - if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 15 ")) { - cmGlobalVisualStudioVersionedGenerator* vs15gen = - static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); - if (vs15gen->GetVSInstance(value)) { - return true; - } + } + if (key == "PROCESSOR_NAME"_s) { + return ValueToString(info.GetExtendedProcessorName()); + } + if (key == "PROCESSOR_DESCRIPTION"_s) { + return info.GetCPUDescription(); + } + if (key == "PROCESSOR_SERIAL_NUMBER"_s) { + return ValueToString(info.GetProcessorSerialNumber()); + } + if (key == "OS_NAME"_s) { + return ValueToString(info.GetOSName()); + } + if (key == "OS_RELEASE"_s) { + return ValueToString(info.GetOSRelease()); + } + if (key == "OS_VERSION"_s) { + return ValueToString(info.GetOSVersion()); + } + if (key == "OS_PLATFORM"_s) { + return ValueToString(info.GetOSPlatform()); + } + return {}; +} + +cm::optional<std::pair<std::string, std::string>> ParseOSReleaseLine( + std::string const& line) +{ + std::string key; + std::string value; + + char prev = 0; + enum ParserState + { + PARSE_KEY_1ST, + PARSE_KEY, + FOUND_EQ, + PARSE_SINGLE_QUOTE_VALUE, + PARSE_DBL_QUOTE_VALUE, + PARSE_VALUE, + IGNORE_REST + } state = PARSE_KEY_1ST; + + for (auto ch : line) { + switch (state) { + case PARSE_KEY_1ST: + if (std::isalpha(ch) || ch == '_') { + key += ch; + state = PARSE_KEY; + } else if (!std::isspace(ch)) { + state = IGNORE_REST; + } + break; + + case PARSE_KEY: + if (ch == '=') { + state = FOUND_EQ; + } else if (std::isalnum(ch) || ch == '_') { + key += ch; + } else { + state = IGNORE_REST; + } + break; + + case FOUND_EQ: + switch (ch) { + case '\'': + state = PARSE_SINGLE_QUOTE_VALUE; + break; + case '"': + state = PARSE_DBL_QUOTE_VALUE; + break; + case '#': + case '\\': + state = IGNORE_REST; + break; + default: + value += ch; + state = PARSE_VALUE; + } + break; + + case PARSE_SINGLE_QUOTE_VALUE: + if (ch == '\'') { + if (prev != '\\') { + state = IGNORE_REST; + } else { + assert(!value.empty()); + value[value.size() - 1] = ch; + } + } else { + value += ch; + } + break; + + case PARSE_DBL_QUOTE_VALUE: + if (ch == '"') { + if (prev != '\\') { + state = IGNORE_REST; + } else { + assert(!value.empty()); + value[value.size() - 1] = ch; + } + } else { + value += ch; + } + break; + + case PARSE_VALUE: + if (ch == '#' || std::isspace(ch)) { + state = IGNORE_REST; + } else { + value += ch; + } + break; + + default: + // Unexpected os-release parser state! + state = IGNORE_REST; + break; } - // Otherwise, find a VS 15 instance ourselves. - cmVSSetupAPIHelper vsSetupAPIHelper(15); - if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { - cmSystemTools::ConvertToUnixSlashes(value); + if (state == IGNORE_REST) { + break; } - } else if (key == "VS_16_DIR") { - // If generating for the VS 16 IDE, use the same instance. - cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator(); - if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 16 ")) { - cmGlobalVisualStudioVersionedGenerator* vs16gen = - static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); - if (vs16gen->GetVSInstance(value)) { - return true; + prev = ch; + } + if (!(key.empty() || value.empty())) { + return std::make_pair(key, value); + } + return {}; +} + +std::map<std::string, std::string> GetOSReleaseVariables( + cmExecutionStatus& status) +{ + auto& makefile = status.GetMakefile(); + const auto& sysroot = makefile.GetSafeDefinition("CMAKE_SYSROOT"); + + std::map<std::string, std::string> data; + // Based on + // https://www.freedesktop.org/software/systemd/man/os-release.html + for (auto name : { "/etc/os-release"_s, "/usr/lib/os-release"_s }) { + const auto& filename = cmStrCat(sysroot, name); + if (cmSystemTools::FileExists(filename)) { + cmsys::ifstream fin(filename.c_str()); + for (std::string line; !std::getline(fin, line).fail();) { + auto kv = ParseOSReleaseLine(line); + if (kv.has_value()) { + data.emplace(kv.value()); + } } + break; } + } + // Got smth? + if (!data.empty()) { + return data; + } + + // Ugh, it could be some pre-os-release distro. + // Lets try some fallback getters. + // See also: + // - http://linuxmafia.com/faq/Admin/release-files.html + + // 1. CMake provided + cmsys::Glob gl; + std::vector<std::string> scripts; + auto const findExpr = cmStrCat(cmSystemTools::GetCMakeRoot(), + "/Modules/Internal/OSRelease/*.cmake"); + if (gl.FindFiles(findExpr)) { + scripts = gl.GetFiles(); + } + + // 2. User provided (append to the CMake prvided) + makefile.GetDefExpandList("CMAKE_GET_OS_RELEASE_FALLBACK_SCRIPTS", scripts); + + // Filter out files that are not in format `NNN-name.cmake` + auto checkName = [](std::string const& filepath) -> bool { + auto const& filename = cmSystemTools::GetFilenameName(filepath); + // NOTE Minimum filename length expected: + // NNN-<at-least-one-char-name>.cmake --> 11 + return (filename.size() < 11) || !std::isdigit(filename[0]) || + !std::isdigit(filename[1]) || !std::isdigit(filename[2]) || + filename[3] != '-'; + }; + scripts.erase(std::remove_if(scripts.begin(), scripts.end(), checkName), + scripts.end()); - // Otherwise, find a VS 16 instance ourselves. - cmVSSetupAPIHelper vsSetupAPIHelper(16); - if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { - cmSystemTools::ConvertToUnixSlashes(value); + // Make sure scripts are running in desired order + std::sort(scripts.begin(), scripts.end(), + [](std::string const& lhs, std::string const& rhs) -> bool { + long lhs_order; + cmStrToLong(cmSystemTools::GetFilenameName(lhs).substr(0u, 3u), + &lhs_order); + long rhs_order; + cmStrToLong(cmSystemTools::GetFilenameName(rhs).substr(0u, 3u), + &rhs_order); + return lhs_order < rhs_order; + }); + + // Name of the variable to put the results + auto const result_variable = "CMAKE_GET_OS_RELEASE_FALLBACK_RESULT"_s; + + for (auto const& script : scripts) { + // Unset the result variable + makefile.RemoveDefinition(result_variable.data()); + + // include FATAL_ERROR and ERROR in the return status + if (!makefile.ReadListFile(script) || + cmSystemTools::GetErrorOccuredFlag()) { + // Ok, no worries... go try the next script. + continue; + } + + std::vector<std::string> variables; + if (!makefile.GetDefExpandList(result_variable.data(), variables)) { + // Heh, this script didn't found anything... go try the next one. + continue; } - } else if (key == "VS_17_DIR") { - // If generating for the VS 17 IDE, use the same instance. - cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator(); - if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 17 ")) { - cmGlobalVisualStudioVersionedGenerator* vs17gen = - static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); - if (vs17gen->GetVSInstance(value)) { - return true; + + for (auto const& variable : variables) { + auto value = makefile.GetSafeDefinition(variable); + makefile.RemoveDefinition(variable); + + if (!cmHasPrefix(variable, cmStrCat(result_variable, '_'))) { + // Ignore unknown variable set by the script + continue; } + + auto key = variable.substr(result_variable.size() + 1, + variable.size() - result_variable.size() - 1); + data.emplace(std::move(key), std::move(value)); } - // Otherwise, find a VS 17 instance ourselves. - cmVSSetupAPIHelper vsSetupAPIHelper(17); - if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { - cmSystemTools::ConvertToUnixSlashes(value); + // Try 'till some script can get anything + if (!data.empty()) { + data.emplace("USED_FALLBACK_SCRIPT", script); + break; } -#endif - } else { - std::string e = "does not recognize <key> " + key; - status.SetError(e); - return false; } - return true; + makefile.RemoveDefinition(result_variable.data()); + + return data; } -std::string ValueToString(size_t value) +cm::optional<std::string> GetValue(cmExecutionStatus& status, + std::string const& key, + std::string const& variable) { - return std::to_string(value); + const auto prefix = "DISTRIB_"_s; + if (!cmHasPrefix(key, prefix)) { + return {}; + } + + static const std::map<std::string, std::string> s_os_release = + GetOSReleaseVariables(status); + + auto& makefile = status.GetMakefile(); + + const std::string subkey = + key.substr(prefix.size(), key.size() - prefix.size()); + if (subkey == "INFO"_s) { + std::string vars; + for (const auto& kv : s_os_release) { + auto cmake_var_name = cmStrCat(variable, '_', kv.first); + vars += DELIM[!vars.empty()] + cmake_var_name; + makefile.AddDefinition(cmake_var_name, kv.second); + } + return cm::optional<std::string>(std::move(vars)); + } + + // Query individual variable + const auto it = s_os_release.find(subkey); + if (it != s_os_release.cend()) { + return it->second; + } + + // NOTE Empty string means requested variable not set + return std::string{}; +} + +#ifdef HAVE_VS_SETUP_HELPER +cm::optional<std::string> GetValue(cmExecutionStatus& status, + std::string const& key) +{ + auto* const gg = status.GetMakefile().GetGlobalGenerator(); + for (auto vs : { 15, 16, 17 }) { + if (key == cmStrCat("VS_"_s, vs, "_DIR"_s)) { + std::string value; + // If generating for the VS nn IDE, use the same instance. + + if (cmHasPrefix(gg->GetName(), cmStrCat("Visual Studio "_s, vs, ' '))) { + cmGlobalVisualStudioVersionedGenerator* vsNNgen = + static_cast<cmGlobalVisualStudioVersionedGenerator*>(gg); + if (vsNNgen->GetVSInstance(value)) { + return value; + } + } + + // Otherwise, find a VS nn instance ourselves. + cmVSSetupAPIHelper vsSetupAPIHelper(vs); + if (vsSetupAPIHelper.GetVSInstanceInfo(value)) { + cmSystemTools::ConvertToUnixSlashes(value); + } + return value; + } + } + + return {}; } +#endif -std::string ValueToString(const char* value) +cm::optional<std::string> GetValueChained() { - std::string safe_string = value ? value : ""; - return safe_string; + return {}; } -std::string ValueToString(std::string const& value) +template <typename GetterFn, typename... Next> +cm::optional<std::string> GetValueChained(GetterFn current, Next... chain) { - return value; + auto value = current(); + if (value.has_value()) { + return value; + } + return GetValueChained(chain...); } +// END Private functions +} // anonymous namespace + +// cmCMakeHostSystemInformation +bool cmCMakeHostSystemInformationCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + std::size_t current_index = 0; + + if (args.size() < (current_index + 2) || args[current_index] != "RESULT"_s) { + status.SetError("missing RESULT specification."); + return false; + } + + auto const& variable = args[current_index + 1]; + current_index += 2; + + if (args.size() < (current_index + 2) || args[current_index] != "QUERY"_s) { + status.SetError("missing QUERY specification"); + return false; + } + + static cmsys::SystemInformation info; + static auto initialized = false; + if (!initialized) { + info.RunCPUCheck(); + info.RunOSCheck(); + info.RunMemoryCheck(); + initialized = true; + } + + std::string result_list; + for (auto i = current_index + 1; i < args.size(); ++i) { + result_list += DELIM[!result_list.empty()]; + + auto const& key = args[i]; + // clang-format off + auto value = + GetValueChained( + [&]() { return GetValue(info, key); } + , [&]() { return GetValue(status, key, variable); } +#ifdef HAVE_VS_SETUP_HELPER + , [&]() { return GetValue(status, key); } +#endif + ); + // clang-format on + if (!value) { + status.SetError("does not recognize <key> " + key); + return false; + } + result_list += value.value(); + } + + status.GetMakefile().AddDefinition(variable, result_list); + + return true; } diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index ebdbe38..8b06a15 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -917,7 +917,7 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os) // Protect that file against use with older CMake versions. /* clang-format off */ os << "# Generated by CMake\n\n"; - os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n" + os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.6)\n" << " message(FATAL_ERROR \"CMake >= 2.6.0 required\")\n" << "endif()\n"; /* clang-format on */ diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index 79c06d6..d0ad53e 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -618,6 +618,9 @@ cmGlobalVisualStudioVersionedGenerator::FindAuxToolset( if (version == "14.29.16.10" && vcToolsetVersion == "14.29.30037") { return AuxToolset::Default; } + if (version == "14.29.16.11" && vcToolsetVersion == "14.29.30133") { + return AuxToolset::Default; + } // The first two components of the default toolset version typically // match the name used by later VS versions for the SxS props files. diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index 898d862..57fcd2d 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -384,39 +384,3 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile, } return true; } - -bool cmQtAutoGen::FileRead(std::string& content, std::string const& filename, - std::string* error) -{ - content.clear(); - if (!cmSystemTools::FileExists(filename, true)) { - if (error != nullptr) { - *error = "Not a file."; - } - return false; - } - - unsigned long const length = cmSystemTools::FileLength(filename); - cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary)); - - // Use lambda to save destructor calls of ifs - return [&ifs, length, &content, error]() -> bool { - if (!ifs) { - if (error != nullptr) { - *error = "Opening the file for reading failed."; - } - return false; - } - content.reserve(length); - using IsIt = std::istreambuf_iterator<char>; - content.assign(IsIt{ ifs }, IsIt{}); - if (!ifs) { - content.clear(); - if (error != nullptr) { - *error = "Reading from the file failed."; - } - return false; - } - return true; - }(); -} diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index b9ae360..466a954 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -100,9 +100,6 @@ public: std::vector<std::string> const& newOpts, bool isQt5); - static bool FileRead(std::string& content, std::string const& filename, - std::string* error = nullptr); - /** @class RccLister * @brief Lists files in qrc resource files */ diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 6cc8328..4dd78e5 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -902,13 +902,6 @@ bool cmQtAutoGenInitializer::InitScanFiles() // The reason is that their file names might be discovered from source files // at generation time. if (this->MocOrUicEnabled()) { - std::set<std::string> uicIncludes; - auto collectUicIncludes = [&](std::unique_ptr<cmSourceFile> const& sf) { - std::string content; - FileRead(content, sf->GetFullPath()); - this->AutoUicHelpers.CollectUicIncludes(uicIncludes, content); - }; - for (const auto& sf : this->Makefile->GetSourceFiles()) { // sf->GetExtension() is only valid after sf->ResolveFullPath() ... // Since we're iterating over source files that might be not in the @@ -921,10 +914,6 @@ bool cmQtAutoGenInitializer::InitScanFiles() std::string const& extLower = cmSystemTools::LowerCase(sf->GetExtension()); - bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN); - bool const skipUic = - (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC) || - !this->Uic.Enabled); if (cm->IsAHeaderExtension(extLower)) { if (!cm::contains(this->AutogenTarget.Headers, sf.get())) { auto muf = makeMUFile(sf.get(), fullPath, {}, false); @@ -932,9 +921,6 @@ bool cmQtAutoGenInitializer::InitScanFiles() addMUHeader(std::move(muf), extLower); } } - if (!skipUic && !sf->GetIsGenerated()) { - collectUicIncludes(sf); - } } else if (cm->IsACLikeSourceExtension(extLower)) { if (!cm::contains(this->AutogenTarget.Sources, sf.get())) { auto muf = makeMUFile(sf.get(), fullPath, {}, false); @@ -942,11 +928,11 @@ bool cmQtAutoGenInitializer::InitScanFiles() addMUSource(std::move(muf)); } } - if (!skipUic && !sf->GetIsGenerated()) { - collectUicIncludes(sf); - } } else if (this->Uic.Enabled && (extLower == kw.ui)) { // .ui file + bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN); + bool const skipUic = + (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC)); if (!skipUic) { // Check if the .ui file has uic options std::string const uicOpts = sf->GetSafeProperty(kw.AUTOUIC_OPTIONS); @@ -956,22 +942,35 @@ bool cmQtAutoGenInitializer::InitScanFiles() this->Uic.UiFilesWithOptions.emplace_back(fullPath, cmExpandedList(uicOpts)); } + + auto uiHeaderRelativePath = cmSystemTools::RelativePath( + this->LocalGen->GetCurrentSourceDirectory(), + cmSystemTools::GetFilenamePath(fullPath)); + + // Avoid creating a path containing adjacent slashes + if (!uiHeaderRelativePath.empty() && + uiHeaderRelativePath.back() != '/') { + uiHeaderRelativePath += '/'; + } + + auto uiHeaderFilePath = cmStrCat( + '/', uiHeaderRelativePath, "ui_"_s, + cmSystemTools::GetFilenameWithoutLastExtension(fullPath), ".h"_s); + + ConfigString uiHeader; + std::string uiHeaderGenex; + this->ConfigFileNamesAndGenex( + uiHeader, uiHeaderGenex, cmStrCat(this->Dir.Build, "/include"_s), + uiHeaderFilePath); + + this->Uic.UiHeaders.emplace_back( + std::make_pair(uiHeader, uiHeaderGenex)); } else { // Register skipped .ui file this->Uic.SkipUi.insert(fullPath); } } } - - for (const auto& include : uicIncludes) { - ConfigString uiHeader; - std::string uiHeaderGenex; - this->ConfigFileNamesAndGenex(uiHeader, uiHeaderGenex, - cmStrCat(this->Dir.Build, "/include"_s), - cmStrCat("/"_s, include)); - this->Uic.UiHeaders.emplace_back( - std::make_pair(uiHeader, uiHeaderGenex)); - } } // Process GENERATED sources and headers diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 3ec87d2..e76817b 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -17,7 +17,6 @@ #include "cmFilePathChecksum.h" #include "cmQtAutoGen.h" -#include "cmQtAutoUicHelpers.h" class cmGeneratorTarget; class cmGlobalGenerator; @@ -171,7 +170,6 @@ private: std::string ConfigDefault; std::vector<std::string> ConfigsList; std::string TargetsFolder; - cmQtAutoUicHelpers AutoUicHelpers; /** Common directories. */ struct diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx index 0c6b5e6..568926e 100644 --- a/Source/cmQtAutoGenerator.cxx +++ b/Source/cmQtAutoGenerator.cxx @@ -121,6 +121,43 @@ bool cmQtAutoGenerator::MakeParentDirectory(std::string const& filename) return success; } +bool cmQtAutoGenerator::FileRead(std::string& content, + std::string const& filename, + std::string* error) +{ + content.clear(); + if (!cmSystemTools::FileExists(filename, true)) { + if (error != nullptr) { + *error = "Not a file."; + } + return false; + } + + unsigned long const length = cmSystemTools::FileLength(filename); + cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary)); + + // Use lambda to save destructor calls of ifs + return [&ifs, length, &content, error]() -> bool { + if (!ifs) { + if (error != nullptr) { + *error = "Opening the file for reading failed."; + } + return false; + } + content.reserve(length); + using IsIt = std::istreambuf_iterator<char>; + content.assign(IsIt{ ifs }, IsIt{}); + if (!ifs) { + content.clear(); + if (error != nullptr) { + *error = "Reading from the file failed."; + } + return false; + } + return true; + }(); +} + bool cmQtAutoGenerator::FileWrite(std::string const& filename, std::string const& content, std::string* error) diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h index 66399d7..5c3a8ad 100644 --- a/Source/cmQtAutoGenerator.h +++ b/Source/cmQtAutoGenerator.h @@ -70,6 +70,8 @@ public: // -- File system methods static bool MakeParentDirectory(std::string const& filename); + static bool FileRead(std::string& content, std::string const& filename, + std::string* error = nullptr); static bool FileWrite(std::string const& filename, std::string const& content, std::string* error = nullptr); diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index 86d54f9..2753fd5 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -30,7 +30,6 @@ #include "cmGeneratedFileStream.h" #include "cmQtAutoGen.h" #include "cmQtAutoGenerator.h" -#include "cmQtAutoUicHelpers.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmWorkerPool.h" @@ -282,7 +281,7 @@ public: std::vector<std::string> Options; std::unordered_map<std::string, UiFile> UiFiles; std::vector<std::string> SearchPaths; - cmQtAutoUicHelpers AutoUicHelpers; + cmsys::RegularExpression RegExpInclude; }; /** Uic shared variables. */ @@ -762,7 +761,11 @@ std::string cmQtAutoMocUicT::MocSettingsT::MacrosString() const return res; } -cmQtAutoMocUicT::UicSettingsT::UicSettingsT() = default; +cmQtAutoMocUicT::UicSettingsT::UicSettingsT() +{ + this->RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+" + "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]"); +} cmQtAutoMocUicT::UicSettingsT::~UicSettingsT() = default; @@ -1053,7 +1056,16 @@ void cmQtAutoMocUicT::JobParseT::UicIncludes() } std::set<std::string> includes; - this->UicConst().AutoUicHelpers.CollectUicIncludes(includes, this->Content); + { + const char* contentChars = this->Content.c_str(); + cmsys::RegularExpression const& regExp = this->UicConst().RegExpInclude; + cmsys::RegularExpressionMatch match; + while (regExp.find(contentChars, match)) { + includes.emplace(match.match(2)); + // Forward content pointer + contentChars += match.end(); + } + } this->CreateKeys(this->FileHandle->ParseData->Uic.Include, includes, UiUnderscoreLength); } diff --git a/Source/cmQtAutoUicHelpers.cxx b/Source/cmQtAutoUicHelpers.cxx deleted file mode 100644 index 751ae08..0000000 --- a/Source/cmQtAutoUicHelpers.cxx +++ /dev/null @@ -1,25 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmQtAutoUicHelpers.h" - -cmQtAutoUicHelpers::cmQtAutoUicHelpers() -{ - RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+" - "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]"); -} - -void cmQtAutoUicHelpers::CollectUicIncludes(std::set<std::string>& includes, - const std::string& content) const -{ - if (content.find("ui_") == std::string::npos) { - return; - } - - const char* contentChars = content.c_str(); - cmsys::RegularExpressionMatch match; - while (this->RegExpInclude.find(contentChars, match)) { - includes.emplace(match.match(2)); - // Forward content pointer - contentChars += match.end(); - } -} diff --git a/Source/cmQtAutoUicHelpers.h b/Source/cmQtAutoUicHelpers.h deleted file mode 100644 index 6b09a31..0000000 --- a/Source/cmQtAutoUicHelpers.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#pragma once - -#include <set> -#include <string> - -#include "cmsys/RegularExpression.hxx" - -class cmQtAutoUicHelpers -{ -public: - cmQtAutoUicHelpers(); - virtual ~cmQtAutoUicHelpers() = default; - void CollectUicIncludes(std::set<std::string>& includes, - const std::string& content) const; - -private: - cmsys::RegularExpression RegExpInclude; -}; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index f082ae8..54fe7a1 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1629,7 +1629,10 @@ bool cmSystemTools::CreateTar(const std::string& outFileName, cmArchiveWrite a(fout, compress, format.empty() ? "paxr" : format, compressionLevel); - a.Open(); + if (!a.Open()) { + cmSystemTools::Error(a.GetError()); + return false; + } a.SetMTime(mtime); a.SetVerbose(verbose); bool tarCreatedSuccessfully = true; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index ab8309d..7f8f654 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -114,7 +114,9 @@ # include "cmExtraSublimeTextGenerator.h" #endif -#if defined(__linux__) || defined(_WIN32) +// NOTE: the __linux__ macro is predefined on Android host too, but +// main CMakeLists.txt filters out this generator by host name. +#if (defined(__linux__) && !defined(__ANDROID__)) || defined(_WIN32) # include "cmGlobalGhsMultiGenerator.h" #endif @@ -2528,7 +2530,7 @@ void cmake::AddDefaultGenerators() this->Generators.push_back(cmGlobalMinGWMakefileGenerator::NewFactory()); #endif #if !defined(CMAKE_BOOTSTRAP) -# if defined(__linux__) || defined(_WIN32) +# if (defined(__linux__) && !defined(__ANDROID__)) || defined(_WIN32) this->Generators.push_back(cmGlobalGhsMultiGenerator::NewFactory()); # endif this->Generators.push_back(cmGlobalUnixMakefileGenerator3::NewFactory()); diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt index 52959e6..9e0b891 100644 --- a/Tests/CMakeTests/CMakeLists.txt +++ b/Tests/CMakeTests/CMakeLists.txt @@ -31,7 +31,6 @@ AddCMakeTest(CompilerIdVendor "") AddCMakeTest(ProcessorCount "-DKWSYS_TEST_EXE=$<TARGET_FILE:cmsysTestsCxx>") AddCMakeTest(PushCheckState "") AddCMakeTest(While "") -AddCMakeTest(CMakeHostSystemInformation "") AddCMakeTest(FileDownload "") set_tests_properties(CMake.FileDownload PROPERTIES diff --git a/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt index a3ba9fb..9b114e9 100644 --- a/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt +++ b/Tests/QtAutogen/RerunUicOnFileChange/CMakeLists.txt @@ -28,12 +28,10 @@ endmacro() configure_file("${testProjectTemplateDir}/mocwidget.h" "${testProjectSrc}/mocwidget.h" COPYONLY) configure_file("${testProjectTemplateDir}/mainwindow.h" "${testProjectSrc}/mainwindow.h" COPYONLY) configure_file("${testProjectTemplateDir}/main.cpp" "${testProjectSrc}/main.cpp" COPYONLY) -configure_file("${testProjectTemplateDir}/subdir/subdircheck.cpp" "${testProjectSrc}/subdir/subdircheck.cpp" COPYONLY) configure_file("${testProjectTemplateDir}/CMakeLists.txt.in" "${testProjectSrc}/CMakeLists.txt" @ONLY) set(Num 1) configure_file("${testProjectTemplateDir}/mainwindow.ui.in" "${testProjectSrc}/mainwindow.ui" @ONLY) -configure_file("${testProjectTemplateDir}/subdir/mainwindowsubdir.ui.in" "${testProjectSrc}/subdir/mainwindowsubdir.ui" @ONLY) if(CMAKE_GENERATOR_INSTANCE) set(_D_CMAKE_GENERATOR_INSTANCE "-DCMAKE_GENERATOR_INSTANCE=${CMAKE_GENERATOR_INSTANCE}") @@ -97,7 +95,6 @@ sleep() set(Num 2) configure_file("${testProjectTemplateDir}/mainwindow.ui.in" "${testProjectSrc}/mainwindow.ui" @ONLY) -configure_file("${testProjectTemplateDir}/subdir/mainwindowsubdir.ui.in" "${testProjectSrc}/subdir/mainwindowsubdir.ui" @ONLY) rebuild(2) execute_process(COMMAND "${testProjectBinDir}/${extra_bin_path}UicOnFileChange" RESULT_VARIABLE result) diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in index c77075c..c787db1 100644 --- a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in +++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/CMakeLists.txt.in @@ -8,7 +8,6 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) add_executable(UicOnFileChange main.cpp mainwindow.ui mainwindow.h - subdir/subdircheck.cpp subdir/mainwindowsubdir.ui ) target_include_directories(UicOnFileChange PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp index 99de13d..4aab2ad 100644 --- a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp +++ b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/main.cpp @@ -1,12 +1,10 @@ #include "mainwindow.h" #include "ui_mainwindow.h" -extern bool subdircheck(); - int main(int argc, char* argv[]) { MocWidget mw; Ui::Widget mwUi; mwUi.setupUi(&mw); - return mw.objectName() == "Widget2" && subdircheck() ? 0 : 1; + return mw.objectName() == "Widget2" ? 0 : 1; } diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/mainwindowsubdir.ui.in b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/mainwindowsubdir.ui.in deleted file mode 100644 index a6a31f6..0000000 --- a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/mainwindowsubdir.ui.in +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>WidgetSubdir</class> - <widget class="MocWidget" name="WidgetSubdir@Num@"/> - <resources/> - <connections/> -</ui> diff --git a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/subdircheck.cpp b/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/subdircheck.cpp deleted file mode 100644 index 3b36a10..0000000 --- a/Tests/QtAutogen/RerunUicOnFileChange/UicOnFileChange/subdir/subdircheck.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "ui_mainwindowsubdir.h" - -bool subdircheck() -{ - MocWidget mw; - Ui::WidgetSubdir mwUi; - mwUi.setupUi(&mw); - return mw.objectName() == "WidgetSubdir2"; -} diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index ef797f7..eb2c2d9 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -349,6 +349,7 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) endif() add_RunCMake_test(execute_process) add_RunCMake_test(export) +add_RunCMake_test(cmake_host_system_information) add_RunCMake_test(cmake_language) add_RunCMake_test(cmake_minimum_required) add_RunCMake_test(cmake_parse_arguments) diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMP0126_NEW.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMP0126_NEW.cmake new file mode 100644 index 0000000..a419ab3 --- /dev/null +++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_CMP0126_NEW.cmake @@ -0,0 +1,64 @@ + +cmake_policy(SET CMP0126 NEW) + +# Needed for CMAKE_SYSTEM_NAME, CMAKE_LIBRARY_ARCHITECTURE, FIND_LIBRARY_USE_LIB32_PATHS and FIND_LIBRARY_USE_LIB64_PATHS +enable_language(C) + +# Prepare environment and variables +set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH TRUE) +set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/pc-foo") +if(WIN32) + set(PKG_CONFIG_EXECUTABLE "${CMAKE_CURRENT_SOURCE_DIR}\\dummy-pkg-config.bat") + set(ENV{CMAKE_PREFIX_PATH} "${CMAKE_CURRENT_SOURCE_DIR}\\pc-bar;X:\\this\\directory\\should\\not\\exist\\in\\the\\filesystem") + set(ENV{PKG_CONFIG_PATH} "C:\\baz") +else() + set(PKG_CONFIG_EXECUTABLE "${CMAKE_CURRENT_SOURCE_DIR}/dummy-pkg-config.sh") + set(ENV{CMAKE_PREFIX_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/pc-bar:/this/directory/should/not/exist/in/the/filesystem") + set(ENV{PKG_CONFIG_PATH} "/baz") +endif() + + +find_package(PkgConfig) + + +if(NOT DEFINED CMAKE_SYSTEM_NAME + OR (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU)$" + AND NOT CMAKE_CROSSCOMPILING)) + if(EXISTS "/etc/debian_version") # is this a debian system ? + if(CMAKE_LIBRARY_ARCHITECTURE MATCHES "^(i386-linux-gnu|x86_64-linux-gnu)$") + # Cannot create directories for all the existing architectures... + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/${CMAKE_LIBRARY_ARCHITECTURE}/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/${CMAKE_LIBRARY_ARCHITECTURE}/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + else() + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + endif() + else() + # not debian, check the FIND_LIBRARY_USE_LIB32_PATHS and FIND_LIBRARY_USE_LIB64_PATHS properties + get_property(uselibx32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS) + get_property(uselib32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS) + get_property(uselib64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) + if(uselibx32 AND CMAKE_INTERNAL_PLATFORM_ABI STREQUAL "ELF X32") + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/libx32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + elseif(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib32/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + elseif(uselib64 AND CMAKE_SIZEOF_VOID_P EQUAL 8) + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib64/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + else() + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + endif() + endif() +else() + if(WIN32) + set(expected_path "C:\\baz;${CMAKE_CURRENT_SOURCE_DIR}\\pc-foo\\lib\\pkgconfig;${CMAKE_CURRENT_SOURCE_DIR}\\pc-bar\\lib\\pkgconfig") + else() + set(expected_path "/baz:${CMAKE_CURRENT_SOURCE_DIR}/pc-foo/lib/pkgconfig:${CMAKE_CURRENT_SOURCE_DIR}/pc-bar/lib/pkgconfig") + endif() +endif() + + +set(FOO_FOUND FALSE) + +pkg_check_modules(FOO "${expected_path}") + +if(NOT FOO_FOUND) + message(FATAL_ERROR "Expected FOO_FOUND == 1.") +endif() diff --git a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake index 81a4732..f36d1eb 100644 --- a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake @@ -7,6 +7,7 @@ set(ENV{CMAKE_FRAMEWORK_PATH} "") run_cmake(PkgConfigDoesNotExist) +run_cmake(FindPkgConfig_CMP0126_NEW) run_cmake(FindPkgConfig_NO_PKGCONFIG_PATH) run_cmake(FindPkgConfig_PKGCONFIG_PATH) run_cmake(FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_PATH) diff --git a/Tests/RunCMake/cmake_host_system_information/000-FirstFallbackScript.cmake b/Tests/RunCMake/cmake_host_system_information/000-FirstFallbackScript.cmake new file mode 100644 index 0000000..ad873eb --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/000-FirstFallbackScript.cmake @@ -0,0 +1 @@ +message(WARNING "The warning text to match just to make sure the script get executed") diff --git a/Tests/RunCMake/cmake_host_system_information/999-LastFallbackScript.cmake b/Tests/RunCMake/cmake_host_system_information/999-LastFallbackScript.cmake new file mode 100644 index 0000000..08d8da8 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/999-LastFallbackScript.cmake @@ -0,0 +1,21 @@ +if(DEFINED CMAKE_GET_OS_RELEASE_FALLBACK_RESULT) + message(FATAL_ERROR "The `CMAKE_GET_OS_RELEASE_FALLBACK_RESULT` expected to be unset at this moment") +endif() + +set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME UnitTest) +set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME "Just a Unit Test") +set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID unittest) +set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID_LIKE nothing) +set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION 0.0.1) +set(CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID 0.0.1) + +list( + APPEND CMAKE_GET_OS_RELEASE_FALLBACK_RESULT + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME + IGNORED_VARIABLE_NAME_WHICH_IS_NOT_STARTED_WITH_EXPECTED_PREFIX + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID_LIKE + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION + CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID + ) diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg1-result.txt b/Tests/RunCMake/cmake_host_system_information/BadArg1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/BadArg1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg1-stderr.txt b/Tests/RunCMake/cmake_host_system_information/BadArg1-stderr.txt new file mode 100644 index 0000000..ed995e6 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/BadArg1-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at BadArg1\.cmake:1 \(cmake_host_system_information\): + cmake_host_system_information missing RESULT specification. +Call Stack \(most recent call first\): + CMakeLists\.txt:7 \(include\) diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg1.cmake b/Tests/RunCMake/cmake_host_system_information/BadArg1.cmake index 1655eb4..1655eb4 100644 --- a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg1.cmake +++ b/Tests/RunCMake/cmake_host_system_information/BadArg1.cmake diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg2-result.txt b/Tests/RunCMake/cmake_host_system_information/BadArg2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/BadArg2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg2-stderr.txt b/Tests/RunCMake/cmake_host_system_information/BadArg2-stderr.txt new file mode 100644 index 0000000..b78c927 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/BadArg2-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at BadArg2\.cmake:1 \(cmake_host_system_information\): + cmake_host_system_information missing QUERY specification +Call Stack \(most recent call first\): + CMakeLists\.txt:7 \(include\) diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg2.cmake b/Tests/RunCMake/cmake_host_system_information/BadArg2.cmake index 1f056d5..1f056d5 100644 --- a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg2.cmake +++ b/Tests/RunCMake/cmake_host_system_information/BadArg2.cmake diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg3-result.txt b/Tests/RunCMake/cmake_host_system_information/BadArg3-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/BadArg3-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/cmake_host_system_information/BadArg3-stderr.txt b/Tests/RunCMake/cmake_host_system_information/BadArg3-stderr.txt new file mode 100644 index 0000000..c3f1314 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/BadArg3-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at BadArg3\.cmake:1 \(cmake_host_system_information\): + cmake_host_system_information does not recognize <key> FOOBAR +Call Stack \(most recent call first\): + CMakeLists\.txt:7 \(include\) diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg3.cmake b/Tests/RunCMake/cmake_host_system_information/BadArg3.cmake index 9c5a558..9c5a558 100644 --- a/Tests/CMakeTests/CMakeHostSystemInformation-BadArg3.cmake +++ b/Tests/RunCMake/cmake_host_system_information/BadArg3.cmake diff --git a/Tests/RunCMake/cmake_host_system_information/CMakeLists.txt b/Tests/RunCMake/cmake_host_system_information/CMakeLists.txt new file mode 100644 index 0000000..0198f9b --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.21) + +project(${RunCMake_TEST} NONE) + +set(CMAKE_SYSROOT ${PROJECT_SOURCE_DIR}/${RunCMake_TEST}) + +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt b/Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt new file mode 100644 index 0000000..50dbb08 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/CentOS6-stdout.txt @@ -0,0 +1,7 @@ +-- CENTOS6_ID=`centos` +-- CENTOS6_ID_LIKE=`rhel` +-- CENTOS6_NAME=`CentOS` +-- CENTOS6_PRETTY_NAME=`CentOS release 6\.10 \(Final\)` +-- CENTOS6_USED_FALLBACK_SCRIPT=`.*/Modules/Internal/OSRelease/010-TryOldCentOS.cmake` +-- CENTOS6_VERSION=`6\.10` +-- CENTOS6_VERSION_ID=`6\.10` diff --git a/Tests/RunCMake/cmake_host_system_information/CentOS6.cmake b/Tests/RunCMake/cmake_host_system_information/CentOS6.cmake new file mode 100644 index 0000000..3bc632b --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/CentOS6.cmake @@ -0,0 +1,5 @@ +cmake_host_system_information(RESULT CENTOS6 QUERY DISTRIB_INFO) + +foreach(VAR IN LISTS CENTOS6) + message(STATUS "${VAR}=`${${VAR}}`") +endforeach() diff --git a/Tests/RunCMake/cmake_host_system_information/CentOS6/etc/centos-release b/Tests/RunCMake/cmake_host_system_information/CentOS6/etc/centos-release new file mode 100644 index 0000000..294ccc9 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/CentOS6/etc/centos-release @@ -0,0 +1 @@ +CentOS release 6.10 (Final) diff --git a/Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt b/Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt new file mode 100644 index 0000000..4193d6f --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Debian6-stdout.txt @@ -0,0 +1,5 @@ +-- DEBIAN6_ID=`debian` +-- DEBIAN6_NAME=`Debian` +-- DEBIAN6_USED_FALLBACK_SCRIPT=`.*/Modules/Internal/OSRelease/020-TryDebianVersion.cmake` +-- DEBIAN6_VERSION=`6\.0\.10` +-- DEBIAN6_VERSION_ID=`6\.0\.10` diff --git a/Tests/RunCMake/cmake_host_system_information/Debian6.cmake b/Tests/RunCMake/cmake_host_system_information/Debian6.cmake new file mode 100644 index 0000000..cbf83a9 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Debian6.cmake @@ -0,0 +1,5 @@ +cmake_host_system_information(RESULT DEBIAN6 QUERY DISTRIB_INFO) + +foreach(VAR IN LISTS DEBIAN6) + message(STATUS "${VAR}=`${${VAR}}`") +endforeach() diff --git a/Tests/RunCMake/cmake_host_system_information/Debian6/etc/debian_version b/Tests/RunCMake/cmake_host_system_information/Debian6/etc/debian_version new file mode 100644 index 0000000..c7d48f0 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Debian6/etc/debian_version @@ -0,0 +1 @@ +6.0.10 diff --git a/Tests/RunCMake/cmake_host_system_information/Exherbo-stdout.txt b/Tests/RunCMake/cmake_host_system_information/Exherbo-stdout.txt new file mode 100644 index 0000000..11ae71f --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Exherbo-stdout.txt @@ -0,0 +1,9 @@ +-- TEST1_ANSI_COLOR=`0;32` +-- TEST1_BUG_REPORT_URL=`https://bugs.exherbo.org/` +-- TEST1_HOME_URL=`https://www.exherbo.org/` +-- TEST1_ID=`exherbo` +-- TEST1_NAME=`Exherbo` +-- TEST1_PRETTY_NAME=`Exherbo Linux` +-- TEST1_SUPPORT_URL=`irc://irc.freenode.net/#exherbo` +-- TEST2_ID=`exherbo` +-- TEST2_VERSION=`` diff --git a/Tests/RunCMake/cmake_host_system_information/Exherbo.cmake b/Tests/RunCMake/cmake_host_system_information/Exherbo.cmake new file mode 100644 index 0000000..7fc26d8 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Exherbo.cmake @@ -0,0 +1,11 @@ +cmake_host_system_information(RESULT TEST1 QUERY DISTRIB_INFO) + +foreach(VAR IN LISTS TEST1) + message(STATUS "${VAR}=`${${VAR}}`") +endforeach() + +# Query individual variables +cmake_host_system_information(RESULT TEST2 QUERY DISTRIB_ID DISTRIB_VERSION) +list(POP_FRONT TEST2 TEST2_ID TEST2_VERSION) +message(STATUS "TEST2_ID=`${TEST2_ID}`") +message(STATUS "TEST2_VERSION=`${TEST2_VERSION}`") diff --git a/Tests/RunCMake/cmake_host_system_information/Exherbo/etc/os-release b/Tests/RunCMake/cmake_host_system_information/Exherbo/etc/os-release new file mode 100644 index 0000000..944c9b4 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Exherbo/etc/os-release @@ -0,0 +1,7 @@ +NAME="Exherbo" +PRETTY_NAME="Exherbo Linux" +ID="exherbo" +ANSI_COLOR="0;32" +HOME_URL="https://www.exherbo.org/" +SUPPORT_URL="irc://irc.freenode.net/#exherbo" +BUG_REPORT_URL="https://bugs.exherbo.org/" diff --git a/Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt b/Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt new file mode 100644 index 0000000..f583deb --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/QueryKeys-stdout.txt @@ -0,0 +1,27 @@ +-- NUMBER_OF_LOGICAL_CORES=`[0-9]+` +-- NUMBER_OF_PHYSICAL_CORES=`[0-9]+` +-- HOSTNAME=`.*` +-- FQDN=`.*` +-- TOTAL_VIRTUAL_MEMORY=`[0-9]+` +-- AVAILABLE_VIRTUAL_MEMORY=`[0-9]+` +-- TOTAL_PHYSICAL_MEMORY=`[0-9]+` +-- AVAILABLE_PHYSICAL_MEMORY=`[0-9]+` +-- IS_64BIT=`[01]` +-- HAS_FPU=`[01]` +-- HAS_MMX=`[01]` +-- HAS_MMX_PLUS=`[01]` +-- HAS_SSE=`[01]` +-- HAS_SSE2=`[01]` +-- HAS_SSE_FP=`[01]` +-- HAS_SSE_MMX=`[01]` +-- HAS_AMD_3DNOW=`[01]` +-- HAS_AMD_3DNOW_PLUS=`[01]` +-- HAS_IA64=`[01]` +-- HAS_SERIAL_NUMBER=`[01]` +-- PROCESSOR_SERIAL_NUMBER=`.*` +-- PROCESSOR_NAME=`.*` +-- PROCESSOR_DESCRIPTION=`.*` +-- OS_NAME=`.*` +-- OS_RELEASE=`.*` +-- OS_VERSION=`.*` +-- OS_PLATFORM=`.*` diff --git a/Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in b/Tests/RunCMake/cmake_host_system_information/QueryKeys.cmake index a3c2b05..f22a0ae 100644 --- a/Tests/CMakeTests/CMakeHostSystemInformationTest.cmake.in +++ b/Tests/RunCMake/cmake_host_system_information/QueryKeys.cmake @@ -1,19 +1,8 @@ -set(BadArg1-RESULT 1) -set(BadArg1-STDERR "missing RESULT specification") -set(BadArg2-RESULT 1) -set(BadArg2-STDERR "missing QUERY specification") -set(BadArg3-RESULT 1) -set(BadArg3-STDERR "does not recognize <key> FOOBAR") -set(QueryList-RESULT 0) -set(QueryList-STDERR "\\[[0-9]+;[0-9]+\\]") - function(try_and_print key) - cmake_host_system_information(RESULT RESULT QUERY ${key}) - message(STATUS "[${key}] [${RESULT}]") + cmake_host_system_information(RESULT RESULT QUERY ${key}) + message(STATUS "${key}=`${RESULT}`") endfunction() -message("CTEST_FULL_OUTPUT (Avoid ctest truncation of output)") - try_and_print(NUMBER_OF_LOGICAL_CORES) try_and_print(NUMBER_OF_PHYSICAL_CORES) try_and_print(HOSTNAME) @@ -41,12 +30,3 @@ try_and_print(OS_NAME) try_and_print(OS_RELEASE) try_and_print(OS_VERSION) try_and_print(OS_PLATFORM) - -include("@CMAKE_CURRENT_SOURCE_DIR@/CheckCMakeTest.cmake") - -check_cmake_test(CMakeHostSystemInformation - BadArg1 - BadArg2 - BadArg3 - QueryList -) diff --git a/Tests/RunCMake/cmake_host_system_information/QueryList-stdout.txt b/Tests/RunCMake/cmake_host_system_information/QueryList-stdout.txt new file mode 100644 index 0000000..eebe0d4 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/QueryList-stdout.txt @@ -0,0 +1 @@ +-- \[[0-9]+;[0-9]+\] diff --git a/Tests/CMakeTests/CMakeHostSystemInformation-QueryList.cmake b/Tests/RunCMake/cmake_host_system_information/QueryList.cmake index 1c3156d..f24aa2b 100644 --- a/Tests/CMakeTests/CMakeHostSystemInformation-QueryList.cmake +++ b/Tests/RunCMake/cmake_host_system_information/QueryList.cmake @@ -2,4 +2,4 @@ cmake_host_system_information(RESULT RESULT QUERY NUMBER_OF_LOGICAL_CORES NUMBER_OF_PHYSICAL_CORES ) -message("[${RESULT}]") +message(STATUS "[${RESULT}]") diff --git a/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake new file mode 100644 index 0000000..189013f --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/RunCMakeTest.cmake @@ -0,0 +1,17 @@ +include(RunCMake) + +run_cmake(BadArg1) +run_cmake(BadArg2) +run_cmake(BadArg3) + +run_cmake(QueryList) +run_cmake(QueryKeys) + +run_cmake(UnitTest) +run_cmake(Exherbo) +run_cmake(Ubuntu) + +run_cmake(CentOS6) +run_cmake(Debian6) + +run_cmake(UserFallbackScript) diff --git a/Tests/RunCMake/cmake_host_system_information/Ubuntu-stdout.txt b/Tests/RunCMake/cmake_host_system_information/Ubuntu-stdout.txt new file mode 100644 index 0000000..d1a18da --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Ubuntu-stdout.txt @@ -0,0 +1,14 @@ +-- TEST1_BUG_REPORT_URL=`https://bugs\.launchpad\.net/ubuntu/` +-- TEST1_HOME_URL=`https://www\.ubuntu\.com/` +-- TEST1_ID=`ubuntu` +-- TEST1_ID_LIKE=`debian` +-- TEST1_NAME=`Ubuntu` +-- TEST1_PRETTY_NAME=`Ubuntu 20\.04\.2 LTS` +-- TEST1_PRIVACY_POLICY_URL=`https://www\.ubuntu\.com/legal/terms-and-policies/privacy-policy` +-- TEST1_SUPPORT_URL=`https://help\.ubuntu\.com/` +-- TEST1_UBUNTU_CODENAME=`focal` +-- TEST1_VERSION=`20\.04\.2 LTS \(Focal Fossa\)` +-- TEST1_VERSION_CODENAME=`focal` +-- TEST1_VERSION_ID=`20\.04` +-- TEST2_ID=`ubuntu` +-- TEST2_VERSION=`20\.04\.2 LTS \(Focal Fossa\)` diff --git a/Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake b/Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake new file mode 100644 index 0000000..7fc26d8 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Ubuntu.cmake @@ -0,0 +1,11 @@ +cmake_host_system_information(RESULT TEST1 QUERY DISTRIB_INFO) + +foreach(VAR IN LISTS TEST1) + message(STATUS "${VAR}=`${${VAR}}`") +endforeach() + +# Query individual variables +cmake_host_system_information(RESULT TEST2 QUERY DISTRIB_ID DISTRIB_VERSION) +list(POP_FRONT TEST2 TEST2_ID TEST2_VERSION) +message(STATUS "TEST2_ID=`${TEST2_ID}`") +message(STATUS "TEST2_VERSION=`${TEST2_VERSION}`") diff --git a/Tests/RunCMake/cmake_host_system_information/Ubuntu/etc/os-release b/Tests/RunCMake/cmake_host_system_information/Ubuntu/etc/os-release new file mode 100644 index 0000000..f228f22 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/Ubuntu/etc/os-release @@ -0,0 +1,12 @@ +NAME="Ubuntu" +VERSION="20.04.2 LTS (Focal Fossa)" +ID=ubuntu +ID_LIKE=debian +PRETTY_NAME="Ubuntu 20.04.2 LTS" +VERSION_ID="20.04" +HOME_URL="https://www.ubuntu.com/" +SUPPORT_URL="https://help.ubuntu.com/" +BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" +PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" +VERSION_CODENAME=focal +UBUNTU_CODENAME=focal diff --git a/Tests/RunCMake/cmake_host_system_information/UnitTest-stdout.txt b/Tests/RunCMake/cmake_host_system_information/UnitTest-stdout.txt new file mode 100644 index 0000000..db6f487 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/UnitTest-stdout.txt @@ -0,0 +1,7 @@ +-- UNIT_TEST_A_LIST_LIKE_VARIABLE=`satu;dua;tiga` +-- UNIT_TEST_DBL_QUOTED_VALUE=`"The" value in double "quotes"` +-- UNIT_TEST_DBL_QUOTED_VALUE_STIPPED_COMMENT=`Blah blah blah` +-- UNIT_TEST_NON_SPACE_VALUE=`Blah-blah-blah` +-- UNIT_TEST_QUOTED_VALUE=`'The' value in single 'quotes'` +-- UNIT_TEST_QUOTED_VALUE_STIPPED_COMMENT=`The value in single quotes` +-- UNIT_TEST_THE_URL_WITH_ANCHOR_TEST=`https://blah.blah/resource#anchor` diff --git a/Tests/RunCMake/cmake_host_system_information/UnitTest.cmake b/Tests/RunCMake/cmake_host_system_information/UnitTest.cmake new file mode 100644 index 0000000..d9a0aca --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/UnitTest.cmake @@ -0,0 +1,5 @@ +cmake_host_system_information(RESULT UNIT_TEST QUERY DISTRIB_INFO) + +foreach(VAR IN LISTS UNIT_TEST) + message(STATUS "${VAR}=`${${VAR}}`") +endforeach() diff --git a/Tests/RunCMake/cmake_host_system_information/UnitTest/etc/os-release b/Tests/RunCMake/cmake_host_system_information/UnitTest/etc/os-release new file mode 100644 index 0000000..66c33b5 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/UnitTest/etc/os-release @@ -0,0 +1,9 @@ +# Comment string gonna be ignored +NON_SPACE_VALUE=Blah-blah-blah +QUOTED_VALUE='\'The\' value in single \'quotes\'' +QUOTED_VALUE_STIPPED_COMMENT='The value in single quotes'# The comment right after `'` +DBL_QUOTED_VALUE="\"The\" value in double \"quotes\"" +DBL_QUOTED_VALUE_STIPPED_COMMENT="Blah blah blah"# The comment right after `'` +THE_URL_WITH_ANCHOR_TEST="https://blah.blah/resource#anchor" # And a comment after +A_LIST_LIKE_VARIABLE='satu;dua;tiga' +INCORRECT_ESCAPE_IGNORED=\'This line gonna be ignored' diff --git a/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stderr.txt b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stderr.txt new file mode 100644 index 0000000..78acea2 --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stderr.txt @@ -0,0 +1,5 @@ +CMake Warning at 000-FirstFallbackScript\.cmake:[0-9]+ \(message\): + The warning text to match just to make sure the script get executed +Call Stack \(most recent call first\): + UserFallbackScript\.cmake:[0-9]+ \(cmake_host_system_information\) + CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt new file mode 100644 index 0000000..acaf47e --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript-stdout.txt @@ -0,0 +1,7 @@ +-- UFS_ID=`unittest` +-- UFS_ID_LIKE=`nothing` +-- UFS_NAME=`UnitTest` +-- UFS_PRETTY_NAME=`Just a Unit Test` +-- UFS_USED_FALLBACK_SCRIPT=`.*/999-LastFallbackScript\.cmake` +-- UFS_VERSION=`0\.0\.1` +-- UFS_VERSION_ID=`0\.0\.1` diff --git a/Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake new file mode 100644 index 0000000..660aa1c --- /dev/null +++ b/Tests/RunCMake/cmake_host_system_information/UserFallbackScript.cmake @@ -0,0 +1,12 @@ +list( + APPEND CMAKE_GET_OS_RELEASE_FALLBACK_SCRIPTS + ${CMAKE_CURRENT_SOURCE_DIR}/000-FirstFallbackScript.cmake + ${CMAKE_CURRENT_SOURCE_DIR}/Ignored-Script.cmake + ${CMAKE_CURRENT_SOURCE_DIR}/999-LastFallbackScript.cmake + ) + +cmake_host_system_information(RESULT UFS QUERY DISTRIB_INFO) + +foreach(VAR IN LISTS UFS) + message(STATUS "${VAR}=`${${VAR}}`") +endforeach() diff --git a/Utilities/KWIML/include/kwiml/int.h b/Utilities/KWIML/include/kwiml/int.h index b2e14d5..25a063a 100644 --- a/Utilities/KWIML/include/kwiml/int.h +++ b/Utilities/KWIML/include/kwiml/int.h @@ -162,7 +162,11 @@ An includer may test the following macros after inclusion: #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ # define KWIML_INT_HAVE_INTTYPES_H 1 #elif defined(_MSC_VER) /* MSVC */ -# define KWIML_INT_NO_INTTYPES_H 1 +# if _MSC_VER >= 1800 +# define KWIML_INT_HAVE_INTTYPES_H 1 +# else +# define KWIML_INT_NO_INTTYPES_H 1 +# endif #elif defined(__BORLANDC__) /* Borland */ # define KWIML_INT_NO_INTTYPES_H 1 #elif defined(__WATCOMC__) /* Watcom */ @@ -272,6 +276,15 @@ An includer may test the following macros after inclusion: # define KWIML_INT_BROKEN_PRIXPTR 1 #endif +#if defined(_MSC_VER) && _MSC_VER < 1900 + /* MSVC scanf seems broken on 8-bit sizes until 19.00 */ +# define KWIML_INT_BROKEN_SCNd8 1 +# define KWIML_INT_BROKEN_SCNi8 1 +# define KWIML_INT_BROKEN_SCNo8 1 +# define KWIML_INT_BROKEN_SCNu8 1 +# define KWIML_INT_BROKEN_SCNx8 1 +#endif + #if (defined(__SUNPRO_C)||defined(__SUNPRO_CC)) && defined(_CHAR_IS_UNSIGNED) # define KWIML_INT_BROKEN_INT8_T 1 /* system type defined incorrectly */ #elif defined(__BORLANDC__) && defined(_CHAR_UNSIGNED) @@ -303,7 +316,7 @@ An includer may test the following macros after inclusion: #elif defined(__BORLANDC__) # define KWIML_INT_private_NO_SCN8 # define KWIML_INT_private_NO_SCN64 -#elif defined(_MSC_VER) +#elif defined(_MSC_VER) && _MSC_VER < 1900 # define KWIML_INT_private_NO_SCN8 #elif defined(__WATCOMC__) # define KWIML_INT_private_NO_SCN8 diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c index 9489e51..bcb67fe 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c @@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$"); #elif HAVE_BSDXML_H #include <bsdxml.h> #elif HAVE_EXPAT_H -#include <expat.h> +#include <cm3p/expat.h> #endif #ifdef HAVE_BZLIB_H #include <cm3p/bzlib.h> diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c index 4d71f98..62f98a4 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c @@ -53,10 +53,10 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_zip.c 201102 #include <cm3p/zlib.h> #endif #ifdef HAVE_BZLIB_H -#include <bzlib.h> +#include <cm3p/bzlib.h> #endif #ifdef HAVE_LZMA_H -#include <lzma.h> +#include <cm3p/lzma.h> #endif #include "archive.h" |