1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-13 17:47:49 +08:00

project: Define variables indicating whether project is top level

Define `PROJECT_IS_TOP_LEVEL` and `<PROJECT-NAME>_IS_TOP_LEVEL`.  The
latter is a STATIC cache entry just like other `<PROJECT-NAME>_*`
variables so that it is globally scoped.

Issue: #20310
Fixes: #21961
This commit is contained in:
friendlyanon
2021-03-24 19:59:14 +00:00
committed by Brad King
parent 3706e9c97c
commit 96a7040107
14 changed files with 100 additions and 0 deletions

View File

@@ -28,6 +28,11 @@ Also sets the variables:
:variable:`PROJECT_BINARY_DIR`, :variable:`<PROJECT-NAME>_BINARY_DIR`
Absolute path to the binary directory for the project.
:variable:`PROJECT_IS_TOP_LEVEL`, :variable:`<PROJECT-NAME>_IS_TOP_LEVEL`
.. versionadded:: 3.21
Boolean value indicating whether the project is top-level.
Further variables are set by the optional arguments described in the following.
If any of these arguments is not used, then the corresponding variables are
set to the empty string.

View File

@@ -130,6 +130,7 @@ Variables that Provide Information
/variable/PROJECT-NAME_BINARY_DIR
/variable/PROJECT-NAME_DESCRIPTION
/variable/PROJECT-NAME_HOMEPAGE_URL
/variable/PROJECT-NAME_IS_TOP_LEVEL
/variable/PROJECT-NAME_SOURCE_DIR
/variable/PROJECT-NAME_VERSION
/variable/PROJECT-NAME_VERSION_MAJOR
@@ -139,6 +140,7 @@ Variables that Provide Information
/variable/PROJECT_BINARY_DIR
/variable/PROJECT_DESCRIPTION
/variable/PROJECT_HOMEPAGE_URL
/variable/PROJECT_IS_TOP_LEVEL
/variable/PROJECT_NAME
/variable/PROJECT_SOURCE_DIR
/variable/PROJECT_VERSION

View File

@@ -0,0 +1,6 @@
project-is-top-level
--------------------
* :command:`project` now sets variables :variable:`PROJECT_IS_TOP_LEVEL` and
:variable:`<PROJECT-NAME>_IS_TOP_LEVEL` to indicate whether it was called
in a top level ``CMakeLists.txt`` file.

View File

@@ -0,0 +1,11 @@
<PROJECT-NAME>_IS_TOP_LEVEL
---------------------------
.. versionadded:: 3.21
A boolean variable indicating whether the named project was called in a top
level ``CMakeLists.txt`` file.
To obtain the value from the most recent call to :command:`project` in
the current directory scope or above, see the
:variable:`PROJECT_IS_TOP_LEVEL` variable.

View File

@@ -0,0 +1,21 @@
PROJECT_IS_TOP_LEVEL
--------------------
.. versionadded:: 3.21
A boolean variable indicating whether :command:`project` was called in a top
level ``CMakeLists.txt`` file.
Some modules should only be included as part of the top level
``CMakeLists.txt`` file to not cause unintended side effects in the build
tree, and this variable can be used to conditionally execute such code. For
example, consider the :module:`CTest` module, which creates targets and
options:
.. code-block:: cmake
project(MyProject)
...
if(PROJECT_IS_TOP_LEVEL)
include(CTest)
endif()

View File

