Bläddra i källkod

GNUInstallDirs: Cache CMAKE_INSTALL_* with leading usr/ for install prefix /

As a consequence, `GNUInstallDirs_get_absolute_install_dir` does not
alter the `var` argument (the relative path argument).

Closes: #26834
Signed-off-by: Cristian Le <[email protected]>
Cristian Le 7 månader sedan
förälder
incheckning
cc6dbd194c

+ 1 - 0
Help/manual/cmake-policies.7.rst

@@ -98,6 +98,7 @@ Policies Introduced by CMake 4.1
 .. toctree::
 .. toctree::
    :maxdepth: 1
    :maxdepth: 1
 
 
+   CMP0193: GNUInstallDirs caches CMAKE_INSTALL_* with leading 'usr/' for install prefix '/'. </policy/CMP0193>
    CMP0192: GNUInstallDirs uses absolute SYSCONFDIR, LOCALSTATEDIR, and RUNSTATEDIR in special prefixes. </policy/CMP0192>
    CMP0192: GNUInstallDirs uses absolute SYSCONFDIR, LOCALSTATEDIR, and RUNSTATEDIR in special prefixes. </policy/CMP0192>
    CMP0191: The FindCABLE module is removed. </policy/CMP0191>
    CMP0191: The FindCABLE module is removed. </policy/CMP0191>
    CMP0190: FindPython enforce consistency in cross-compiling mode. </policy/CMP0190>
    CMP0190: FindPython enforce consistency in cross-compiling mode. </policy/CMP0190>

+ 31 - 0
Help/policy/CMP0193.rst

@@ -0,0 +1,31 @@
+CMP0193
+-------
+
+.. versionadded:: 4.1
+
+:module:`GNUInstallDirs` caches ``CMAKE_INSTALL_*`` with leading ``usr/`` for
+install prefix ``/``.
+
+When :variable:`CMAKE_INSTALL_PREFIX` is ``/``, the ``CMAKE_INSTALL_<dir>``
+variables, for ``<dir>`` equal to ``BINDIR``, ``SBINDIR``, ``LIBEXECDIR``,
+``SHAREDSTATEDIR``, ``INCLUDEDIR``, ``OLDINCLUDEDIR``, ``DATAROOTDIR``, and
+``LIBDIR``, are prepended with a leading ``usr/`` as documented among the
+:ref:`special cases <GNUInstallDirs special cases>`.
+In CMake 4.0 and below, these ``CMAKE_INSTALL_<dir>`` variables were cached
+without their leading ``usr/``, and it was prepended in normal variables that
+shadow their cache entries.
+CMake 4.1 and above prefer to cache ``CMAKE_INSTALL_<dir>`` with their leading
+``usr/``.  Consequently, the :command:`GNUInstallDirs_get_absolute_install_dir`
+command no longer alters the relative ``var`` input variable.  This policy
+provides compatibility for projects that have not been updated to expect
+the new behavior.
+
+The ``OLD`` behavior for this policy is to cache ``CMAKE_INSTALL_<dir>``
+variables without the leading ``usr/``.  The ``NEW`` behavior for this
+policy is to cache ``CMAKE_INSTALL_<dir>`` variables with the leading ``usr/``.
+
+.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.1
+.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
+.. include:: include/STANDARD_ADVICE.rst
+
+.. include:: include/DEPRECATED.rst

+ 4 - 0
Help/release/dev/GNUInstallDirs-special-cases.rst

@@ -5,3 +5,7 @@ GNUInstallDirs-special-cases
   ``SYSCONFDIR``, ``LOCALSTATEDIR``, and ``RUNSTATEDIR`` to
   ``SYSCONFDIR``, ``LOCALSTATEDIR``, and ``RUNSTATEDIR`` to
   absolute paths when installing to special prefixes.
   absolute paths when installing to special prefixes.
   See policy :policy:`CMP0192`.
   See policy :policy:`CMP0192`.
