Merge topic 'if-space-dldt' 2c0d16df7b Help/command/if: fix formatting in precedence order overview Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !9777
diff --git a/CompileFlags.cmake b/CompileFlags.cmake index f94e079..3080daa 100644 --- a/CompileFlags.cmake +++ b/CompileFlags.cmake
@@ -37,7 +37,13 @@ string(APPEND CMAKE_EXE_LINKER_FLAGS " -Xlinker -stack:20000000") endif() -#silence duplicate symbol warnings on AIX +# Silence "Additional optimization may be attained by recompiling and +# specifying MAXMEM option" warning on XLC (AIX) +if(CMAKE_CXX_COMPILER_ID MATCHES "^(XL|XLClang)$") + string(APPEND CMAKE_CXX_FLAGS " -qmaxmem=-1") +endif() + +# Silence duplicate symbol warnings on AIX if(CMAKE_SYSTEM_NAME MATCHES "AIX") if(NOT CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -bhalt:5 ")
diff --git a/Help/command/install.rst b/Help/command/install.rst index a2e7491..b199147 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst
@@ -19,6 +19,7 @@ install(`SCRIPT`_ <file> [...]) install(`CODE`_ <code> [...]) install(`EXPORT`_ <export-name> [...]) + install(`PACKAGE_INFO`_ <package-name> [...]) install(`RUNTIME_DEPENDENCY_SET`_ <set-name> [...]) Introduction @@ -905,6 +906,61 @@ ``mp_myexe`` as if the target were built in its own tree. .. signature:: + install(PACKAGE_INFO <package-name> [...]) + + .. versionadded:: 3.31 + .. note:: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO``. + + Installs a |CPS|_ file exporting targets for dependent projects: + + .. code-block:: cmake + + install(PACKAGE_INFO <package-name> EXPORT <export-name> + [APPENDIX <appendix-name>] + [DESTINATION <dir>] + [LOWER_CASE_FILE] + [VERSION <version> + [COMPAT_VERSION <version>] + [VERSION_SCHEMA <string>]] + [DEFAULT_TARGETS <target>...] + [DEFAULT_CONFIGURATIONS <config>...] + [PERMISSIONS <permission>...] + [CONFIGURATIONS <config>...] + [COMPONENT <component>] + [EXCLUDE_FROM_ALL]) + + The ``PACKAGE_INFO`` form generates and installs a |CPS| file which describes + installed targets such that they can be consumed by another project. + Target installations are associated with the export ``<export-name>`` + using the ``EXPORT`` option of the :command:`install(TARGETS)` signature + documented above. Unlike :command:`install(EXPORT)`, this information is not + expressed in CMake code, and can be consumed by tools other than CMake. When + imported into another CMake project, the imported targets will be prefixed + with ``<package-name>::``. By default, the generated file will be called + ``<package-name>[-<appendix-name>].cps``. If ``LOWER_CASE_FILE`` is given, + the package name as it appears on disk (in both the file name and install + destination) will be first converted to lower case. + + If ``DESTINATION`` is not specified, a platform-specific default is used. + + If ``APPENDIX`` is specified, rather than generating a top level package + specification, the specified targets will be exported as an appendix to the + named package. Appendices may be used to separate less commonly used targets + (along with their external dependencies) from the rest of a package. This + enables consumers to ignore transitive dependencies for targets that they + don't use, and also allows a single logical "package" to be composed of + artifacts produced by multiple build trees. + + Appendices are not permitted to change basic package metadata; therefore, + none of ``VERSION``, ``COMPAT_VERSION``, ``VERSION_SCHEMA``, + ``DEFAULT_TARGETS`` or ``DEFAULT_CONFIGURATIONS`` may be specified in + combination with ``APPENDIX``. Additionally, it is strongly recommended that + use of ``LOWER_CASE_FILE`` should be consistent between the main package and + any appendices. + +.. signature:: install(RUNTIME_DEPENDENCY_SET <set-name> [...]) .. versionadded:: 3.21 @@ -1096,3 +1152,6 @@ This is an environment variable rather than a CMake variable. It allows you to change the installation prefix on UNIX systems. See :envvar:`DESTDIR` for details. + +.. _CPS: https://cps-org.github.io/cps/ +.. |CPS| replace:: Common Package Specification
diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst index 35ea34f..fb33112 100644 --- a/Help/dev/experimental.rst +++ b/Help/dev/experimental.rst
@@ -39,6 +39,23 @@ using the ``CMAKE_EXPORT_FIND_PACKAGE_NAME`` variable and/or ``EXPORT_FIND_PACKAGE_NAME`` target property. +Export |CPS| Package Information +================================ + +In order to activate support for this experimental feature, set + +* variable ``CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO`` to +* value ``b80be207-778e-46ba-8080-b23bba22639e``. + +This UUID may change in future versions of CMake. Be sure to use the value +documented here by the source tree of the version of CMake with which you are +experimenting. + +When activated, this experimental feature provides the following: + +* The experimental ``install(PACKAGE_INFO)`` command is available to export + package information in the |CPS|_ format. + C++ ``import std`` support ========================== @@ -60,3 +77,6 @@ * Targets with the property set to a true value and at least ``cxx_std_23`` may use ``import std;`` in any scanned C++ source file. + +.. _CPS: https://cps-org.github.io/cps/ +.. |CPS| replace:: Common Package Specification
diff --git a/Help/release/3.30.rst b/Help/release/3.30.rst index 2d57249..ca35d1f 100644 --- a/Help/release/3.30.rst +++ b/Help/release/3.30.rst
@@ -254,3 +254,11 @@ * These versions made no changes to documented features or interfaces. Some implementation updates were made to support ecosystem changes and/or fix regressions. + +.. 3.30.3 (unreleased) + + * The :module:`FindPython` and :module:`FindPython3` modules now define, + respectively, the ``Python_DEFINITIONS`` and ``Python3_DEFINITIONS`` + variables on Windows to support development with the free threaded + version of Python. The :prop_tgt:`INTERFACE_COMPILE_DEFINITIONS` target + property is also defined for the various targets provided by these modules.
diff --git a/Modules/CheckCCompilerFlag.cmake b/Modules/CheckCCompilerFlag.cmake index 696f7a3..0a658c4 100644 --- a/Modules/CheckCCompilerFlag.cmake +++ b/Modules/CheckCCompilerFlag.cmake
@@ -5,7 +5,7 @@ CheckCCompilerFlag ------------------ -Check whether the C compiler supports a given flag. +Check once whether the C compiler supports a given flag. .. command:: check_c_compiler_flag @@ -13,24 +13,25 @@ check_c_compiler_flag(<flag> <resultVar>) - Check that the ``<flag>`` is accepted by the compiler without - a diagnostic. Stores the result in an internal cache entry - named ``<resultVar>``. +Check once that the ``<flag>`` is accepted by the compiler without a diagnostic. +The result is stored in the internal cache variable specified by +``<resultVar>``, with boolean ``true`` for success and boolean ``false`` for +failure. -A positive result from this check indicates only that the compiler did not -issue a diagnostic message when given the flag. Whether the flag has any -effect or even a specific one is beyond the scope of this module. +``true`` indicates only that the compiler did not issue a diagnostic message +when given the flag. Whether the flag has any effect is beyond the scope of +this module. -The check is only performed once, with the result cached in the variable named -by ``<resultVar>``. Every subsequent CMake run will reuse this cached value -rather than performing the check again, even if the ``<code>`` changes. In -order to force the check to be re-evaluated, the variable named by -``<resultVar>`` must be manually removed from the cache. +Internally, :command:`try_compile` is used to perform the check. If +:variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` is set to ``EXECUTABLE`` (default), +the check compiles and links an executable program. If set to +``STATIC_LIBRARY``, the check is compiled but not linked. See also :command:`check_compiler_flag` for a more general command syntax. The compile and link commands can be influenced by setting any of the -following variables prior to calling ``check_c_compiler_flag()`` +following variables prior to calling ``check_c_compiler_flag()``. Unknown flags +in these variables can case a false negative result. .. include:: /module/CMAKE_REQUIRED_FLAGS.txt
diff --git a/Modules/CheckCXXCompilerFlag.cmake b/Modules/CheckCXXCompilerFlag.cmake index 90cd488..1465b9f 100644 --- a/Modules/CheckCXXCompilerFlag.cmake +++ b/Modules/CheckCXXCompilerFlag.cmake
@@ -5,7 +5,7 @@ CheckCXXCompilerFlag ------------------------ -Check whether the CXX compiler supports a given flag. +Check once whether the CXX compiler supports a given flag. .. command:: check_cxx_compiler_flag @@ -13,20 +13,37 @@ check_cxx_compiler_flag(<flag> <var>) - Check that the ``<flag>`` is accepted by the compiler without - a diagnostic. Stores the result in an internal cache entry - named ``<var>``. +Check once that the ``<flag>`` is accepted by the compiler without a diagnostic. +The result is stored in the internal cache variable specified by +``<resultVar>``, with boolean ``true`` for success and boolean ``false`` for +failure. -A positive result from this check indicates only that the compiler did not -issue a diagnostic message when given the flag. Whether the flag has any -effect or even a specific one is beyond the scope of this module. +``true`` indicates only that the compiler did not issue a diagnostic message +when given the flag. Whether the flag has any effect is beyond the scope of +this module. + +Internally, :command:`try_compile` is used to perform the check. If +:variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` is set to ``EXECUTABLE`` (default), +the check compiles and links an executable program. If set to +``STATIC_LIBRARY``, the check is compiled but not linked. See also :command:`check_compiler_flag` for a more general command syntax. -.. note:: - Since the :command:`try_compile` command forwards flags from variables - like :variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>`, unknown flags - in such variables may cause a false negative for this check. +The compile and link commands can be influenced by setting any of the +following variables prior to calling ``check_cxx_compiler_flag()``. Unknown flags +in these variables can case a false negative result. + +.. include:: /module/CMAKE_REQUIRED_FLAGS.txt + +.. include:: /module/CMAKE_REQUIRED_DEFINITIONS.txt + +.. include:: /module/CMAKE_REQUIRED_INCLUDES.txt + +.. include:: /module/CMAKE_REQUIRED_LINK_OPTIONS.txt + +.. include:: /module/CMAKE_REQUIRED_LIBRARIES.txt + +.. include:: /module/CMAKE_REQUIRED_QUIET.txt #]=======================================================================] include_guard(GLOBAL)
diff --git a/Modules/CheckCompilerFlag.cmake b/Modules/CheckCompilerFlag.cmake index 0f2ec4c..6252767 100644 --- a/Modules/CheckCompilerFlag.cmake +++ b/Modules/CheckCompilerFlag.cmake
@@ -7,7 +7,7 @@ .. versionadded:: 3.19 -Check whether the compiler supports a given flag. +Check once whether the ``<lang>`` compiler supports a given flag. .. command:: check_compiler_flag @@ -15,21 +15,23 @@ check_compiler_flag(<lang> <flag> <resultVar>) -Check that the ``<flag>`` is accepted by the compiler without a diagnostic. -Stores the result in an internal cache entry named ``<resultVar>``. +Check once that the ``<flag>`` is accepted by the ``<lang>`` compiler without +a diagnostic. The result is stored in the internal cache variable specified by +``<resultVar>``, with boolean ``true`` for success and boolean ``false`` for +failure. -A positive result from this check indicates only that the compiler did not -issue a diagnostic message when given the flag. Whether the flag has any -effect or even a specific one is beyond the scope of this module. +``true`` indicates only that the compiler did not issue a diagnostic message +when given the flag. Whether the flag has any effect is beyond the scope of +this module. -The check is only performed once, with the result cached in the variable named -by ``<resultVar>``. Every subsequent CMake run will reuse this cached value -rather than performing the check again, even if the ``<code>`` changes. In -order to force the check to be re-evaluated, the variable named by -``<resultVar>`` must be manually removed from the cache. +Internally, :command:`try_compile` is used to perform the check. If +:variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` is set to ``EXECUTABLE`` (default), +the check compiles and links an executable program. If set to +``STATIC_LIBRARY``, the check is compiled but not linked. The compile and link commands can be influenced by setting any of the -following variables prior to calling ``check_compiler_flag()`` +following variables prior to calling ``check_compiler_flag()``. Unknown flags +in these variables can case a false negative result. .. include:: /module/CMAKE_REQUIRED_FLAGS.txt
diff --git a/Modules/CheckFortranCompilerFlag.cmake b/Modules/CheckFortranCompilerFlag.cmake index 94090ef..7ab1247 100644 --- a/Modules/CheckFortranCompilerFlag.cmake +++ b/Modules/CheckFortranCompilerFlag.cmake
@@ -7,7 +7,7 @@ .. versionadded:: 3.3 -Check whether the Fortran compiler supports a given flag. +Check once whether the Fortran compiler supports a given flag. .. command:: check_fortran_compiler_flag @@ -15,24 +15,25 @@ check_fortran_compiler_flag(<flag> <resultVar>) - Check that the ``<flag>`` is accepted by the compiler without - a diagnostic. Stores the result in an internal cache entry - named ``<resultVar>``. +Check once that the ``<flag>`` is accepted by the compiler without a diagnostic. +The result is stored in the internal cache variable specified by +``<resultVar>``, with boolean ``true`` for success and boolean ``false`` for +failure. -A positive result from this check indicates only that the compiler did not -issue a diagnostic message when given the flag. Whether the flag has any -effect or even a specific one is beyond the scope of this module. +``true`` indicates only that the compiler did not issue a diagnostic message +when given the flag. Whether the flag has any effect is beyond the scope of +this module. -The check is only performed once, with the result cached in the variable named -by ``<resultVar>``. Every subsequent CMake run will reuse this cached value -rather than performing the check again, even if the ``<code>`` changes. In -order to force the check to be re-evaluated, the variable named by -``<resultVar>`` must be manually removed from the cache. +Internally, :command:`try_compile` is used to perform the check. If +:variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` is set to ``EXECUTABLE`` (default), +the check compiles and links an executable program. If set to +``STATIC_LIBRARY``, the check is compiled but not linked. See also :command:`check_compiler_flag` for a more general command syntax. The compile and link commands can be influenced by setting any of the -following variables prior to calling ``check_fortran_compiler_flag()`` +following variables prior to calling ``check_fortran_compiler_flag()``. Unknown +flags in these variables can case a false negative result. .. include:: /module/CMAKE_REQUIRED_FLAGS.txt
diff --git a/Modules/CheckFunctionExists.cmake b/Modules/CheckFunctionExists.cmake index e7c47a4..76fa76a 100644 --- a/Modules/CheckFunctionExists.cmake +++ b/Modules/CheckFunctionExists.cmake
@@ -5,7 +5,7 @@ CheckFunctionExists ------------------- -Check if a C function can be linked +Check once if a C function can be linked from system libraries. .. command:: check_function_exists @@ -14,8 +14,7 @@ check_function_exists(<function> <variable>) Checks that the ``<function>`` is provided by libraries on the system and store - the result in a ``<variable>``, which will be created as an internal - cache variable. + the result in internal cache variable ``<variable>``. The following variables may be set before calling this macro to modify the way the check is run: @@ -34,8 +33,8 @@ .. note:: - Prefer using :Module:`CheckSymbolExists` instead of this module, - for the following reasons: + Prefer using :module:`CheckSymbolExists` or :module:`CheckSourceCompiles` + instead of this module, for the following reasons: * ``check_function_exists()`` can't detect functions that are inlined in headers or specified as a macro.
diff --git a/Modules/CheckLibraryExists.cmake b/Modules/CheckLibraryExists.cmake index 8340500..d48d7ec 100644 --- a/Modules/CheckLibraryExists.cmake +++ b/Modules/CheckLibraryExists.cmake
@@ -5,7 +5,7 @@ CheckLibraryExists ------------------ -Check if the function exists. +Check once if the function exists in system or specified library. .. command:: CHECK_LIBRARY_EXISTS @@ -18,10 +18,11 @@ LIBRARY - the name of the library you are looking for FUNCTION - the name of the function LOCATION - location where the library should be found - VARIABLE - variable to store the result - Will be created as an internal cache variable. + VARIABLE - internal cache variable to store the result - +Prefer using :module:`CheckSymbolExists` or :module:`CheckSourceCompiles` +instead of this module for more robust detection if a function is available in +a library. The following variables may be set before calling this macro to modify the way the check is run:
diff --git a/Modules/CheckOBJCCompilerFlag.cmake b/Modules/CheckOBJCCompilerFlag.cmake index f87949b..102b137 100644 --- a/Modules/CheckOBJCCompilerFlag.cmake +++ b/Modules/CheckOBJCCompilerFlag.cmake
@@ -7,7 +7,7 @@ .. versionadded:: 3.16 -Check whether the Objective-C compiler supports a given flag. +Check once whether the Objective-C compiler supports a given flag. .. command:: check_objc_compiler_flag @@ -15,24 +15,25 @@ check_objc_compiler_flag(<flag> <resultVar>) - Check that the ``<flag>`` is accepted by the compiler without - a diagnostic. Stores the result in an internal cache entry - named ``<resultVar>``. +Check once that the ``<flag>`` is accepted by the compiler without a diagnostic. +The result is stored in the internal cache variable specified by +``<resultVar>``, with boolean ``true`` for success and boolean ``false`` for +failure. -A positive result from this check indicates only that the compiler did not -issue a diagnostic message when given the flag. Whether the flag has any -effect or even a specific one is beyond the scope of this module. +``true`` indicates only that the compiler did not issue a diagnostic message +when given the flag. Whether the flag has any effect is beyond the scope of +this module. -The check is only performed once, with the result cached in the variable named -by ``<resultVar>``. Every subsequent CMake run will reuse this cached value -rather than performing the check again, even if the ``<code>`` changes. In -order to force the check to be re-evaluated, the variable named by -``<resultVar>`` must be manually removed from the cache. +Internally, :command:`try_compile` is used to perform the check. If +:variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` is set to ``EXECUTABLE`` (default), +the check compiles and links an executable program. If set to +``STATIC_LIBRARY``, the check is compiled but not linked. See also :command:`check_compiler_flag` for a more general command syntax. The compile and link commands can be influenced by setting any of the -following variables prior to calling ``check_objc_compiler_flag()`` +following variables prior to calling ``check_objc_compiler_flag()``. Unknown +flags in these variables can case a false negative result. .. include:: /module/CMAKE_REQUIRED_FLAGS.txt
diff --git a/Modules/CheckOBJCXXCompilerFlag.cmake b/Modules/CheckOBJCXXCompilerFlag.cmake index 5091a75..21daa5c 100644 --- a/Modules/CheckOBJCXXCompilerFlag.cmake +++ b/Modules/CheckOBJCXXCompilerFlag.cmake
@@ -7,7 +7,7 @@ .. versionadded:: 3.16 -Check whether the Objective-C++ compiler supports a given flag. +Check once whether the Objective-C++ compiler supports a given flag. .. command:: check_objcxx_compiler_flag @@ -15,24 +15,25 @@ check_objcxx_compiler_flag(<flag> <resultVar>) - Check that the ``<flag>`` is accepted by the compiler without - a diagnostic. Stores the result in an internal cache entry - named ``<resultVar>``. +Check once that the ``<flag>`` is accepted by the compiler without a diagnostic. +The result is stored in the internal cache variable specified by +``<resultVar>``, with boolean ``true`` for success and boolean ``false`` for +failure. -A positive result from this check indicates only that the compiler did not -issue a diagnostic message when given the flag. Whether the flag has any -effect or even a specific one is beyond the scope of this module. +``true`` indicates only that the compiler did not issue a diagnostic message +when given the flag. Whether the flag has any effect is beyond the scope of +this module. -The check is only performed once, with the result cached in the variable named -by ``<resultVar>``. Every subsequent CMake run will reuse this cached value -rather than performing the check again, even if the ``<code>`` changes. In -order to force the check to be re-evaluated, the variable named by -``<resultVar>`` must be manually removed from the cache. +Internally, :command:`try_compile` is used to perform the check. If +:variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` is set to ``EXECUTABLE`` (default), +the check compiles and links an executable program. If set to +``STATIC_LIBRARY``, the check is compiled but not linked. See also :command:`check_compiler_flag` for a more general command syntax. The compile and link commands can be influenced by setting any of the -following variables prior to calling ``check_objcxx_compiler_flag()`` +following variables prior to calling ``check_objcxx_compiler_flag()``. Unknown +flags in these variables can case a false negative result. .. include:: /module/CMAKE_REQUIRED_FLAGS.txt
diff --git a/Modules/FindIconv.cmake b/Modules/FindIconv.cmake index 879ff16f..876af8d 100644 --- a/Modules/FindIconv.cmake +++ b/Modules/FindIconv.cmake
@@ -134,6 +134,8 @@ find_path(Iconv_INCLUDE_DIR NAMES "iconv.h" + PATH_SUFFIXES + gnu-libiconv # GNU libiconv on Alpine Linux has header in a subdirectory. DOC "iconv include directory") set(Iconv_LIBRARY_NAMES "iconv" "libiconv") mark_as_advanced(Iconv_INCLUDE_DIR)
diff --git a/Modules/FindPython.cmake b/Modules/FindPython.cmake index 7f11999..0c5958a 100644 --- a/Modules/FindPython.cmake +++ b/Modules/FindPython.cmake
@@ -224,6 +224,11 @@ The Python include directories. +``Python_DEFINITIONS`` + .. versionadded:: 3.30.3 + + The Python preprocessor definitions. + ``Python_DEBUG_POSTFIX`` .. versionadded.. 3.30
diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake index 1386117..35a1d67 100644 --- a/Modules/FindPython/Support.cmake +++ b/Modules/FindPython/Support.cmake
@@ -3740,6 +3740,14 @@ _${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE _${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG) endif() + + if (WIN32 AND _${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "t${CMAKE_IMPORT_LIBRARY_SUFFIX}$") + # On windows, header file is shared between the different implementations + # So Py_GIL_DISABLED should be set explicitly + set (${_PYTHON_PREFIX}_DEFINITIONS Py_GIL_DISABLED=1) + else() + unset (${_PYTHON_PREFIX}_DEFINITIONS) + endif() endif() if ("SABI_LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS) @@ -3769,6 +3777,14 @@ _${_PYTHON_PREFIX}_RUNTIME_SABI_LIBRARY_RELEASE _${_PYTHON_PREFIX}_RUNTIME_SABI_LIBRARY_DEBUG) endif() + + if (WIN32 AND _${_PYTHON_PREFIX}_SABI_LIBRARY_RELEASE MATCHES "t${CMAKE_IMPORT_LIBRARY_SUFFIX}$") + # On windows, header file is shared between the different implementations + # So Py_GIL_DISABLED should be set explicitly + set (${_PYTHON_PREFIX}_DEFINITIONS Py_GIL_DISABLED=1) + else() + unset (${_PYTHON_PREFIX}_DEFINITIONS) + endif() endif() if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE OR _${_PYTHON_PREFIX}_SABI_LIBRARY_RELEASE OR _${_PYTHON_PREFIX}_INCLUDE_DIR) @@ -3903,11 +3919,12 @@ # Workaround Intel MKL library outputting a message in stdout, which cause # incorrect detection of numpy.get_include() and numpy.__version__ - # See https://github.com/numpy/numpy/issues/23775 - if(DEFINED ENV{MKL_ENABLE_INSTRUCTIONS}) - set(_${_PYTHON_PREFIX}_BACKUP_ENV_VAR_MKL_ENABLE_INSTRUCTIONS ENV{MKL_ENABLE_INSTRUCTIONS}) + # See https://github.com/numpy/numpy/issues/23775 and + # https://gitlab.kitware.com/cmake/cmake/-/issues/26240 + if(NOT DEFINED ENV{MKL_ENABLE_INSTRUCTIONS}) + set(_${_PYTHON_PREFIX}_UNSET_ENV_VAR_MKL_ENABLE_INSTRUCTIONS YES) + set(ENV{MKL_ENABLE_INSTRUCTIONS} "SSE4_2") endif() - set(ENV{MKL_ENABLE_INSTRUCTIONS} "SSE4_2") if (NOT _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR) execute_process(COMMAND ${${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c @@ -3949,11 +3966,9 @@ set (${_PYTHON_PREFIX}_NumPy_FOUND FALSE) endif() - # Restore previous value of MKL_ENABLE_INSTRUCTIONS - if(DEFINED _${_PYTHON_PREFIX}_BACKUP_ENV_VAR_MKL_ENABLE_INSTRUCTIONS) - set(ENV{MKL_ENABLE_INSTRUCTIONS} ${_${_PYTHON_PREFIX}_BACKUP_ENV_VAR_MKL_ENABLE_INSTRUCTIONS}) - unset(_${_PYTHON_PREFIX}_BACKUP_ENV_VAR_MKL_ENABLE_INSTRUCTIONS) - else() + # Unset MKL_ENABLE_INSTRUCTIONS if set by us + if(DEFINED _${_PYTHON_PREFIX}_UNSET_ENV_VAR_MKL_ENABLE_INSTRUCTIONS) + unset(_${_PYTHON_PREFIX}_UNSET_ENV_VAR_MKL_ENABLE_INSTRUCTIONS) unset(ENV{MKL_ENABLE_INSTRUCTIONS}) endif() @@ -4067,6 +4082,12 @@ set_property (TARGET ${__name} PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIRS}") + if (${_PYTHON_PREFIX}_DEFINITIONS) + set_property (TARGET ${__name} + PROPERTY INTERFACE_COMPILE_DEFINITIONS "${${_PYTHON_PREFIX}_DEFINITIONS}") + endif() + + if (${_PYTHON_PREFIX}_${_PREFIX}LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_RUNTIME_${_PREFIX}LIBRARY_RELEASE) # System manage shared libraries in two parts: import and runtime if (${_PYTHON_PREFIX}_${_PREFIX}LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_${_PREFIX}LIBRARY_DEBUG) @@ -4123,6 +4144,11 @@ set_property (TARGET ${__name} PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIRS}") + if (${_PYTHON_PREFIX}_DEFINITIONS) + set_property (TARGET ${__name} + PROPERTY INTERFACE_COMPILE_DEFINITIONS "${${_PYTHON_PREFIX}_DEFINITIONS}") + endif() + # When available, enforce shared library generation with undefined symbols if (APPLE) set_property (TARGET ${__name}
diff --git a/Modules/FindPython3.cmake b/Modules/FindPython3.cmake index 5214583..9796828 100644 --- a/Modules/FindPython3.cmake +++ b/Modules/FindPython3.cmake
@@ -226,6 +226,11 @@ The Python 3 include directories. +``Python3_DEFINITIONS`` + .. versionadded:: 3.30.3 + + The Python 3 preprocessor definitions. + ``Python3_DEBUG_POSTFIX`` .. versionadded.. 3.30
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 6841f1d..67360bc 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt
@@ -217,6 +217,10 @@ cmExportInstallCMakeConfigGenerator.cxx cmExportInstallFileGenerator.h cmExportInstallFileGenerator.cxx + cmExportInstallPackageInfoGenerator.h + cmExportInstallPackageInfoGenerator.cxx + cmExportPackageInfoGenerator.h + cmExportPackageInfoGenerator.cxx cmExportTryCompileFileGenerator.h cmExportTryCompileFileGenerator.cxx cmExportSet.h @@ -336,6 +340,8 @@ cmInstallFilesGenerator.cxx cmInstallImportedRuntimeArtifactsGenerator.h cmInstallImportedRuntimeArtifactsGenerator.cxx + cmInstallPackageInfoExportGenerator.h + cmInstallPackageInfoExportGenerator.cxx cmInstallRuntimeDependencySet.h cmInstallRuntimeDependencySet.cxx cmInstallRuntimeDependencySetGenerator.h
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 530abaa..fe78b30 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 30) -set(CMake_VERSION_PATCH 20240827) +set(CMake_VERSION_PATCH 20240828) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/cmExperimental.cxx b/Source/cmExperimental.cxx index a2e6e70..4504c07 100644 --- a/Source/cmExperimental.cxx +++ b/Source/cmExperimental.cxx
@@ -46,6 +46,16 @@ {}, cmExperimental::TryCompileCondition::Always, false }, + // ExportPackageInfo + { "ExportPackageInfo", + "b80be207-778e-46ba-8080-b23bba22639e", + "CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO", + "CMake's support for exporting package information in the Common Package " + "Specification format. It is meant only for experimentation and feedback " + "to CMake developers.", + {}, + cmExperimental::TryCompileCondition::Always, + false }, }; static_assert(sizeof(LookupTable) / sizeof(LookupTable[0]) == static_cast<size_t>(cmExperimental::Feature::Sentinel),
diff --git a/Source/cmExperimental.h b/Source/cmExperimental.h index 05764f9..46a9bc4 100644 --- a/Source/cmExperimental.h +++ b/Source/cmExperimental.h
@@ -20,6 +20,7 @@ ExportPackageDependencies, WindowsKernelModeDriver, CxxImportStd, + ExportPackageInfo, Sentinel, };
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 24ed273..5e9461d 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx
@@ -331,6 +331,14 @@ } } +bool cmExportFileGenerator::NoteLinkedTarget( + cmGeneratorTarget const* /*target*/, std::string const& /*linkedName*/, + cmGeneratorTarget const* /*linkedTarget*/) +{ + // Default implementation does nothing; only needed by some generators. + return true; +} + bool cmExportFileGenerator::AddTargetNamespace(std::string& input, cmGeneratorTarget const* target, cmLocalGenerator const* lg) @@ -352,8 +360,9 @@ if (tgt->IsImported()) { input = tgt->GetName(); - return true; + return this->NoteLinkedTarget(target, input, tgt); } + if (this->ExportedTargets.find(tgt) != this->ExportedTargets.end()) { input = this->Namespace + tgt->GetExportName(); } else { @@ -365,7 +374,8 @@ input = tgt->GetName(); } } - return true; + + return this->NoteLinkedTarget(target, input, tgt); } void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index f765493..b1c9ce3 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h
@@ -95,6 +95,11 @@ std::string const& config, std::string const& suffix) = 0; + /** Record a target referenced by an exported target. */ + virtual bool NoteLinkedTarget(cmGeneratorTarget const* target, + std::string const& linkedName, + cmGeneratorTarget const* linkedTarget); + /** Each subclass knows how to deal with a target that is missing from an * export set. */ virtual void HandleMissingTarget(std::string& link_libs,
diff --git a/Source/cmExportInstallPackageInfoGenerator.cxx b/Source/cmExportInstallPackageInfoGenerator.cxx new file mode 100644 index 0000000..b9b715e --- /dev/null +++ b/Source/cmExportInstallPackageInfoGenerator.cxx
@@ -0,0 +1,197 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmExportInstallPackageInfoGenerator.h" + +#include <memory> +#include <set> +#include <utility> +#include <vector> + +#include <cm3p/json/value.h> + +#include "cmExportSet.h" +#include "cmGeneratorExpression.h" +#include "cmGeneratorTarget.h" +#include "cmInstallExportGenerator.h" +#include "cmLocalGenerator.h" +#include "cmMakefile.h" +#include "cmStateTypes.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" +#include "cmTarget.h" +#include "cmTargetExport.h" + +cmExportInstallPackageInfoGenerator::cmExportInstallPackageInfoGenerator( + cmInstallExportGenerator* iegen, std::string packageName, + std::string version, std::string versionCompat, std::string versionSchema, + std::vector<std::string> defaultTargets, + std::vector<std::string> defaultConfigurations) + : cmExportPackageInfoGenerator( + std::move(packageName), std::move(version), std::move(versionCompat), + std::move(versionSchema), std::move(defaultTargets), + std::move(defaultConfigurations)) + , cmExportInstallFileGenerator(iegen) +{ +} + +std::string cmExportInstallPackageInfoGenerator::GetConfigImportFileGlob() + const +{ + std::string glob = cmStrCat(this->FileBase, "@*", this->FileExt); + return glob; +} + +std::string const& cmExportInstallPackageInfoGenerator::GetExportName() const +{ + return this->GetPackageName(); +} + +bool cmExportInstallPackageInfoGenerator::GenerateMainFile(std::ostream& os) +{ + std::vector<cmTargetExport const*> allTargets; + { + auto visitor = [&](cmTargetExport const* te) { allTargets.push_back(te); }; + + if (!this->CollectExports(visitor)) { + return false; + } + } + + if (!this->CheckDefaultTargets()) { + return false; + } + + Json::Value root = this->GeneratePackageInfo(); + Json::Value& components = root["components"]; + + // Compute the relative import prefix for the file + std::string const& packagePath = this->GenerateImportPrefix(); + if (packagePath.empty()) { + return false; + } + root["cps_path"] = packagePath; + + bool requiresConfigFiles = false; + // Create all the imported targets. + for (cmTargetExport const* te : allTargets) { + cmGeneratorTarget* gt = te->Target; + cmStateEnums::TargetType targetType = this->GetExportTargetType(te); + + Json::Value* const component = + this->GenerateImportTarget(components, gt, targetType); + if (!component) { + return false; + } + + ImportPropertyMap properties; + if (!this->PopulateInterfaceProperties(te, properties)) { + return false; + } + this->PopulateInterfaceLinkLibrariesProperty( + gt, cmGeneratorExpression::InstallInterface, properties); + + if (targetType != cmStateEnums::INTERFACE_LIBRARY) { + requiresConfigFiles = true; + } + + // Set configuration-agnostic properties for component. + this->GenerateInterfaceProperties(*component, gt, properties); + } + + this->GeneratePackageRequires(root); + + // Write the primary packing information file. + this->WritePackageInfo(root, os); + + bool result = true; + + // Generate an import file for each configuration. + if (requiresConfigFiles) { + for (std::string const& c : this->Configurations) { + if (!this->GenerateImportFileConfig(c)) { + result = false; + } + } + } + + return result; +} + +void cmExportInstallPackageInfoGenerator::GenerateImportTargetsConfig( + std::ostream& os, std::string const& config, std::string const& suffix) +{ + Json::Value root; + root["name"] = this->GetPackageName(); + root["configuration"] = config; + + Json::Value& components = root["components"]; + + for (auto const& te : this->GetExportSet()->GetTargetExports()) { + // Collect import properties for this target. + if (this->GetExportTargetType(te.get()) == + cmStateEnums::INTERFACE_LIBRARY) { + continue; + } + + ImportPropertyMap properties; + std::set<std::string> importedLocations; + + this->PopulateImportProperties(config, suffix, te.get(), properties, + importedLocations); + + this->GenerateInterfaceConfigProperties(components, te->Target, suffix, + properties); + } + + this->WritePackageInfo(root, os); +} + +std::string cmExportInstallPackageInfoGenerator::GenerateImportPrefix() const +{ + std::string expDest = this->IEGen->GetDestination(); + if (cmSystemTools::FileIsFullPath(expDest)) { + std::string const& installPrefix = + this->IEGen->GetLocalGenerator()->GetMakefile()->GetSafeDefinition( + "CMAKE_INSTALL_PREFIX"); + if (cmHasPrefix(expDest, installPrefix)) { + auto n = installPrefix.length(); + while (n < expDest.length() && expDest[n] == '/') { + ++n; + } + expDest = expDest.substr(n); + } else { + this->ReportError( + cmStrCat("install(PACKAGE_INFO \"", this->GetExportName(), + "\" ...) specifies DESTINATION \"", expDest, + "\" which is not a subdirectory of the install prefix.")); + return {}; + } + } + + if (expDest.empty()) { + return this->GetInstallPrefix(); + } + return cmStrCat(this->GetImportPrefixWithSlash(), expDest); +} + +std::string cmExportInstallPackageInfoGenerator::InstallNameDir( + cmGeneratorTarget const* target, std::string const& config) +{ + std::string install_name_dir; + + cmMakefile* mf = target->Target->GetMakefile(); + if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { + install_name_dir = + target->GetInstallNameDirForInstallTree(config, "@prefix@"); + } + + return install_name_dir; +} + +std::string cmExportInstallPackageInfoGenerator::GetCxxModulesDirectory() const +{ + // TODO: Implement a not-CMake-specific mechanism for providing module + // information. + // return IEGen->GetCxxModuleDirectory(); + return {}; +}
diff --git a/Source/cmExportInstallPackageInfoGenerator.h b/Source/cmExportInstallPackageInfoGenerator.h new file mode 100644 index 0000000..5861b05 --- /dev/null +++ b/Source/cmExportInstallPackageInfoGenerator.h
@@ -0,0 +1,66 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <iosfwd> +#include <string> +#include <vector> + +#include "cmExportInstallFileGenerator.h" +#include "cmExportPackageInfoGenerator.h" + +class cmGeneratorTarget; +class cmInstallExportGenerator; + +/** \class cmExportInstallPackageInfoGenerator + * \brief Generate files exporting targets from an install tree. + * + * cmExportInstallPackageInfoGenerator generates files exporting targets from + * an installation tree. The files are placed in a temporary location for + * installation by cmInstallExportGenerator. The file format is the Common + * Package Specification (https://cps-org.github.io/cps/). + * + * One main file is generated that describes the imported targets. Additional, + * per-configuration files describe target locations and settings for each + * configuration. + * + * This is used to implement the INSTALL(PACKAGE_INFO) command. + */ +class cmExportInstallPackageInfoGenerator + : public cmExportPackageInfoGenerator + , public cmExportInstallFileGenerator +{ +public: + /** Construct with the export installer that will install the + files. */ + cmExportInstallPackageInfoGenerator( + cmInstallExportGenerator* iegen, std::string packageName, + std::string version, std::string versionCompat, std::string versionSchema, + std::vector<std::string> defaultTargets, + std::vector<std::string> defaultConfigurations); + + /** Compute the globbing expression used to load per-config import + files from the main file. */ + std::string GetConfigImportFileGlob() const override; + +protected: + std::string const& GetExportName() const override; + + // Implement virtual methods from the superclass. + bool GenerateMainFile(std::ostream& os) override; + void GenerateImportTargetsConfig(std::ostream& os, std::string const& config, + std::string const& suffix) override; + + char GetConfigFileNameSeparator() const override { return '@'; } + + /** Generate the cps_path, which determines the import prefix. */ + std::string GenerateImportPrefix() const; + + std::string InstallNameDir(cmGeneratorTarget const* target, + std::string const& config) override; + + std::string GetCxxModulesDirectory() const override; + // TODO: Generate C++ module info in a not-CMake-specific format. +};
diff --git a/Source/cmExportPackageInfoGenerator.cxx b/Source/cmExportPackageInfoGenerator.cxx new file mode 100644 index 0000000..7625953 --- /dev/null +++ b/Source/cmExportPackageInfoGenerator.cxx
@@ -0,0 +1,452 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmExportPackageInfoGenerator.h" + +#include <memory> +#include <set> +#include <utility> +#include <vector> + +#include <cm/string_view> +#include <cmext/algorithm> +#include <cmext/string_view> + +#include <cm3p/json/value.h> +#include <cm3p/json/writer.h> + +#include "cmExportSet.h" +#include "cmFindPackageStack.h" +#include "cmGeneratorExpression.h" +#include "cmGeneratorTarget.h" +#include "cmList.h" +#include "cmMakefile.h" +#include "cmMessageType.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" +#include "cmTarget.h" +#include "cmValue.h" + +constexpr char const* cmExportPackageInfoGenerator::CPS_VERSION_STR; + +cmExportPackageInfoGenerator::cmExportPackageInfoGenerator( + std::string packageName, std::string version, std::string versionCompat, + std::string versionSchema, std::vector<std::string> defaultTargets, + std::vector<std::string> defaultConfigurations) + : PackageName(std::move(packageName)) + , PackageVersion(std::move(version)) + , PackageVersionCompat(std::move(versionCompat)) + , PackageVersionSchema(std::move(versionSchema)) + , DefaultTargets(std::move(defaultTargets)) + , DefaultConfigurations(std::move(defaultConfigurations)) +{ +} + +cm::string_view cmExportPackageInfoGenerator::GetImportPrefixWithSlash() const +{ + return "@prefix@/"_s; +} + +bool cmExportPackageInfoGenerator::GenerateImportFile(std::ostream& os) +{ + return this->GenerateMainFile(os); +} + +void cmExportPackageInfoGenerator::WritePackageInfo( + Json::Value const& packageInfo, std::ostream& os) const +{ + Json::StreamWriterBuilder builder; + builder["indentation"] = " "; + builder["commentStyle"] = "None"; + std::unique_ptr<Json::StreamWriter> const writer(builder.newStreamWriter()); + writer->write(packageInfo, &os); +} + +namespace { +template <typename T> +void buildArray(Json::Value& object, std::string const& property, + T const& values) +{ + if (!values.empty()) { + Json::Value& array = object[property]; + for (auto const& item : values) { + array.append(item); + } + } +} +} + +bool cmExportPackageInfoGenerator::CheckDefaultTargets() const +{ + bool result = true; + std::set<std::string> exportedTargetNames; + for (auto const* te : this->ExportedTargets) { + exportedTargetNames.emplace(te->GetExportName()); + } + + for (auto const& name : this->DefaultTargets) { + if (!cm::contains(exportedTargetNames, name)) { + this->ReportError( + cmStrCat("Package \"", this->GetPackageName(), + "\" specifies DEFAULT_TARGETS \"", name, + "\", which is not a target in the export set \"", + this->GetExportSet()->GetName(), "\".")); + result = false; + } + } + + return result; +} + +Json::Value cmExportPackageInfoGenerator::GeneratePackageInfo() const +{ + Json::Value package; + + package["name"] = this->GetPackageName(); + package["cps_version"] = this->CPS_VERSION_STR; + + if (!this->PackageVersion.empty()) { + package["version"] = this->PackageVersion; + if (!this->PackageVersion.empty()) { + package["compat_version"] = this->PackageVersionCompat; + } + if (!this->PackageVersion.empty()) { + package["version_schema"] = this->PackageVersionSchema; + } + } + + buildArray(package, "default_components", this->DefaultTargets); + buildArray(package, "configurations", this->DefaultConfigurations); + + // TODO: description, website, license + + return package; +} + +void cmExportPackageInfoGenerator::GeneratePackageRequires( + Json::Value& package) const +{ + if (!this->Requirements.empty()) { + Json::Value& requirements = package["requires"]; + for (auto const& requirement : this->Requirements) { + // TODO: version, hint + requirements[requirement] = Json::Value{}; + } + } +} + +Json::Value* cmExportPackageInfoGenerator::GenerateImportTarget( + Json::Value& components, cmGeneratorTarget const* target, + cmStateEnums::TargetType targetType) const +{ + auto const& name = target->GetExportName(); + if (name.empty()) { + return nullptr; + } + + Json::Value& component = components[name]; + Json::Value& type = component["type"]; + switch (targetType) { + case cmStateEnums::EXECUTABLE: + type = "executable"; + break; + case cmStateEnums::STATIC_LIBRARY: + type = "archive"; + break; + case cmStateEnums::SHARED_LIBRARY: + type = "dylib"; + break; + case cmStateEnums::MODULE_LIBRARY: + type = "module"; + break; + case cmStateEnums::INTERFACE_LIBRARY: + type = "interface"; + break; + default: + type = "unknown"; + break; + } + return &component; +} + +bool cmExportPackageInfoGenerator::GenerateInterfaceProperties( + Json::Value& component, cmGeneratorTarget const* target, + ImportPropertyMap const& properties) const +{ + bool result = true; + + this->GenerateInterfaceLinkProperties(result, component, target, properties); + + this->GenerateInterfaceCompileFeatures(result, component, target, + properties); + this->GenerateInterfaceCompileDefines(result, component, target, properties); + + this->GenerateInterfaceListProperty(result, component, target, + "compile_flags", "COMPILE_OPTIONS"_s, + properties); + this->GenerateInterfaceListProperty(result, component, target, "link_flags", + "LINK_OPTIONS"_s, properties); + this->GenerateInterfaceListProperty(result, component, target, + "link_directories", "LINK_DIRECTORIES"_s, + properties); + this->GenerateInterfaceListProperty(result, component, target, "includes", + "INCLUDE_DIRECTORIES"_s, properties); + + // TODO: description, license + + return result; +} + +namespace { +bool forbidGeneratorExpressions(std::string const& propertyName, + std::string const& propertyValue, + cmGeneratorTarget const* target) +{ + std::string const& evaluatedValue = cmGeneratorExpression::Preprocess( + propertyValue, cmGeneratorExpression::StripAllGeneratorExpressions); + if (evaluatedValue != propertyValue) { + target->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Property \"", propertyName, "\" of target \"", + target->GetName(), + "\" contains a generator expression. This is not allowed.")); + return false; + } + return true; +} +} + +bool cmExportPackageInfoGenerator::NoteLinkedTarget( + cmGeneratorTarget const* target, std::string const& linkedName, + cmGeneratorTarget const* linkedTarget) +{ + if (cm::contains(this->ExportedTargets, linkedTarget)) { + // Target is internal to this package. + this->LinkTargets.emplace(linkedName, + cmStrCat(':', linkedTarget->GetExportName())); + return true; + } + + if (linkedTarget->IsImported()) { + // Target is imported from a found package. + auto pkgName = [linkedTarget]() -> std::string { + auto const& pkgStack = linkedTarget->Target->GetFindPackageStack(); + if (!pkgStack.Empty()) { + return pkgStack.Top().Name; + } + + return linkedTarget->Target->GetProperty("EXPORT_FIND_PACKAGE_NAME"); + }(); + + if (pkgName.empty()) { + target->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Target \"", target->GetName(), + "\" references imported target \"", linkedName, + "\" which does not come from any known package.")); + return false; + } + + auto const& prefix = cmStrCat(pkgName, "::"); + if (!cmHasPrefix(linkedName, prefix)) { + target->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Target \"", target->GetName(), "\" references target \"", + linkedName, "\", which comes from the \"", pkgName, + "\" package, but does not belong to the package's " + "canonical namespace. This is not allowed.")); + return false; + } + + // TODO: Record package version, hint. + this->Requirements.emplace(pkgName); + this->LinkTargets.emplace( + linkedName, cmStrCat(pkgName, ':', linkedName.substr(prefix.length()))); + return true; + } + + // Target belongs to another export from this build. + auto const& exportInfo = this->FindExportInfo(linkedTarget); + if (exportInfo.first.size() == 1) { + auto const& linkNamespace = exportInfo.second; + if (!cmHasSuffix(linkNamespace, "::")) { + target->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Target \"", target->GetName(), "\" references target \"", + linkedName, + "\", which does not use the standard namespace separator. " + "This is not allowed.")); + return false; + } + + auto pkgName = + cm::string_view{ linkNamespace.data(), linkNamespace.size() - 2 }; + + if (pkgName == this->GetPackageName()) { + this->LinkTargets.emplace(linkedName, + cmStrCat(':', linkedTarget->GetExportName())); + } else { + this->Requirements.emplace(pkgName); + this->LinkTargets.emplace( + linkedName, cmStrCat(pkgName, ':', linkedTarget->GetExportName())); + } + return true; + } + + // cmExportFileGenerator::HandleMissingTarget should have complained about + // this already. (In fact, we probably shouldn't ever get here.) + return false; +} + +void cmExportPackageInfoGenerator::GenerateInterfaceLinkProperties( + bool& result, Json::Value& component, cmGeneratorTarget const* target, + ImportPropertyMap const& properties) const +{ + auto const& iter = properties.find("INTERFACE_LINK_LIBRARIES"); + if (iter == properties.end()) { + return; + } + + // TODO: Support $<LINK_ONLY>. + if (!forbidGeneratorExpressions(iter->first, iter->second, target)) { + result = false; + return; + } + + std::vector<std::string> buildRequires; + // std::vector<std::string> linkRequires; TODO + std::vector<std::string> linkLibraries; + + for (auto const& name : cmList{ iter->second }) { + auto const& ti = this->LinkTargets.find(name); + if (ti != this->LinkTargets.end()) { + if (ti->second.empty()) { + result = false; + } else { + buildRequires.emplace_back(ti->second); + } + } else { + linkLibraries.emplace_back(name); + } + } + + buildArray(component, "requires", buildRequires); + // buildArray(component, "link_requires", linkRequires); TODO + buildArray(component, "link_libraries", linkLibraries); +} + +void cmExportPackageInfoGenerator::GenerateInterfaceCompileFeatures( + bool& result, Json::Value& component, cmGeneratorTarget const* target, + ImportPropertyMap const& properties) const +{ + auto const& iter = properties.find("INTERFACE_COMPILE_FEATURES"); + if (iter == properties.end()) { + return; + } + + if (!forbidGeneratorExpressions(iter->first, iter->second, target)) { + result = false; + return; + } + + std::set<std::string> features; + for (auto const& value : cmList{ iter->second }) { + if (cmHasLiteralPrefix(value, "c_std_")) { + auto suffix = cm::string_view{ value }.substr(6, 2); + features.emplace(cmStrCat("cxx", suffix)); + } else if (cmHasLiteralPrefix(value, "cxx_std_")) { + auto suffix = cm::string_view{ value }.substr(8, 2); + features.emplace(cmStrCat("c++", suffix)); + } + } + + buildArray(component, "compile_features", features); +} + +void cmExportPackageInfoGenerator::GenerateInterfaceCompileDefines( + bool& result, Json::Value& component, cmGeneratorTarget const* target, + ImportPropertyMap const& properties) const +{ + auto const& iter = properties.find("INTERFACE_COMPILE_DEFINITIONS"); + if (iter == properties.end()) { + return; + } + + // TODO: Support language-specific defines. + if (!forbidGeneratorExpressions(iter->first, iter->second, target)) { + result = false; + return; + } + + Json::Value defines; + for (auto const& def : cmList{ iter->second }) { + auto const n = def.find('='); + if (n == std::string::npos) { + defines[def] = Json::Value{}; + } else { + defines[def.substr(0, n)] = def.substr(n + 1); + } + } + + if (!defines.empty()) { + component["compile_definitions"]["*"] = std::move(defines); + } +} + +void cmExportPackageInfoGenerator::GenerateInterfaceListProperty( + bool& result, Json::Value& component, cmGeneratorTarget const* target, + std::string const& outName, cm::string_view inName, + ImportPropertyMap const& properties) const +{ + auto const& prop = cmStrCat("INTERFACE_", inName); + auto const& iter = properties.find(prop); + if (iter == properties.end()) { + return; + } + + if (!forbidGeneratorExpressions(prop, iter->second, target)) { + result = false; + return; + } + + Json::Value& array = component[outName]; + for (auto const& value : cmList{ iter->second }) { + array.append(value); + } +} + +void cmExportPackageInfoGenerator::GenerateInterfaceConfigProperties( + Json::Value& components, cmGeneratorTarget const* target, + std::string const& suffix, ImportPropertyMap const& properties) const +{ + Json::Value component; + auto const suffixLength = suffix.length(); + + for (auto const& p : properties) { + if (!cmHasSuffix(p.first, suffix)) { + continue; + } + auto const n = p.first.length() - suffixLength - 9; + auto const prop = cm::string_view{ p.first }.substr(9, n); + + if (prop == "LOCATION") { + component["location"] = p.second; + } else if (prop == "IMPLIB") { + component["link_location"] = p.second; + } else if (prop == "LINK_INTERFACE_LANGUAGES") { + std::vector<std::string> languages; + for (auto const& lang : cmList{ p.second }) { + auto ll = cmSystemTools::LowerCase(lang); + if (ll == "cxx") { + languages.emplace_back("cpp"); + } else { + languages.emplace_back(std::move(ll)); + } + } + buildArray(component, "link_languages", languages); + } + } + + if (!component.empty()) { + components[target->GetExportName()] = component; + } +}
diff --git a/Source/cmExportPackageInfoGenerator.h b/Source/cmExportPackageInfoGenerator.h new file mode 100644 index 0000000..1fb1703 --- /dev/null +++ b/Source/cmExportPackageInfoGenerator.h
@@ -0,0 +1,116 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <iosfwd> +#include <map> +#include <set> +#include <string> +#include <vector> + +#include <cm/string_view> + +#include "cmExportFileGenerator.h" +#include "cmStateTypes.h" + +class cmGeneratorTarget; +namespace Json { +class Value; +} + +/** \class cmExportPackageInfoGenerator + * \brief Generate Common Package Specification package information files + * exporting targets from a build or install tree. + * + * cmExportPackageInfoGenerator is the superclass for + * cmExportBuildPackageInfoGenerator and cmExportInstallPackageInfoGenerator. + * It contains common code generation routines for the two kinds of export + * implementations. + */ +class cmExportPackageInfoGenerator : virtual public cmExportFileGenerator +{ +public: + cmExportPackageInfoGenerator(std::string packageName, std::string version, + std::string versionCompat, + std::string versionSchema, + std::vector<std::string> defaultTargets, + std::vector<std::string> defaultConfigurations); + + using cmExportFileGenerator::GenerateImportFile; + +protected: + std::string const& GetPackageName() const { return this->PackageName; } + + void WritePackageInfo(Json::Value const& packageInfo, + std::ostream& os) const; + + // Methods to implement export file code generation. + bool GenerateImportFile(std::ostream& os) override; + + bool CheckDefaultTargets() const; + + Json::Value GeneratePackageInfo() const; + Json::Value* GenerateImportTarget(Json::Value& components, + cmGeneratorTarget const* target, + cmStateEnums::TargetType targetType) const; + + void GeneratePackageRequires(Json::Value& package) const; + + using ImportPropertyMap = std::map<std::string, std::string>; + bool GenerateInterfaceProperties(Json::Value& component, + cmGeneratorTarget const* target, + ImportPropertyMap const& properties) const; + void GenerateInterfaceConfigProperties( + Json::Value& components, cmGeneratorTarget const* target, + std::string const& suffix, ImportPropertyMap const& properties) const; + + cm::string_view GetImportPrefixWithSlash() const override; + + std::string GetCxxModuleFile(std::string const& /*name*/) const override + { + // TODO + return {}; + } + + void GenerateCxxModuleConfigInformation(std::string const& /*name*/, + std::ostream& /*os*/) const override + { + // TODO + } + + bool NoteLinkedTarget(cmGeneratorTarget const* target, + std::string const& linkedName, + cmGeneratorTarget const* linkedTarget) override; + +private: + void GenerateInterfaceLinkProperties( + bool& result, Json::Value& component, cmGeneratorTarget const* target, + ImportPropertyMap const& properties) const; + + void GenerateInterfaceCompileFeatures( + bool& result, Json::Value& component, cmGeneratorTarget const* target, + ImportPropertyMap const& properties) const; + + void GenerateInterfaceCompileDefines( + bool& result, Json::Value& component, cmGeneratorTarget const* target, + ImportPropertyMap const& properties) const; + + void GenerateInterfaceListProperty( + bool& result, Json::Value& component, cmGeneratorTarget const* target, + std::string const& outName, cm::string_view inName, + ImportPropertyMap const& properties) const; + + std::string const PackageName; + std::string const PackageVersion; + std::string const PackageVersionCompat; + std::string const PackageVersionSchema; + std::vector<std::string> DefaultTargets; + std::vector<std::string> DefaultConfigurations; + + std::map<std::string, std::string> LinkTargets; + std::set<std::string> Requirements; + + static constexpr char const* CPS_VERSION_STR = "0.12.0"; +};
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 3160585..f4cc4c3 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx
@@ -36,6 +36,7 @@ #include "cmInstallGenerator.h" #include "cmInstallGetRuntimeDependenciesGenerator.h" #include "cmInstallImportedRuntimeArtifactsGenerator.h" +#include "cmInstallPackageInfoExportGenerator.h" #include "cmInstallRuntimeDependencySet.h" #include "cmInstallRuntimeDependencySetGenerator.h" #include "cmInstallScriptGenerator.h" @@ -2162,6 +2163,143 @@ return true; } +bool HandlePackageInfoMode(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ +#ifndef CMAKE_BOOTSTRAP + if (!cmExperimental::HasSupportEnabled( + status.GetMakefile(), cmExperimental::Feature::ExportPackageInfo)) { + status.SetError("does not recognize sub-command PACKAGE_INFO"); + return false; + } + + Helper helper(status); + + // This is the PACKAGE_INFO mode. + cmInstallCommandArguments ica(helper.DefaultComponentName); + + ArgumentParser::NonEmpty<std::string> pkg; + ArgumentParser::NonEmpty<std::string> appendix; + ArgumentParser::NonEmpty<std::string> exportName; + bool lowerCase = false; + ArgumentParser::NonEmpty<std::string> version; + ArgumentParser::NonEmpty<std::string> versionCompat; + ArgumentParser::NonEmpty<std::string> versionSchema; + ArgumentParser::NonEmpty<std::vector<std::string>> defaultTargets; + ArgumentParser::NonEmpty<std::vector<std::string>> defaultConfigs; + ArgumentParser::NonEmpty<std::string> cxxModulesDirectory; + + // TODO: Support DESTINATION. + ica.Bind("PACKAGE_INFO"_s, pkg); + ica.Bind("EXPORT"_s, exportName); + ica.Bind("APPENDIX"_s, appendix); + ica.Bind("LOWER_CASE_FILE"_s, lowerCase); + ica.Bind("VERSION"_s, version); + ica.Bind("COMPAT_VERSION"_s, versionCompat); + ica.Bind("VERSION_SCHEMA"_s, versionSchema); + ica.Bind("DEFAULT_TARGETS"_s, defaultTargets); + ica.Bind("DEFAULT_CONFIGURATIONS"_s, defaultConfigs); + // ica.Bind("CXX_MODULES_DIRECTORY"_s, cxxModulesDirectory); TODO? + + std::vector<std::string> unknownArgs; + ica.Parse(args, &unknownArgs); + + if (!unknownArgs.empty()) { + // Unknown argument. + status.SetError( + cmStrCat(args[0], " given unknown argument \"", unknownArgs[0], "\".")); + return false; + } + + if (!ica.Finalize()) { + return false; + } + + if (exportName.empty()) { + status.SetError(cmStrCat(args[0], " missing EXPORT.")); + return false; + } + + if (version.empty()) { + if (!versionCompat.empty()) { + status.SetError("COMPAT_VERSION requires VERSION."); + return false; + } + if (!versionSchema.empty()) { + status.SetError("VERSION_SCHEMA requires VERSION."); + return false; + } + } else { + if (!appendix.empty()) { + status.SetError("APPENDIX and VERSION are mutually exclusive."); + return false; + } + } + if (!appendix.empty()) { + if (!defaultTargets.empty()) { + status.SetError("APPENDIX and DEFAULT_TARGETS are mutually exclusive."); + return false; + } + if (!defaultConfigs.empty()) { + status.SetError("APPENDIX and DEFAULT_CONFIGURATIONS " + "are mutually exclusive."); + return false; + } + } + + // Validate the package name. + if (!cmGeneratorExpression::IsValidTargetName(pkg) || + pkg.find(':') != std::string::npos) { + status.SetError( + cmStrCat(args[0], " given invalid package name \"", pkg, "\".")); + return false; + } + + // Construct the case-normalized package name and the file name. + std::string const pkgNameOnDisk = + (lowerCase ? cmSystemTools::LowerCase(pkg) : pkg); + std::string pkgFileName = [&]() -> std::string { + if (appendix.empty()) { + return cmStrCat(pkgNameOnDisk, ".cps"); + } + return cmStrCat(pkgNameOnDisk, '-', appendix, ".cps"); + }(); + + // Get or construct the destination path. + std::string dest = ica.GetDestination(); + if (dest.empty()) { + if (helper.Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "Windows") { + dest = std::string{ "cps"_s }; + } else { + dest = cmStrCat(helper.GetLibraryDestination(nullptr), "/cps/", + pkgNameOnDisk); + } + } + + cmExportSet& exportSet = + helper.Makefile->GetGlobalGenerator()->GetExportSets()[exportName]; + + cmInstallGenerator::MessageLevel message = + cmInstallGenerator::SelectMessageLevel(helper.Makefile); + + // Create the export install generator. + helper.Makefile->AddInstallGenerator( + cm::make_unique<cmInstallPackageInfoExportGenerator>( + &exportSet, dest, ica.GetPermissions(), ica.GetConfigurations(), + ica.GetComponent(), message, ica.GetExcludeFromAll(), + std::move(pkgFileName), std::move(pkg), std::move(version), + std::move(versionCompat), std::move(versionSchema), + std::move(defaultTargets), std::move(defaultConfigs), + std::move(cxxModulesDirectory), helper.Makefile->GetBacktrace())); + + return true; +#else + static_cast<void>(args); + status.SetError("PACKAGE_INFO not supported in bootstrap cmake"); + return false; +#endif +} + bool HandleRuntimeDependencySetMode(std::vector<std::string> const& args, cmExecutionStatus& status) { @@ -2525,6 +2663,7 @@ { "DIRECTORY"_s, HandleDirectoryMode }, { "EXPORT"_s, HandleExportMode }, { "EXPORT_ANDROID_MK"_s, HandleExportAndroidMKMode }, + { "PACKAGE_INFO"_s, HandlePackageInfoMode }, { "RUNTIME_DEPENDENCY_SET"_s, HandleRuntimeDependencySetMode }, };
diff --git a/Source/cmInstallPackageInfoExportGenerator.cxx b/Source/cmInstallPackageInfoExportGenerator.cxx new file mode 100644 index 0000000..4ff045b --- /dev/null +++ b/Source/cmInstallPackageInfoExportGenerator.cxx
@@ -0,0 +1,36 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmInstallPackageInfoExportGenerator.h" + +#include <utility> + +#include <cm/memory> + +#include "cmExportInstallFileGenerator.h" +#include "cmExportInstallPackageInfoGenerator.h" +#include "cmListFileCache.h" + +class cmExportSet; + +cmInstallPackageInfoExportGenerator::cmInstallPackageInfoExportGenerator( + cmExportSet* exportSet, std::string destination, std::string filePermissions, + std::vector<std::string> const& configurations, std::string component, + MessageLevel message, bool excludeFromAll, std::string filename, + std::string packageName, std::string version, std::string versionCompat, + std::string versionSchema, std::vector<std::string> defaultTargets, + std::vector<std::string> defaultConfigurations, + std::string cxxModulesDirectory, cmListFileBacktrace backtrace) + : cmInstallExportGenerator( + exportSet, std::move(destination), std::move(filePermissions), + configurations, std::move(component), message, excludeFromAll, + std::move(filename), packageName + "::", std::move(cxxModulesDirectory), + std::move(backtrace)) +{ + this->EFGen = cm::make_unique<cmExportInstallPackageInfoGenerator>( + this, std::move(packageName), std::move(version), std::move(versionCompat), + std::move(versionSchema), std::move(defaultTargets), + std::move(defaultConfigurations)); +} + +cmInstallPackageInfoExportGenerator::~cmInstallPackageInfoExportGenerator() = + default;
diff --git a/Source/cmInstallPackageInfoExportGenerator.h b/Source/cmInstallPackageInfoExportGenerator.h new file mode 100644 index 0000000..c79df84 --- /dev/null +++ b/Source/cmInstallPackageInfoExportGenerator.h
@@ -0,0 +1,36 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include <string> +#include <vector> + +#include "cmInstallExportGenerator.h" + +class cmExportSet; +class cmListFileBacktrace; + +/** \class cmInstallPackageInfoGenerator + * \brief Generate rules for creating CPS package info files. + */ +class cmInstallPackageInfoExportGenerator : public cmInstallExportGenerator +{ +public: + cmInstallPackageInfoExportGenerator( + cmExportSet* exportSet, std::string destination, + std::string filePermissions, + std::vector<std::string> const& configurations, std::string component, + MessageLevel message, bool excludeFromAll, std::string filename, + std::string packageName, std::string version, std::string versionCompat, + std::string versionSchema, std::vector<std::string> defaultTargets, + std::vector<std::string> defaultConfigurations, + std::string cxxModulesDirectory, cmListFileBacktrace backtrace); + cmInstallPackageInfoExportGenerator( + cmInstallPackageInfoExportGenerator const&) = delete; + ~cmInstallPackageInfoExportGenerator() override; + + cmInstallPackageInfoExportGenerator& operator=( + cmInstallPackageInfoExportGenerator const&) = delete; + + char const* InstallSubcommand() const override { return "PACKAGE_INFO"; } +};
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 1f7b8c5..65295cc 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt
@@ -1177,6 +1177,7 @@ ) add_RunCMake_test(AndroidMK) +add_RunCMake_test(PackageInfo) if(CMake_TEST_ANDROID_NDK OR CMake_TEST_ANDROID_STANDALONE_TOOLCHAIN) if(NOT "${CMAKE_GENERATOR}" MATCHES "Make|Ninja|Visual Studio 1[456]")
diff --git a/Tests/RunCMake/PackageInfo/Appendix-check.cmake b/Tests/RunCMake/PackageInfo/Appendix-check.cmake new file mode 100644 index 0000000..864e731 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/Appendix-check.cmake
@@ -0,0 +1,16 @@ +include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake) + +set(out_dir "${RunCMake_BINARY_DIR}/Appendix-build/CMakeFiles/Export/510c5684a4a8a792eadfb55bc9744983") + +file(READ "${out_dir}/foo.cps" content) +expect_value("${content}" "foo" "name") +expect_value("${content}" "interface" "components" "mammal" "type") +expect_value("${content}" "1.0" "version") + +file(READ "${out_dir}/foo-dog.cps" content) +expect_value("${content}" "foo" "name") +expect_value("${content}" "interface" "components" "canine" "type") +expect_missing("${content}" "version") + +expect_array("${content}" 1 "components" "canine" "requires") +expect_value("${content}" ":mammal" "components" "canine" "requires" 0)
diff --git a/Tests/RunCMake/PackageInfo/Appendix.cmake b/Tests/RunCMake/PackageInfo/Appendix.cmake new file mode 100644 index 0000000..fe67778 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/Appendix.cmake
@@ -0,0 +1,9 @@ +add_library(mammal INTERFACE) +add_library(canine INTERFACE) +target_link_libraries(canine INTERFACE mammal) + +install(TARGETS mammal EXPORT mammal DESTINATION .) +install(TARGETS canine EXPORT canine DESTINATION .) + +install(PACKAGE_INFO foo DESTINATION cps EXPORT mammal VERSION 1.0) +install(PACKAGE_INFO foo DESTINATION cps EXPORT canine APPENDIX dog)
diff --git a/Tests/RunCMake/PackageInfo/Assertions.cmake b/Tests/RunCMake/PackageInfo/Assertions.cmake new file mode 100644 index 0000000..8157618 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/Assertions.cmake
@@ -0,0 +1,34 @@ +macro(_expect entity op actual expected) + if(NOT "${actual}" ${op} "${expected}") + list(JOIN ARGN "." name) + set(RunCMake_TEST_FAILED + "Attribute '${name}' ${entity} '${actual}' does not match expected ${entity} '${expected}'" PARENT_SCOPE) + return() + endif() +endmacro() + +function(expect_value content expected_value) + string(JSON actual_value GET "${content}" ${ARGN}) + _expect("value" STREQUAL "${actual_value}" "${expected_value}" ${ARGN}) +endfunction() + +function(expect_array content expected_length) + string(JSON actual_type TYPE "${content}" ${ARGN}) + _expect("type" STREQUAL "${actual_type}" "ARRAY" ${ARGN}) + + string(JSON actual_length LENGTH "${content}" ${ARGN}) + _expect("length" EQUAL "${actual_length}" "${expected_length}" ${ARGN}) +endfunction() + +function(expect_null content) + string(JSON actual_type TYPE "${content}" ${ARGN}) + _expect("type" STREQUAL "${actual_type}" "NULL" ${ARGN}) +endfunction() + +function(expect_missing content) + string(JSON value ERROR_VARIABLE error GET "${content}" ${ARGN}) + if(NOT value MATCHES "^(.*-)?NOTFOUND$") + set(RunCMake_TEST_FAILED + "Attribute '${ARGN}' is unexpectedly present" PARENT_SCOPE) + endif() +endfunction()
diff --git a/Tests/RunCMake/PackageInfo/BadArgs1-result.txt b/Tests/RunCMake/PackageInfo/BadArgs1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadArgs1-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/PackageInfo/BadArgs1-stderr.txt b/Tests/RunCMake/PackageInfo/BadArgs1-stderr.txt new file mode 100644 index 0000000..92ba6fb --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadArgs1-stderr.txt
@@ -0,0 +1,2 @@ +CMake Error at BadArgs1.cmake:3 \(install\): + install COMPAT_VERSION requires VERSION.
diff --git a/Tests/RunCMake/PackageInfo/BadArgs1.cmake b/Tests/RunCMake/PackageInfo/BadArgs1.cmake new file mode 100644 index 0000000..b99997c --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadArgs1.cmake
@@ -0,0 +1,3 @@ +add_library(foo INTERFACE) +install(TARGETS foo EXPORT foo DESTINATION .) +install(PACKAGE_INFO test EXPORT foo COMPAT_VERSION 1.0)
diff --git a/Tests/RunCMake/PackageInfo/BadArgs2-result.txt b/Tests/RunCMake/PackageInfo/BadArgs2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadArgs2-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/PackageInfo/BadArgs2-stderr.txt b/Tests/RunCMake/PackageInfo/BadArgs2-stderr.txt new file mode 100644 index 0000000..636335c --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadArgs2-stderr.txt
@@ -0,0 +1,2 @@ +CMake Error at BadArgs2.cmake:3 \(install\): + install VERSION_SCHEMA requires VERSION.
diff --git a/Tests/RunCMake/PackageInfo/BadArgs2.cmake b/Tests/RunCMake/PackageInfo/BadArgs2.cmake new file mode 100644 index 0000000..265d93c --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadArgs2.cmake
@@ -0,0 +1,3 @@ +add_library(foo INTERFACE) +install(TARGETS foo EXPORT foo DESTINATION .) +install(PACKAGE_INFO test EXPORT foo VERSION_SCHEMA simple)
diff --git a/Tests/RunCMake/PackageInfo/BadArgs3-result.txt b/Tests/RunCMake/PackageInfo/BadArgs3-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadArgs3-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/PackageInfo/BadArgs3-stderr.txt b/Tests/RunCMake/PackageInfo/BadArgs3-stderr.txt new file mode 100644 index 0000000..11e1a8c --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadArgs3-stderr.txt
@@ -0,0 +1,2 @@ +CMake Error at BadArgs3.cmake:3 \(install\): + install APPENDIX and VERSION are mutually exclusive.
diff --git a/Tests/RunCMake/PackageInfo/BadArgs3.cmake b/Tests/RunCMake/PackageInfo/BadArgs3.cmake new file mode 100644 index 0000000..5f57f6a --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadArgs3.cmake
@@ -0,0 +1,3 @@ +add_library(foo INTERFACE) +install(TARGETS foo EXPORT foo DESTINATION .) +install(PACKAGE_INFO test EXPORT foo APPENDIX test VERSION 1.0)
diff --git a/Tests/RunCMake/PackageInfo/BadArgs4-result.txt b/Tests/RunCMake/PackageInfo/BadArgs4-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadArgs4-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/PackageInfo/BadArgs4-stderr.txt b/Tests/RunCMake/PackageInfo/BadArgs4-stderr.txt new file mode 100644 index 0000000..067a07b --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadArgs4-stderr.txt
@@ -0,0 +1,2 @@ +CMake Error at BadArgs4.cmake:3 \(install\): + install APPENDIX and DEFAULT_TARGETS are mutually exclusive.
diff --git a/Tests/RunCMake/PackageInfo/BadArgs4.cmake b/Tests/RunCMake/PackageInfo/BadArgs4.cmake new file mode 100644 index 0000000..426d10b --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadArgs4.cmake
@@ -0,0 +1,3 @@ +add_library(foo INTERFACE) +install(TARGETS foo EXPORT foo DESTINATION .) +install(PACKAGE_INFO test EXPORT foo APPENDIX test DEFAULT_TARGETS foo)
diff --git a/Tests/RunCMake/PackageInfo/BadArgs5-result.txt b/Tests/RunCMake/PackageInfo/BadArgs5-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadArgs5-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/PackageInfo/BadArgs5-stderr.txt b/Tests/RunCMake/PackageInfo/BadArgs5-stderr.txt new file mode 100644 index 0000000..4f7d285 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadArgs5-stderr.txt
@@ -0,0 +1,2 @@ +CMake Error at BadArgs5.cmake:3 \(install\): + install APPENDIX and DEFAULT_CONFIGURATIONS are mutually exclusive.
diff --git a/Tests/RunCMake/PackageInfo/BadArgs5.cmake b/Tests/RunCMake/PackageInfo/BadArgs5.cmake new file mode 100644 index 0000000..356c856 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadArgs5.cmake
@@ -0,0 +1,3 @@ +add_library(foo INTERFACE) +install(TARGETS foo EXPORT foo DESTINATION .) +install(PACKAGE_INFO test EXPORT foo APPENDIX test DEFAULT_CONFIGURATIONS test)
diff --git a/Tests/RunCMake/PackageInfo/BadDefaultTarget-result.txt b/Tests/RunCMake/PackageInfo/BadDefaultTarget-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadDefaultTarget-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/PackageInfo/BadDefaultTarget-stderr.txt b/Tests/RunCMake/PackageInfo/BadDefaultTarget-stderr.txt new file mode 100644 index 0000000..6467a14 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadDefaultTarget-stderr.txt
@@ -0,0 +1,2 @@ +CMake Error: Package "test" specifies DEFAULT_TARGETS "dog", which is not a target in the export set "foo". +CMake Error: Package "test" specifies DEFAULT_TARGETS "cat", which is not a target in the export set "foo".
diff --git a/Tests/RunCMake/PackageInfo/BadDefaultTarget.cmake b/Tests/RunCMake/PackageInfo/BadDefaultTarget.cmake new file mode 100644 index 0000000..d3d993a --- /dev/null +++ b/Tests/RunCMake/PackageInfo/BadDefaultTarget.cmake
@@ -0,0 +1,5 @@ +add_library(foo INTERFACE) +add_library(dog INTERFACE) +install(TARGETS foo EXPORT foo DESTINATION .) +install(TARGETS dog EXPORT dog DESTINATION .) +install(PACKAGE_INFO test EXPORT foo DEFAULT_TARGETS dog cat)
diff --git a/Tests/RunCMake/PackageInfo/CMakeLists.txt b/Tests/RunCMake/PackageInfo/CMakeLists.txt new file mode 100644 index 0000000..dda37d8 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/CMakeLists.txt
@@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.30) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/PackageInfo/ExperimentalGate-result.txt b/Tests/RunCMake/PackageInfo/ExperimentalGate-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/PackageInfo/ExperimentalGate-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/PackageInfo/ExperimentalGate-stderr.txt b/Tests/RunCMake/PackageInfo/ExperimentalGate-stderr.txt new file mode 100644 index 0000000..40799b7 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/ExperimentalGate-stderr.txt
@@ -0,0 +1,2 @@ +CMake Error at ExperimentalGate.cmake:5 \(install\): + install does not recognize sub-command PACKAGE_INFO
diff --git a/Tests/RunCMake/PackageInfo/ExperimentalGate.cmake b/Tests/RunCMake/PackageInfo/ExperimentalGate.cmake new file mode 100644 index 0000000..327d3bb --- /dev/null +++ b/Tests/RunCMake/PackageInfo/ExperimentalGate.cmake
@@ -0,0 +1,5 @@ +unset(CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO) + +add_library(foo INTERFACE) +install(TARGETS foo EXPORT foo DESTINATION .) +install(PACKAGE_INFO foo DESTINATION cps EXPORT foo)
diff --git a/Tests/RunCMake/PackageInfo/ExperimentalWarning-stderr.txt b/Tests/RunCMake/PackageInfo/ExperimentalWarning-stderr.txt new file mode 100644 index 0000000..960d541 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/ExperimentalWarning-stderr.txt
@@ -0,0 +1,7 @@ +CMake Warning \(dev\) at ExperimentalWarning.cmake:8 \(install\): + CMake's support for exporting package information in the Common Package + Specification format. It is meant only for experimentation and feedback to + CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/PackageInfo/ExperimentalWarning.cmake b/Tests/RunCMake/PackageInfo/ExperimentalWarning.cmake new file mode 100644 index 0000000..df6604c --- /dev/null +++ b/Tests/RunCMake/PackageInfo/ExperimentalWarning.cmake
@@ -0,0 +1,8 @@ +set( + CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO + "b80be207-778e-46ba-8080-b23bba22639e" + ) + +add_library(foo INTERFACE) +install(TARGETS foo EXPORT foo DESTINATION .) +install(PACKAGE_INFO foo DESTINATION cps EXPORT foo)
diff --git a/Tests/RunCMake/PackageInfo/InterfaceProperties-check.cmake b/Tests/RunCMake/PackageInfo/InterfaceProperties-check.cmake new file mode 100644 index 0000000..2c3272e --- /dev/null +++ b/Tests/RunCMake/PackageInfo/InterfaceProperties-check.cmake
@@ -0,0 +1,24 @@ +include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake) + +set(out_dir "${RunCMake_BINARY_DIR}/InterfaceProperties-build/CMakeFiles/Export/510c5684a4a8a792eadfb55bc9744983") + +file(READ "${out_dir}/foo.cps" content) +expect_value("${content}" "foo" "name") + +string(JSON component GET "${content}" "components" "foo") + +expect_value("${component}" "interface" "type") +expect_array("${component}" 1 "includes") +expect_value("${component}" "@prefix@/include/foo" "includes" 0) +expect_array("${component}" 1 "compile_features") +expect_value("${component}" "c++23" "compile_features" 0) +expect_array("${component}" 1 "compile_flags") +expect_value("${component}" "-ffast-math" "compile_flags" 0) +expect_null("${component}" "compile_definitions" "*" "FOO") +expect_value("${component}" "BAR" "compile_definitions" "*" "BAR") +expect_array("${component}" 1 "link_directories") +expect_value("${component}" "/opt/foo/lib" "link_directories" 0) +expect_array("${component}" 1 "link_flags") +expect_value("${component}" "--needed" "link_flags" 0) +expect_array("${component}" 1 "link_libraries") +expect_value("${component}" "/usr/lib/libm.so" "link_libraries" 0)
diff --git a/Tests/RunCMake/PackageInfo/InterfaceProperties.cmake b/Tests/RunCMake/PackageInfo/InterfaceProperties.cmake new file mode 100644 index 0000000..42edc21 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/InterfaceProperties.cmake
@@ -0,0 +1,15 @@ +add_library(foo INTERFACE) + +target_compile_features(foo INTERFACE cxx_std_23) +target_compile_options(foo INTERFACE -ffast-math) +target_compile_definitions(foo INTERFACE -DFOO -DBAR=BAR) +target_include_directories( + foo INTERFACE + $<INSTALL_INTERFACE:include/foo> + ) +target_link_directories(foo INTERFACE /opt/foo/lib) +target_link_options(foo INTERFACE --needed) +target_link_libraries(foo INTERFACE /usr/lib/libm.so) + +install(TARGETS foo EXPORT foo DESTINATION .) +install(PACKAGE_INFO foo DESTINATION cps EXPORT foo)
diff --git a/Tests/RunCMake/PackageInfo/LowerCaseFile-check.cmake b/Tests/RunCMake/PackageInfo/LowerCaseFile-check.cmake new file mode 100644 index 0000000..d8de372 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/LowerCaseFile-check.cmake
@@ -0,0 +1,9 @@ +include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake) + +set(out_dir "${RunCMake_BINARY_DIR}/LowerCaseFile-build/CMakeFiles/Export/510c5684a4a8a792eadfb55bc9744983") + +file(READ "${out_dir}/lowercase.cps" content) +expect_value("${content}" "LowerCase" "name") + +file(READ "${out_dir}/PreserveCase.cps" content) +expect_value("${content}" "PreserveCase" "name")
diff --git a/Tests/RunCMake/PackageInfo/LowerCaseFile.cmake b/Tests/RunCMake/PackageInfo/LowerCaseFile.cmake new file mode 100644 index 0000000..dc6827f --- /dev/null +++ b/Tests/RunCMake/PackageInfo/LowerCaseFile.cmake
@@ -0,0 +1,4 @@ +add_library(foo INTERFACE) +install(TARGETS foo EXPORT foo DESTINATION .) +install(PACKAGE_INFO LowerCase DESTINATION cps EXPORT foo LOWER_CASE_FILE) +install(PACKAGE_INFO PreserveCase DESTINATION cps EXPORT foo)
diff --git a/Tests/RunCMake/PackageInfo/Metadata-check.cmake b/Tests/RunCMake/PackageInfo/Metadata-check.cmake new file mode 100644 index 0000000..8db8c29 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/Metadata-check.cmake
@@ -0,0 +1,16 @@ +include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake) + +set(out_dir "${RunCMake_BINARY_DIR}/Metadata-build/CMakeFiles/Export/510c5684a4a8a792eadfb55bc9744983") + +file(READ "${out_dir}/foo.cps" content) +expect_value("${content}" "foo" "name") +expect_value("${content}" "1.2.3" "version") +expect_value("${content}" "1.2.0" "compat_version") +expect_value("${content}" "simple" "version_schema") + +expect_array("${content}" 1 "default_components") +expect_value("${content}" "foo" "default_components" 0) + +expect_array("${content}" 2 "configurations") +expect_value("${content}" "release" "configurations" 0) +expect_value("${content}" "debug" "configurations" 1)
diff --git a/Tests/RunCMake/PackageInfo/Metadata.cmake b/Tests/RunCMake/PackageInfo/Metadata.cmake new file mode 100644 index 0000000..f8fc9b8 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/Metadata.cmake
@@ -0,0 +1,12 @@ +add_library(foo INTERFACE) +install(TARGETS foo EXPORT foo DESTINATION .) +install( + PACKAGE_INFO foo + DESTINATION cps + EXPORT foo + VERSION 1.2.3 + VERSION_SCHEMA simple + COMPAT_VERSION 1.2.0 + DEFAULT_TARGETS foo + DEFAULT_CONFIGURATIONS release debug + )
diff --git a/Tests/RunCMake/PackageInfo/Minimal-check.cmake b/Tests/RunCMake/PackageInfo/Minimal-check.cmake new file mode 100644 index 0000000..9608ed8 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/Minimal-check.cmake
@@ -0,0 +1,18 @@ +include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake) + +set(out_dir "${RunCMake_BINARY_DIR}/Minimal-build/CMakeFiles/Export/510c5684a4a8a792eadfb55bc9744983") + +file(READ "${out_dir}/foo.cps" content) +expect_value("${content}" "foo" "name") +expect_value("${content}" "interface" "components" "foo" "type") +expect_missing("${content}" "version") +expect_missing("${content}" "configurations") +expect_missing("${content}" "default_targets") +expect_missing("${content}" "components" "foo" "compile_definitions") +expect_missing("${content}" "components" "foo" "compile_features") +expect_missing("${content}" "components" "foo" "compile_flags") +expect_missing("${content}" "components" "foo" "link_directories") +expect_missing("${content}" "components" "foo" "link_features") +expect_missing("${content}" "components" "foo" "link_flags") +expect_missing("${content}" "components" "foo" "link_libraries") +expect_missing("${content}" "components" "foo" "requires")
diff --git a/Tests/RunCMake/PackageInfo/Minimal.cmake b/Tests/RunCMake/PackageInfo/Minimal.cmake new file mode 100644 index 0000000..6c060b9 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/Minimal.cmake
@@ -0,0 +1,3 @@ +add_library(foo INTERFACE) +install(TARGETS foo EXPORT foo DESTINATION .) +install(PACKAGE_INFO foo DESTINATION cps EXPORT foo)
diff --git a/Tests/RunCMake/PackageInfo/ReferencesNonExportedTarget-result.txt b/Tests/RunCMake/PackageInfo/ReferencesNonExportedTarget-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/PackageInfo/ReferencesNonExportedTarget-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/PackageInfo/ReferencesNonExportedTarget-stderr.txt b/Tests/RunCMake/PackageInfo/ReferencesNonExportedTarget-stderr.txt new file mode 100644 index 0000000..c68d518 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/ReferencesNonExportedTarget-stderr.txt
@@ -0,0 +1 @@ +CMake Error: install\(PACKAGE_INFO "dog" \.\.\.\) includes target "canine" which requires target "mammal" that is not in any export set.
diff --git a/Tests/RunCMake/PackageInfo/ReferencesNonExportedTarget.cmake b/Tests/RunCMake/PackageInfo/ReferencesNonExportedTarget.cmake new file mode 100644 index 0000000..a835582 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/ReferencesNonExportedTarget.cmake
@@ -0,0 +1,6 @@ +add_library(mammal INTERFACE) +add_library(canine INTERFACE) +target_link_libraries(canine INTERFACE mammal) + +install(TARGETS canine EXPORT dog DESTINATION .) +install(PACKAGE_INFO dog EXPORT dog)
diff --git a/Tests/RunCMake/PackageInfo/ReferencesWronglyExportedTarget-result.txt b/Tests/RunCMake/PackageInfo/ReferencesWronglyExportedTarget-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/PackageInfo/ReferencesWronglyExportedTarget-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/PackageInfo/ReferencesWronglyExportedTarget-stderr.txt b/Tests/RunCMake/PackageInfo/ReferencesWronglyExportedTarget-stderr.txt new file mode 100644 index 0000000..0a74e18 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/ReferencesWronglyExportedTarget-stderr.txt
@@ -0,0 +1,7 @@ +CMake Error in CMakeLists.txt: + Target "test" references target "foo", which does not use the standard + namespace separator. This is not allowed. +.* +CMake Error in CMakeLists.txt: + Target "test" references target "bar_bar", which does not use the standard + namespace separator. This is not allowed.
diff --git a/Tests/RunCMake/PackageInfo/ReferencesWronglyExportedTarget.cmake b/Tests/RunCMake/PackageInfo/ReferencesWronglyExportedTarget.cmake new file mode 100644 index 0000000..3e3d21d --- /dev/null +++ b/Tests/RunCMake/PackageInfo/ReferencesWronglyExportedTarget.cmake
@@ -0,0 +1,14 @@ +add_library(foo INTERFACE) +add_library(bar INTERFACE) + +add_library(test INTERFACE) +target_link_libraries(test INTERFACE foo bar) + +install(TARGETS foo EXPORT foo DESTINATION .) +install(TARGETS bar EXPORT bar DESTINATION .) + +install(EXPORT foo DESTINATION .) +install(EXPORT bar DESTINATION . NAMESPACE bar_) + +install(TARGETS test EXPORT test DESTINATION .) +install(PACKAGE_INFO test EXPORT test)
diff --git a/Tests/RunCMake/PackageInfo/ReferencesWronglyImportedTarget-result.txt b/Tests/RunCMake/PackageInfo/ReferencesWronglyImportedTarget-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/PackageInfo/ReferencesWronglyImportedTarget-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/PackageInfo/ReferencesWronglyImportedTarget-stderr.txt b/Tests/RunCMake/PackageInfo/ReferencesWronglyImportedTarget-stderr.txt new file mode 100644 index 0000000..cc4e824 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/ReferencesWronglyImportedTarget-stderr.txt
@@ -0,0 +1,3 @@ +CMake Error in CMakeLists.txt: + Target "foo" references imported target "bar" which does not come from any + known package.
diff --git a/Tests/RunCMake/PackageInfo/ReferencesWronglyImportedTarget.cmake b/Tests/RunCMake/PackageInfo/ReferencesWronglyImportedTarget.cmake new file mode 100644 index 0000000..8addd64 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/ReferencesWronglyImportedTarget.cmake
@@ -0,0 +1,7 @@ +add_library(bar INTERFACE IMPORTED) + +add_library(foo INTERFACE) +target_link_libraries(foo INTERFACE bar) + +install(TARGETS foo EXPORT foo DESTINATION .) +install(PACKAGE_INFO foo EXPORT foo)
diff --git a/Tests/RunCMake/PackageInfo/ReferencesWronglyNamespacedTarget-result.txt b/Tests/RunCMake/PackageInfo/ReferencesWronglyNamespacedTarget-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/PackageInfo/ReferencesWronglyNamespacedTarget-result.txt
@@ -0,0 +1 @@ +1
diff --git a/Tests/RunCMake/PackageInfo/ReferencesWronglyNamespacedTarget-stderr.txt b/Tests/RunCMake/PackageInfo/ReferencesWronglyNamespacedTarget-stderr.txt new file mode 100644 index 0000000..0a6872e --- /dev/null +++ b/Tests/RunCMake/PackageInfo/ReferencesWronglyNamespacedTarget-stderr.txt
@@ -0,0 +1,4 @@ +CMake Error in CMakeLists.txt: + Target "foo" references target "wrong::lib", which comes from the "broken" + package, but does not belong to the package's canonical namespace. This is + not allowed.
diff --git a/Tests/RunCMake/PackageInfo/ReferencesWronglyNamespacedTarget.cmake b/Tests/RunCMake/PackageInfo/ReferencesWronglyNamespacedTarget.cmake new file mode 100644 index 0000000..7a4f9c0 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/ReferencesWronglyNamespacedTarget.cmake
@@ -0,0 +1,11 @@ +find_package( + broken REQUIRED CONFIG + NO_DEFAULT_PATH + PATHS ${CMAKE_CURRENT_LIST_DIR} + ) + +add_library(foo INTERFACE) +target_link_libraries(foo INTERFACE wrong::lib) + +install(TARGETS foo EXPORT foo DESTINATION .) +install(PACKAGE_INFO foo EXPORT foo)
diff --git a/Tests/RunCMake/PackageInfo/Requirements-check.cmake b/Tests/RunCMake/PackageInfo/Requirements-check.cmake new file mode 100644 index 0000000..59a212f --- /dev/null +++ b/Tests/RunCMake/PackageInfo/Requirements-check.cmake
@@ -0,0 +1,20 @@ +include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake) + +set(out_dir "${RunCMake_BINARY_DIR}/Requirements-build/CMakeFiles/Export/510c5684a4a8a792eadfb55bc9744983") + +file(READ "${out_dir}/foo.cps" content) +expect_value("${content}" "foo" "name") +expect_value("${content}" "interface" "components" "libb" "type") + +file(READ "${out_dir}/bar.cps" content) +expect_value("${content}" "bar" "name") +expect_null("${content}" "requires" "foo") +expect_null("${content}" "requires" "test") +expect_value("${content}" "interface" "components" "libc" "type") +expect_value("${content}" "interface" "components" "libd" "type") + +string(JSON component GET "${content}" "components" "libd") +expect_array("${component}" 3 "requires") +expect_value("${component}" "test:liba" "requires" 0) +expect_value("${component}" "foo:libb" "requires" 1) +expect_value("${component}" ":libc" "requires" 2)
diff --git a/Tests/RunCMake/PackageInfo/Requirements.cmake b/Tests/RunCMake/PackageInfo/Requirements.cmake new file mode 100644 index 0000000..a4e947c --- /dev/null +++ b/Tests/RunCMake/PackageInfo/Requirements.cmake
@@ -0,0 +1,20 @@ +find_package( + test REQUIRED CONFIG + NO_DEFAULT_PATH + PATHS ${CMAKE_CURRENT_LIST_DIR} + ) + +add_library(libb INTERFACE) +add_library(libc INTERFACE) +add_library(libd INTERFACE) + +add_library(foo ALIAS libb) +add_library(bar ALIAS libc) + +target_link_libraries(libd INTERFACE test::liba foo bar) + +install(TARGETS libb EXPORT foo DESTINATION .) +install(PACKAGE_INFO foo DESTINATION cps EXPORT foo) + +install(TARGETS libc libd EXPORT bar DESTINATION .) +install(PACKAGE_INFO bar DESTINATION cps EXPORT bar)
diff --git a/Tests/RunCMake/PackageInfo/RunCMakeTest.cmake b/Tests/RunCMake/PackageInfo/RunCMakeTest.cmake new file mode 100644 index 0000000..54a32d5 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/RunCMakeTest.cmake
@@ -0,0 +1,32 @@ +include(RunCMake) + +# Test experimental gate +run_cmake(ExperimentalGate) +run_cmake(ExperimentalWarning) + +# Enable experimental feature and suppress warnings +set(RunCMake_TEST_OPTIONS + -Wno-dev + "-DCMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO:STRING=b80be207-778e-46ba-8080-b23bba22639e" + ) + +# Test incorrect usage +run_cmake(BadArgs1) +run_cmake(BadArgs2) +run_cmake(BadArgs3) +run_cmake(BadArgs4) +run_cmake(BadArgs5) +run_cmake(BadDefaultTarget) +run_cmake(ReferencesNonExportedTarget) +run_cmake(ReferencesWronglyExportedTarget) +run_cmake(ReferencesWronglyImportedTarget) +run_cmake(ReferencesWronglyNamespacedTarget) + +# Test functionality +run_cmake(Appendix) +run_cmake(InterfaceProperties) +run_cmake(Metadata) +run_cmake(Minimal) +run_cmake(LowerCaseFile) +run_cmake(Requirements) +run_cmake(TargetTypes)
diff --git a/Tests/RunCMake/PackageInfo/TargetTypes-check.cmake b/Tests/RunCMake/PackageInfo/TargetTypes-check.cmake new file mode 100644 index 0000000..34ca5ab --- /dev/null +++ b/Tests/RunCMake/PackageInfo/TargetTypes-check.cmake
@@ -0,0 +1,11 @@ +include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake) + +set(out_dir "${RunCMake_BINARY_DIR}/TargetTypes-build/CMakeFiles/Export/510c5684a4a8a792eadfb55bc9744983") + +file(READ "${out_dir}/foo.cps" content) +expect_value("${content}" "foo" "name") +expect_value("${content}" "archive" "components" "foo-static" "type") +expect_value("${content}" "dylib" "components" "foo-shared" "type") +expect_value("${content}" "module" "components" "foo-module" "type") +expect_value("${content}" "interface" "components" "bar" "type") +expect_value("${content}" "executable" "components" "test" "type")
diff --git a/Tests/RunCMake/PackageInfo/TargetTypes.cmake b/Tests/RunCMake/PackageInfo/TargetTypes.cmake new file mode 100644 index 0000000..755c3a3 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/TargetTypes.cmake
@@ -0,0 +1,20 @@ +project(TargetTypes CXX) + +add_library(foo-static STATIC foo.cxx) +add_library(foo-shared SHARED foo.cxx) +add_library(foo-module MODULE foo.cxx) +add_library(bar INTERFACE) +add_executable(test test.cxx) + +install( + TARGETS + foo-static + foo-shared + foo-module + bar + test + EXPORT foo + DESTINATION . + ) + +install(PACKAGE_INFO foo DESTINATION cps EXPORT foo)
diff --git a/Tests/RunCMake/PackageInfo/broken-config.cmake b/Tests/RunCMake/PackageInfo/broken-config.cmake new file mode 100644 index 0000000..09e40df --- /dev/null +++ b/Tests/RunCMake/PackageInfo/broken-config.cmake
@@ -0,0 +1 @@ +add_library(wrong::lib INTERFACE IMPORTED)
diff --git a/Tests/RunCMake/PackageInfo/foo.cxx b/Tests/RunCMake/PackageInfo/foo.cxx new file mode 100644 index 0000000..3695dc9 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/foo.cxx
@@ -0,0 +1,3 @@ +void foo() +{ +}
diff --git a/Tests/RunCMake/PackageInfo/test-config.cmake b/Tests/RunCMake/PackageInfo/test-config.cmake new file mode 100644 index 0000000..3c46ea6 --- /dev/null +++ b/Tests/RunCMake/PackageInfo/test-config.cmake
@@ -0,0 +1 @@ +add_library(test::liba INTERFACE IMPORTED)
diff --git a/Tests/RunCMake/PackageInfo/test.cxx b/Tests/RunCMake/PackageInfo/test.cxx new file mode 100644 index 0000000..f8b643a --- /dev/null +++ b/Tests/RunCMake/PackageInfo/test.cxx
@@ -0,0 +1,4 @@ +int main() +{ + return 0; +}