project: Always set <PROJECT-NAME>_* as normal variables
Re-introduce the behavior originally introduced in CMake 3.30.3 by
commit c1ece78d11
(project: non cache <project> prefix variables are
also created, 2024-08-27, v3.30.3~2^2), but this time with a policy for
compatibility.
Issue: #25714
Issue: #26243
This commit is contained in:
parent
ddf1d2944f
commit
e5a9ccbcc8
@ -44,27 +44,18 @@ Projects should not rely on ``<PROJECT-NAME>_SOURCE_DIR`` or
|
|||||||
``<PROJECT-NAME>_BINARY_DIR`` holding a particular value outside of the scope
|
``<PROJECT-NAME>_BINARY_DIR`` holding a particular value outside of the scope
|
||||||
of the call to ``project()`` or one of its child scopes.
|
of the call to ``project()`` or one of its child scopes.
|
||||||
|
|
||||||
.. versionchanged:: 3.30.3
|
.. versionchanged:: 3.30
|
||||||
``<PROJECT-NAME>_SOURCE_DIR``, ``<PROJECT-NAME>_BINARY_DIR``, and
|
``<PROJECT-NAME>_SOURCE_DIR``, ``<PROJECT-NAME>_BINARY_DIR``, and
|
||||||
``<PROJECT-NAME>_IS_TOP_LEVEL`` are always set as non-cache variables by
|
``<PROJECT-NAME>_IS_TOP_LEVEL``, if already set as normal variables when
|
||||||
``project(<PROJECT-NAME> ...)``.
|
``project(<PROJECT-NAME> ...)`` is called, are updated by the call.
|
||||||
|
Cache entries by the same names are always set as before.
|
||||||
|
See release notes for 3.30.3, 3.30.4, and 3.30.5 for details.
|
||||||
|
|
||||||
.. versionchanged:: 3.30.4
|
.. versionchanged:: 3.31
|
||||||
The variables ``<PROJECT-NAME>_SOURCE_DIR``, ``<PROJECT-NAME>_BINARY_DIR``,
|
``<PROJECT-NAME>_SOURCE_DIR``, ``<PROJECT-NAME>_BINARY_DIR``, and
|
||||||
and ``<PROJECT-NAME>_IS_TOP_LEVEL`` are only set as non-cache variables if
|
``<PROJECT-NAME>_IS_TOP_LEVEL`` are always set as normal variables by
|
||||||
they are already set as cache or non-cache variables when
|
``project(<PROJECT-NAME> ...)``. See policy :policy:`CMP0180`.
|
||||||
``project(<PROJECT-NAME> ...)`` is called.
|
Cache entries by the same names are always set as before.
|
||||||
Note that this logic is flawed, as it can result in different behavior
|
|
||||||
between the first and subsequent runs because cache variables won't exist
|
|
||||||
on the first run, but they will on subsequent runs.
|
|
||||||
|
|
||||||
.. versionchanged:: 3.30.5
|
|
||||||
The variables ``<PROJECT-NAME>_SOURCE_DIR``, ``<PROJECT-NAME>_BINARY_DIR``,
|
|
||||||
and ``<PROJECT-NAME>_IS_TOP_LEVEL`` are only set as non-cache variables if
|
|
||||||
they are already set as non-cache variables when
|
|
||||||
``project(<PROJECT-NAME> ...)`` is called.
|
|
||||||
Unlike the flawed behavior of 3.30.4, non-cache variables will not be set
|
|
||||||
if only cache variables of the same name are set.
|
|
||||||
|
|
||||||
Options
|
Options
|
||||||
^^^^^^^
|
^^^^^^^
|
||||||
|
@ -57,6 +57,7 @@ Policies Introduced by CMake 3.31
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
|
CMP0180: project() always sets <PROJECT-NAME>_* as normal variables. </policy/CMP0180>
|
||||||
CMP0179: De-duplication of static libraries on link lines keeps first occurrence. </policy/CMP0179>
|
CMP0179: De-duplication of static libraries on link lines keeps first occurrence. </policy/CMP0179>
|
||||||
CMP0178: Test command lines preserve empty arguments. </policy/CMP0178>
|
CMP0178: Test command lines preserve empty arguments. </policy/CMP0178>
|
||||||
CMP0177: install() DESTINATION paths are normalized. </policy/CMP0177>
|
CMP0177: install() DESTINATION paths are normalized. </policy/CMP0177>
|
||||||
|
36
Help/policy/CMP0180.rst
Normal file
36
Help/policy/CMP0180.rst
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
CMP0180
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. versionadded:: 3.31
|
||||||
|
|
||||||
|
:command:`project` always sets ``<PROJECT-NAME>_*`` as normal variables.
|
||||||
|
|
||||||
|
In CMake 3.29 and below, the :command:`project` command set
|
||||||
|
:variable:`<PROJECT-NAME>_SOURCE_DIR`, :variable:`<PROJECT-NAME>_BINARY_DIR`,
|
||||||
|
and :variable:`<PROJECT-NAME>_IS_TOP_LEVEL` as cache entries, but not as
|
||||||
|
normal variables. CMake 3.30 started setting them as normal variables,
|
||||||
|
but only if they are already set as normal variables. This was needed to
|
||||||
|
preserve support for some :module:`FetchContent` use cases under policy
|
||||||
|
:policy:`CMP0169`'s NEW behavior, while also preserving behavior of nested
|
||||||
|
directories that call :command:`project` with the same project name.
|
||||||
|
See release notes for 3.30.3, 3.30.4, and 3.30.5 for details.
|
||||||
|
|
||||||
|
CMake 3.31 and later prefer to always set ``<PROJECT-NAME>_SOURCE_DIR``,
|
||||||
|
``<PROJECT-NAME>_BINARY_DIR``, and ``<PROJECT-NAME>_IS_TOP_LEVEL``, as both
|
||||||
|
cache entries and normal variables, regardless of what cache or normal
|
||||||
|
variables already exist. This policy provides compatibility for projects
|
||||||
|
that have not been updated to expect this behavior.
|
||||||
|
|
||||||
|
The ``OLD`` behavior for this policy will only set normal variables for
|
||||||
|
``<PROJECT-NAME>_SOURCE_DIR``, ``<PROJECT-NAME>_BINARY_DIR``, and
|
||||||
|
``<PROJECT-NAME>_IS_TOP_LEVEL`` if there is already a normal variable by that
|
||||||
|
name when :command:`project` is called.
|
||||||
|
The ``NEW`` behavior for this policy will always set normal variables for
|
||||||
|
``<PROJECT-NAME>_SOURCE_DIR``, ``<PROJECT-NAME>_BINARY_DIR``, and
|
||||||
|
``<PROJECT-NAME>_IS_TOP_LEVEL`` when :command:`project` is called.
|
||||||
|
|
||||||
|
.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 3.31
|
||||||
|
.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
|
||||||
|
.. include:: STANDARD_ADVICE.txt
|
||||||
|
|
||||||
|
.. include:: DEPRECATED.txt
|
7
Help/release/dev/project-vars-policy.rst
Normal file
7
Help/release/dev/project-vars-policy.rst
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
project-vars-policy
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
* The :command:`project` command now always sets
|
||||||
|
:variable:`<PROJECT-NAME>_SOURCE_DIR`, :variable:`<PROJECT-NAME>_BINARY_DIR`,
|
||||||
|
and :variable:`<PROJECT-NAME>_IS_TOP_LEVEL` as both normal variables and
|
||||||
|
cache entries. See policy :policy:`CMP0180`.
|
@ -549,7 +549,10 @@ class cmMakefile;
|
|||||||
SELECT(POLICY, CMP0179, \
|
SELECT(POLICY, CMP0179, \
|
||||||
"De-duplication of static libraries on link lines keeps first " \
|
"De-duplication of static libraries on link lines keeps first " \
|
||||||
"occurrence.", \
|
"occurrence.", \
|
||||||
3, 31, 0, cmPolicies::WARN)
|
3, 31, 0, cmPolicies::WARN) \
|
||||||
|
SELECT(POLICY, CMP0180, \
|
||||||
|
"project() always sets <PROJECT-NAME>_* as normal variables.", 3, \
|
||||||
|
31, 0, cmPolicies::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)
|
||||||
#define CM_FOR_EACH_POLICY_ID(POLICY) \
|
#define CM_FOR_EACH_POLICY_ID(POLICY) \
|
||||||
|
@ -58,11 +58,13 @@ bool cmProjectCommand(std::vector<std::string> const& args,
|
|||||||
|
|
||||||
mf.SetProjectName(projectName);
|
mf.SetProjectName(projectName);
|
||||||
|
|
||||||
|
cmPolicies::PolicyStatus cmp0180 = mf.GetPolicyStatus(cmPolicies::CMP0180);
|
||||||
|
|
||||||
std::string varName = cmStrCat(projectName, "_BINARY_DIR"_s);
|
std::string varName = cmStrCat(projectName, "_BINARY_DIR"_s);
|
||||||
bool nonCacheVarAlreadySet = mf.IsNormalDefinitionSet(varName);
|
bool nonCacheVarAlreadySet = mf.IsNormalDefinitionSet(varName);
|
||||||
mf.AddCacheDefinition(varName, mf.GetCurrentBinaryDirectory(),
|
mf.AddCacheDefinition(varName, mf.GetCurrentBinaryDirectory(),
|
||||||
"Value Computed by CMake", cmStateEnums::STATIC);
|
"Value Computed by CMake", cmStateEnums::STATIC);
|
||||||
if (nonCacheVarAlreadySet) {
|
if (cmp0180 == cmPolicies::NEW || nonCacheVarAlreadySet) {
|
||||||
mf.AddDefinition(varName, mf.GetCurrentBinaryDirectory());
|
mf.AddDefinition(varName, mf.GetCurrentBinaryDirectory());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +72,7 @@ bool cmProjectCommand(std::vector<std::string> const& args,
|
|||||||
nonCacheVarAlreadySet = mf.IsNormalDefinitionSet(varName);
|
nonCacheVarAlreadySet = mf.IsNormalDefinitionSet(varName);
|
||||||
mf.AddCacheDefinition(varName, mf.GetCurrentSourceDirectory(),
|
mf.AddCacheDefinition(varName, mf.GetCurrentSourceDirectory(),
|
||||||
"Value Computed by CMake", cmStateEnums::STATIC);
|
"Value Computed by CMake", cmStateEnums::STATIC);
|
||||||
if (nonCacheVarAlreadySet) {
|
if (cmp0180 == cmPolicies::NEW || nonCacheVarAlreadySet) {
|
||||||
mf.AddDefinition(varName, mf.GetCurrentSourceDirectory());
|
mf.AddDefinition(varName, mf.GetCurrentSourceDirectory());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +87,7 @@ bool cmProjectCommand(std::vector<std::string> const& args,
|
|||||||
nonCacheVarAlreadySet = mf.IsNormalDefinitionSet(varName);
|
nonCacheVarAlreadySet = mf.IsNormalDefinitionSet(varName);
|
||||||
mf.AddCacheDefinition(varName, mf.IsRootMakefile() ? "ON" : "OFF",
|
mf.AddCacheDefinition(varName, mf.IsRootMakefile() ? "ON" : "OFF",
|
||||||
"Value Computed by CMake", cmStateEnums::STATIC);
|
"Value Computed by CMake", cmStateEnums::STATIC);
|
||||||
if (nonCacheVarAlreadySet) {
|
if (cmp0180 == cmPolicies::NEW || nonCacheVarAlreadySet) {
|
||||||
mf.AddDefinition(varName, mf.IsRootMakefile() ? "ON" : "OFF");
|
mf.AddDefinition(varName, mf.IsRootMakefile() ? "ON" : "OFF");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
Tests/RunCMake/project/CMP0180-NEW-stdout.txt
Normal file
16
Tests/RunCMake/project/CMP0180-NEW-stdout.txt
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
(-- )?From subdir1:
|
||||||
|
CMP0180-NEW_SOURCE_DIR = [^
|
||||||
|
]+/project/subdir1
|
||||||
|
CMP0180-NEW_BINARY_DIR = [^
|
||||||
|
]+/project/CMP0180-NEW-build/subdir1
|
||||||
|
CMP0180-NEW_IS_TOP_LEVEL = OFF
|
||||||
|
(-- )?From subdir2:
|
||||||
|
CMP0180-NEW_SOURCE_DIR = [^
|
||||||
|
]+/project
|
||||||
|
CMP0180-NEW_BINARY_DIR = [^
|
||||||
|
]+/project/CMP0180-NEW-build
|
||||||
|
CMP0180-NEW_IS_TOP_LEVEL = ON
|
||||||
|
(-- )? sub2proj_SOURCE_DIR = [^
|
||||||
|
]+/project/subdir2
|
||||||
|
sub2proj_BINARY_DIR = [^
|
||||||
|
]+/project/CMP0180-NEW-build/subdir2
|
2
Tests/RunCMake/project/CMP0180-NEW.cmake
Normal file
2
Tests/RunCMake/project/CMP0180-NEW.cmake
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# CMP0180 is handled in CMakeLists.txt
|
||||||
|
include(CMP0180.cmake)
|
16
Tests/RunCMake/project/CMP0180-OLD-stdout.txt
Normal file
16
Tests/RunCMake/project/CMP0180-OLD-stdout.txt
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
(-- )?From subdir1:
|
||||||
|
CMP0180-OLD_SOURCE_DIR = [^
|
||||||
|
]+/project/subdir1
|
||||||
|
CMP0180-OLD_BINARY_DIR = [^
|
||||||
|
]+/project/CMP0180-OLD-build/subdir1
|
||||||
|
CMP0180-OLD_IS_TOP_LEVEL = OFF
|
||||||
|
(-- )?From subdir2:
|
||||||
|
CMP0180-OLD_SOURCE_DIR = [^
|
||||||
|
]+/project/subdir1
|
||||||
|
CMP0180-OLD_BINARY_DIR = [^
|
||||||
|
]+/project/CMP0180-OLD-build/subdir1
|
||||||
|
CMP0180-OLD_IS_TOP_LEVEL = OFF
|
||||||
|
(-- )? sub2proj_SOURCE_DIR = [^
|
||||||
|
]+/project/subdir2
|
||||||
|
sub2proj_BINARY_DIR = [^
|
||||||
|
]+/project/CMP0180-OLD-build/subdir2
|
2
Tests/RunCMake/project/CMP0180-OLD.cmake
Normal file
2
Tests/RunCMake/project/CMP0180-OLD.cmake
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# CMP0180 is handled in CMakeLists.txt
|
||||||
|
include(CMP0180.cmake)
|
@ -4,6 +4,12 @@ elseif(RunCMake_TEST MATCHES "^CMP0048")
|
|||||||
cmake_minimum_required(VERSION 2.8.12) # old enough to not set CMP0048
|
cmake_minimum_required(VERSION 2.8.12) # old enough to not set CMP0048
|
||||||
else()
|
else()
|
||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
# CMP0180 needs to be set before the project() call for these tests
|
||||||
|
if("x${RunCMake_TEST}" STREQUAL "xCMP0180-NEW")
|
||||||
|
cmake_policy(SET CMP0180 NEW)
|
||||||
|
elseif("x${RunCMake_TEST}" STREQUAL "xCMP0180-OLD")
|
||||||
|
cmake_policy(SET CMP0180 OLD)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
project(${RunCMake_TEST} NONE)
|
project(${RunCMake_TEST} NONE)
|
||||||
include(${RunCMake_TEST}.cmake)
|
include(${RunCMake_TEST}.cmake)
|
||||||
|
@ -63,9 +63,13 @@ run_cmake(CMP0096-OLD)
|
|||||||
run_cmake(CMP0096-NEW)
|
run_cmake(CMP0096-NEW)
|
||||||
|
|
||||||
# We deliberately run these twice to verify behavior of the second CMake run
|
# We deliberately run these twice to verify behavior of the second CMake run
|
||||||
run_cmake(SameProjectVarsSubdir)
|
run_cmake(CMP0180-OLD)
|
||||||
set(RunCMake_TEST_NO_CLEAN 1)
|
set(RunCMake_TEST_NO_CLEAN 1)
|
||||||
run_cmake(SameProjectVarsSubdir)
|
run_cmake(CMP0180-OLD)
|
||||||
|
set(RunCMake_TEST_NO_CLEAN 0)
|
||||||
|
run_cmake(CMP0180-NEW)
|
||||||
|
set(RunCMake_TEST_NO_CLEAN 1)
|
||||||
|
run_cmake(CMP0180-NEW)
|
||||||
set(RunCMake_TEST_NO_CLEAN 0)
|
set(RunCMake_TEST_NO_CLEAN 0)
|
||||||
|
|
||||||
run_cmake(NoMinimumRequired)
|
run_cmake(NoMinimumRequired)
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
(-- )? SameProjectVarsSubdir_SOURCE_DIR = [^
|
|
||||||
]+/subdir1
|
|
||||||
SameProjectVarsSubdir_BINARY_DIR = [^
|
|
||||||
]+/subdir1
|
|
||||||
SameProjectVarsSubdir_IS_TOP_LEVEL = OFF
|
|
||||||
(-- )? sub2proj_SOURCE_DIR = [^
|
|
||||||
]+/subdir2
|
|
||||||
sub2proj_BINARY_DIR = [^
|
|
||||||
]+/subdir2
|
|
@ -1 +1,8 @@
|
|||||||
project(${RunCMake_TEST} LANGUAGES NONE)
|
project(${RunCMake_TEST} LANGUAGES NONE)
|
||||||
|
|
||||||
|
message(STATUS
|
||||||
|
"From subdir1:\n"
|
||||||
|
" ${RunCMake_TEST}_SOURCE_DIR = ${${RunCMake_TEST}_SOURCE_DIR}\n"
|
||||||
|
" ${RunCMake_TEST}_BINARY_DIR = ${${RunCMake_TEST}_BINARY_DIR}\n"
|
||||||
|
" ${RunCMake_TEST}_IS_TOP_LEVEL = ${${RunCMake_TEST}_IS_TOP_LEVEL}"
|
||||||
|
)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
message(STATUS
|
message(STATUS
|
||||||
|
"From subdir2:\n"
|
||||||
" ${RunCMake_TEST}_SOURCE_DIR = ${${RunCMake_TEST}_SOURCE_DIR}\n"
|
" ${RunCMake_TEST}_SOURCE_DIR = ${${RunCMake_TEST}_SOURCE_DIR}\n"
|
||||||
" ${RunCMake_TEST}_BINARY_DIR = ${${RunCMake_TEST}_BINARY_DIR}\n"
|
" ${RunCMake_TEST}_BINARY_DIR = ${${RunCMake_TEST}_BINARY_DIR}\n"
|
||||||
" ${RunCMake_TEST}_IS_TOP_LEVEL = ${${RunCMake_TEST}_IS_TOP_LEVEL}"
|
" ${RunCMake_TEST}_IS_TOP_LEVEL = ${${RunCMake_TEST}_IS_TOP_LEVEL}"
|
||||||
|
Loading…
Reference in New Issue
Block a user