+
+* The :module:`GNUInstallDirs` module now caches ``CMAKE_INSTALL_*``
+  variables with their leading ``usr/`` for install prefix ``/``.
+  See policy :policy:`CMP0193`.

+ 55 - 1
Modules/GNUInstallDirs.cmake

@@ -129,6 +129,10 @@ The following values of :variable:`CMAKE_INSTALL_PREFIX` are special:
     When building the complete GNU system, the prefix will be empty
     When building the complete GNU system, the prefix will be empty
     and ``/usr`` will be a symbolic link to ``/``.
     and ``/usr`` will be a symbolic link to ``/``.
 
 
+  .. versionchanged:: 4.1
+    The ``CMAKE_INSTALL_<dir>`` variables are cached with the ``usr/`` prefix.
+    See policy :policy:`CMP0193`.
+
 ``/usr``
 ``/usr``
 
 
   For ``<dir>`` equal to ``SYSCONFDIR``, ``LOCALSTATEDIR`` or
   For ``<dir>`` equal to ``SYSCONFDIR``, ``LOCALSTATEDIR`` or
@@ -186,6 +190,9 @@ Functions
   .. versionchanged:: 3.20
   .. versionchanged:: 3.20
     Added the ``<dirname>`` parameter.  Previous versions of CMake passed
     Added the ``<dirname>`` parameter.  Previous versions of CMake passed
     this value through the variable ``${dir}``.
     this value through the variable ``${dir}``.
+
+  .. versionchanged:: 4.1
+    The ``var`` variable is no longer altered. See policy :policy:`CMP0193`.
 #]=======================================================================]
 #]=======================================================================]
 
 
 cmake_policy(SET CMP0140 NEW)
 cmake_policy(SET CMP0140 NEW)
@@ -330,6 +337,20 @@ function(__GNUInstallDirs_default_in_root out_var original_path install_prefix)
   return(PROPAGATE ${out_var})
   return(PROPAGATE ${out_var})
 endfunction()
 endfunction()
 
 
+# Common handler for defaults that should be in usr/<dir>
+function(__GNUInstallDirs_default_in_usr out_var initial_value install_prefix)
+  set(${out_var} "${initial_value}")
+  if(install_prefix STREQUAL "/")
+    cmake_policy(GET CMP0193 cmp0193
+        PARENT_SCOPE # undocumented, do not use outside of CMake
+    )
+    if(cmp0193 STREQUAL "NEW")
+      set(${out_var} "usr/${${out_var}}")
+    endif()
+  endif()
+  return(PROPAGATE ${out_var})
+endfunction()
+
 # Installation directories
 # Installation directories
 #
 #
 
 
@@ -388,6 +409,7 @@ function(_GNUInstallDirs_LIBDIR_get_default out_var install_prefix)
       endif()
       endif()
     endif()
     endif()
   endif()
   endif()
+  __GNUInstallDirs_default_in_usr(${out_var} "${${out_var}}" "${install_prefix}")
 
 
   return(PROPAGATE ${out_var})
   return(PROPAGATE ${out_var})
 endfunction()
 endfunction()
@@ -423,6 +445,31 @@ function(_GNUInstallDirs_RUNSTATEDIR_get_default out_var install_prefix)
   return(PROPAGATE ${out_var})
   return(PROPAGATE ${out_var})
 endfunction()
 endfunction()
 
 