@@ -59,6 +59,11 @@ bool cmProjectCommand(std::vector<std::string> const& args,
mf.AddDefinition("PROJECT_NAME", projectName);
mf.AddDefinitionBool("PROJECT_IS_TOP_LEVEL", mf.IsRootMakefile());
mf.AddCacheDefinition(projectName + "_IS_TOP_LEVEL",
mf.IsRootMakefile() ? "ON" : "OFF",
"Value Computed by CMake", cmStateEnums::STATIC);
// Set the CMAKE_PROJECT_NAME variable to be the highest-level
// project name in the tree. If there are two project commands
// in the same CMakeLists.txt file, and it is the top level

View File

@@ -0,0 +1,2 @@
-- PROJECT_IS_TOP_LEVEL=ON
-- ProjectIsTopLevel_IS_TOP_LEVEL=ON

View File

@@ -0,0 +1,9 @@
# no project() call, includer already calls project(${RunCMake_TEST} NONE)
if(NOT DEFINED PROJECT_IS_TOP_LEVEL)
message(FATAL_ERROR "PROJECT_IS_TOP_LEVEL is not defined")
endif()
if(NOT DEFINED "CACHE{${RunCMake_TEST}_IS_TOP_LEVEL}")
message(FATAL_ERROR "IsTopLevel_IS_TOP_LEVEL is not defined")
endif()
message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}")
message(STATUS "${RunCMake_TEST}_IS_TOP_LEVEL=${${RunCMake_TEST}_IS_TOP_LEVEL}")

View File

@@ -0,0 +1,3 @@
-- PROJECT_IS_TOP_LEVEL=ON
-- ProjectIsTopLevelMultiple_IS_TOP_LEVEL=ON
-- IsTopLevel_IS_TOP_LEVEL=ON

View File

@@ -0,0 +1,14 @@
# only one project() call, includer already calls project(${RunCMake_TEST} NONE)
project(IsTopLevel NONE)
if(NOT DEFINED PROJECT_IS_TOP_LEVEL)
message(FATAL_ERROR "PROJECT_IS_TOP_LEVEL is not defined")
endif()
if(NOT DEFINED "CACHE{${RunCMake_TEST}_IS_TOP_LEVEL}")
message(FATAL_ERROR "${RunCMake_TEST}_IS_TOP_LEVEL is not defined")
endif()
if(NOT DEFINED CACHE{IsTopLevel_IS_TOP_LEVEL})
message(FATAL_ERROR "IsTopLevel_IS_TOP_LEVEL is not defined")
endif()
message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}")
message(STATUS "${RunCMake_TEST}_IS_TOP_LEVEL=${${RunCMake_TEST}_IS_TOP_LEVEL}")
message(STATUS "IsTopLevel_IS_TOP_LEVEL=${IsTopLevel_IS_TOP_LEVEL}")

View File

@@ -0,0 +1,6 @@
-- PROJECT_IS_TOP_LEVEL=ON
-- PROJECT_IS_TOP_LEVEL=ON
-- PROJECT_IS_TOP_LEVEL=OFF
-- PROJECT_IS_TOP_LEVEL=ON
-- ProjectIsTopLevelSubdirectory_IS_TOP_LEVEL=ON
-- NotTopLevel_IS_TOP_LEVEL=OFF

View File

@@ -0,0 +1,8 @@
# no project() call, includer already calls project(${RunCMake_TEST} NONE)
message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}")
add_subdirectory(ProjectIsTopLevelSubdirectory)
message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}")
message(STATUS "${RunCMake_TEST}_IS_TOP_LEVEL=${${RunCMake_TEST}_IS_TOP_LEVEL}")
message(STATUS "NotTopLevel_IS_TOP_LEVEL=${NotTopLevel_IS_TOP_LEVEL}")

View File

@@ -0,0 +1,5 @@
message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}")
project(NotTopLevel NONE)
message(STATUS "PROJECT_IS_TOP_LEVEL=${PROJECT_IS_TOP_LEVEL}")

View File

@@ -15,6 +15,9 @@ run_cmake(ProjectDescriptionNoArg2)
run_cmake(ProjectHomepage)
run_cmake(ProjectHomepage2)
run_cmake(ProjectHomepageNoArg)
run_cmake(ProjectIsTopLevel)
run_cmake(ProjectIsTopLevelMultiple)
run_cmake(ProjectIsTopLevelSubdirectory)
run_cmake(ProjectTwice)
run_cmake(VersionAndLanguagesEmpty)
run_cmake(VersionEmpty)