+# All of the other (primitive) dirs are typically in usr/<dir>.
+# A special handling is needed for the `/` install_prefix
+foreach(dir IN ITEMS
+    BINDIR
+    SBINDIR
+    LIBEXECDIR
+    SHAREDSTATEDIR
+    INCLUDEDIR
+    OLDINCLUDEDIR
+    DATAROOTDIR
+    # Except all the previous ones that had a special handling:
+    # LIBDIR, SYSCONFDIR, LOCALSTATEDIR, OLDINCLUDEDIR
+)
+  # Cannot call function() directly because `dir` would not be accessible inside the function
+  # Using cmake_language(EVAL) to call a short wrapper function instead
+  cmake_language(EVAL CODE "
+    function(_GNUInstallDirs_${dir}_get_default out_var install_prefix)
+      set(\${out_var} \"\${_GNUInstallDirs_${dir}_DEFAULT}\")
+      __GNUInstallDirs_default_in_usr(\${out_var} \"\${\${out_var}}\" \"\${install_prefix}\")
+      return(PROPAGATE \${out_var})
+    endfunction()
+  "
+  )
+endforeach()
+
 _GNUInstallDirs_cache_path(BINDIR
 _GNUInstallDirs_cache_path(BINDIR
   "User executables")
   "User executables")
 _GNUInstallDirs_cache_path(SBINDIR
 _GNUInstallDirs_cache_path(SBINDIR
@@ -571,7 +618,14 @@ function(GNUInstallDirs_get_absolute_install_dir absvar var)
     set(${absvar} "${${var}}")
     set(${absvar} "${${var}}")
   endif()
   endif()
 
 
-  return(PROPAGATE ${var} ${absvar})
+  set(return_vars ${absvar})
+  cmake_policy(GET CMP0193 cmp0193
+    PARENT_SCOPE # undocumented, do not use outside of CMake
+  )
+  if(NOT cmp0193 STREQUAL "NEW")
+    list(APPEND return_vars ${var})
+  endif()
+  return(PROPAGATE ${return_vars})
 endfunction()
 endfunction()
 
 
 # Result directories
 # Result directories

+ 4 - 0
Source/cmPolicies.h

@@ -574,6 +574,10 @@ class cmMakefile;
   SELECT(POLICY, CMP0192,                                                     \
   SELECT(POLICY, CMP0192,                                                     \
          "GNUInstallDirs uses absolute SYSCONFDIR, LOCALSTATEDIR, and "       \
          "GNUInstallDirs uses absolute SYSCONFDIR, LOCALSTATEDIR, and "       \
          "RUNSTATEDIR in special prefixes.",                                  \
          "RUNSTATEDIR in special prefixes.",                                  \
+         4, 1, 0, WARN)                                                       \
+  SELECT(POLICY, CMP0193,                                                     \
+         "GNUInstallDirs caches CMAKE_INSTALL_* with leading 'usr/' for "     \
+         "install prefix '/'.",                                               \
          4, 1, 0, WARN)
          4, 1, 0, WARN)
 
 
 #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
 #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)

+ 1 - 0
Tests/RunCMake/GNUInstallDirs/CMakeLists.txt

@@ -1,4 +1,5 @@
 cmake_minimum_required(VERSION 3.10)
 cmake_minimum_required(VERSION 3.10)
 cmake_policy(SET CMP0192 NEW)
 cmake_policy(SET CMP0192 NEW)
+cmake_policy(SET CMP0193 NEW)
 project(${RunCMake_TEST} NONE)
 project(${RunCMake_TEST} NONE)
 include(${RunCMake_TEST}.cmake)
 include(${RunCMake_TEST}.cmake)

+ 1 - 1
Tests/RunCMake/GNUInstallDirs/GetAbs-stderr.txt

@@ -6,7 +6,7 @@ CMake Warning \(dev\) at [^
   below.
   below.
 Call Stack \(most recent call first\):
 Call Stack \(most recent call first\):
   GetAbs.cmake:10 \(GNUInstallDirs_get_absolute_install_dir\)
   GetAbs.cmake:10 \(GNUInstallDirs_get_absolute_install_dir\)
-  CMakeLists.txt:4 \(include\)
+  CMakeLists.txt:5 \(include\)
 This warning is for project developers.  Use -Wno-dev to suppress it.
 This warning is for project developers.  Use -Wno-dev to suppress it.
 +
 +
 PROJ2_FULL_BINDIR='/usr/bin'$
 PROJ2_FULL_BINDIR='/usr/bin'$