diff options
author | Brad King <brad.king@kitware.com> | 2024-05-24 14:29:43 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2024-05-24 14:29:57 (GMT) |
commit | 1d519cf7967c41f33e485155f9f69109235f080c (patch) | |
tree | ebd7eef7144af159708548ccff3cc03e8689c5c2 | |
parent | dfe0a107773cd15093c2546332016595005bd777 (diff) | |
parent | 0e5250e63c5c82ff0c8b52ade9c2f84fbe251152 (diff) | |
download | CMake-1d519cf7967c41f33e485155f9f69109235f080c.zip CMake-1d519cf7967c41f33e485155f9f69109235f080c.tar.gz CMake-1d519cf7967c41f33e485155f9f69109235f080c.tar.bz2 |
Merge topic 'ninja-parallel'
0e5250e63c Ninja: Add option for parallel install
daeb8fffa2 Help: Add Builtin Targets section to Ninja help
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !9505
20 files changed, 157 insertions, 11 deletions
diff --git a/Help/generator/Ninja.rst b/Help/generator/Ninja.rst index f3ba222..5f5ffb8 100644 --- a/Help/generator/Ninja.rst +++ b/Help/generator/Ninja.rst @@ -1,11 +1,35 @@ Ninja ----- -Generates ``build.ninja`` files. +Generates a ``build.ninja`` file into the build tree. -A ``build.ninja`` file is generated into the build tree. Use the ninja -program to build the project through the ``all`` target and install the -project through the ``install`` (or ``install/strip``) target. +Builtin Targets +^^^^^^^^^^^^^^^ + +``all`` + + Depends on all targets required by the project, except those with + :prop_tgt:`EXCLUDE_FROM_ALL` set to true. + +``install`` + + Runs the install step. + +``install/strip`` + + .. versionadded:: 3.7 + + Runs the install followed by a ``CMAKE_STRIP`` command, if any. + + The ``CMAKE_STRIP`` variable will contain the platform's ``strip`` utility, which + removes symbols information from generated binaries. + +``install/parallel`` + + .. versionadded:: 3.30 + + Created only if the :prop_gbl:`INSTALL_PARALLEL` global property is ``ON``. + Runs the install step for each subdirectory independently and in parallel. For each subdirectory ``sub/dir`` of the project, additional targets are generated: @@ -25,12 +49,10 @@ are generated: ``sub/dir/install/strip`` .. versionadded:: 3.7 + Runs the install step in the subdirectory followed by a ``CMAKE_STRIP`` command, if any. - The ``CMAKE_STRIP`` variable will contain the platform's ``strip`` utility, which - removes symbols information from generated binaries. - ``sub/dir/test`` .. versionadded:: 3.7 diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 549ec53..f37e72f 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -39,6 +39,7 @@ Properties of Global Scope /prop_gbl/GENERATOR_IS_MULTI_CONFIG /prop_gbl/GLOBAL_DEPENDS_DEBUG_MODE /prop_gbl/GLOBAL_DEPENDS_NO_CYCLES + /prop_gbl/INSTALL_PARALLEL /prop_gbl/IN_TRY_COMPILE /prop_gbl/JOB_POOLS /prop_gbl/PACKAGES_FOUND diff --git a/Help/prop_gbl/INSTALL_PARALLEL.rst b/Help/prop_gbl/INSTALL_PARALLEL.rst new file mode 100644 index 0000000..7b6632e --- /dev/null +++ b/Help/prop_gbl/INSTALL_PARALLEL.rst @@ -0,0 +1,23 @@ +INSTALL_PARALLEL +---------------- + +.. versionadded:: 3.30 + +Enables parallel installation option for the Ninja generator. + +When this property is ``ON``, ``install/local`` targets have the +console pool disabled, allowing them to run concurrently. + +This property also provides the target ``install/parallel``, which has an +explicit dependency on the ``install/local`` target for each subdirectory, +recursing down the project. + +Setting this property has no affect on the behavior of ``cmake --install``. +The install must be invoked by building the ``install/parallel`` target +directly. + +Calls to :command:`install(CODE)` or :command:`install(SCRIPT)` might depend +on actions performed by an earlier :command:`install` command in a different +directory such as files installed or variable settings. If the project has +such order-dependent installation logic, parallel installation should be +not be enabled, in order to prevent possible race conditions. diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 0ee2dac..019271b 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -3048,7 +3048,9 @@ void cmGlobalGenerator::AddGlobalTarget_Install( if (const char* install_local = this->GetInstallLocalTargetName()) { gti.Name = install_local; gti.Message = "Installing only the local directory..."; - gti.UsesTerminal = true; + gti.UsesTerminal = + !this->GetCMakeInstance()->GetState()->GetGlobalPropertyAsBool( + "INSTALL_PARALLEL"); gti.CommandLines.clear(); cmCustomCommandLine localCmdLine = singleLine; diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 250546f..4e6f164 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -1835,6 +1835,21 @@ void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os) if (!this->DefaultFileConfig.empty()) { this->WriteTargetDefault(*this->GetDefaultFileStream()); } + + if (this->InstallTargetEnabled && + this->GetCMakeInstance()->GetState()->GetGlobalPropertyAsBool( + "INSTALL_PARALLEL") && + !this->Makefiles[0]->IsOn("CMAKE_SKIP_INSTALL_RULES")) { + cmNinjaBuild build("phony"); + build.Comment = "Install every subdirectory in parallel"; + build.Outputs.emplace_back(this->GetInstallParallelTargetName()); + for (auto const& mf : this->Makefiles) { + build.ExplicitDeps.emplace_back( + this->ConvertToNinjaPath(cmStrCat(mf->GetCurrentBinaryDirectory(), "/", + this->GetInstallLocalTargetName()))); + } + WriteBuild(os, build); + } } void cmGlobalNinjaGenerator::WriteTargetDefault(std::ostream& os) diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 64eed4d..9758627 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -218,6 +218,10 @@ public: { return "install/strip"; } + const char* GetInstallParallelTargetName() const + { + return "install/parallel"; + } const char* GetTestTargetName() const override { return "test"; } const char* GetPackageTargetName() const override { return "package"; } const char* GetPackageSourceTargetName() const override diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 1440771..94e62ff 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -730,10 +730,12 @@ void cmLocalGenerator::GenerateInstallRules() " set(CMAKE_INSTALL_MANIFEST \"install_manifest.txt\")\n" "endif()\n" "\n" - "string(REPLACE \";\" \"\\n\" CMAKE_INSTALL_MANIFEST_CONTENT\n" + "if(NOT CMAKE_INSTALL_LOCAL_ONLY)\n" + " string(REPLACE \";\" \"\\n\" CMAKE_INSTALL_MANIFEST_CONTENT\n" " \"${CMAKE_INSTALL_MANIFEST_FILES}\")\n" - "file(WRITE \"" << homedir << "/${CMAKE_INSTALL_MANIFEST}\"\n" - " \"${CMAKE_INSTALL_MANIFEST_CONTENT}\")\n"; + " file(WRITE \"" << homedir << "/${CMAKE_INSTALL_MANIFEST}\"\n" + " \"${CMAKE_INSTALL_MANIFEST_CONTENT}\")\n" + "endif()\n"; /* clang-format on */ } } diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 76a68b4..184a074 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -252,6 +252,7 @@ if(CMAKE_GENERATOR MATCHES "Ninja") add_RunCMake_test(NinjaPrivateDeps -DCMAKE_C_OUTPUT_EXTENSION=${CMAKE_C_OUTPUT_EXTENSION} -DRunCMake_GENERATOR_IS_MULTI_CONFIG=${_isMultiConfig}) + add_RunCMake_test(InstallParallel) endif() add_RunCMake_test(CTest) diff --git a/Tests/RunCMake/InstallParallel/CMakeLists.txt b/Tests/RunCMake/InstallParallel/CMakeLists.txt new file mode 100644 index 0000000..94e43ba --- /dev/null +++ b/Tests/RunCMake/InstallParallel/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.29) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/InstallParallel/RunCMakeTest.cmake b/Tests/RunCMake/InstallParallel/RunCMakeTest.cmake new file mode 100644 index 0000000..ae3f112 --- /dev/null +++ b/Tests/RunCMake/InstallParallel/RunCMakeTest.cmake @@ -0,0 +1,17 @@ +include(RunCMake) + +function(install_test test parallel install_target check_script) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-install) + set(RunCMake_TEST_OPTIONS -DINSTALL_PARALLEL=${parallel}) + if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) + list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug) + endif() + run_cmake(install) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(${test}-install ${CMAKE_COMMAND} --build . --config Debug -t ${install_target}) + set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY ${RunCMake_SOURCE_DIR}) + run_cmake_command(verify-parallel ${CMAKE_COMMAND} -P ${check_script} ${RunCMake_TEST_BINARY_DIR}/.ninja_log) +endfunction() + +install_test(parallel 1 install/parallel check-parallel.cmake) +install_test(no-parallel 0 install check-single.cmake) diff --git a/Tests/RunCMake/InstallParallel/check-parallel.cmake b/Tests/RunCMake/InstallParallel/check-parallel.cmake new file mode 100644 index 0000000..4e4cf52 --- /dev/null +++ b/Tests/RunCMake/InstallParallel/check-parallel.cmake @@ -0,0 +1,15 @@ +include(read-ninja-install.cmake) + +foreach(line ${lines}) + string(REPLACE "\t" ";" line ${line}) + list(GET line 0 start) + list(GET line 1 end) + list(APPEND start_times ${start}) + list(APPEND end_times ${end}) +endforeach() +list(GET start_times 1 start_2) +list(GET end_times 0 end_1) + +if (NOT start_2 LESS end_1) + message(FATAL_ERROR "Install is not parallel") +endif() diff --git a/Tests/RunCMake/InstallParallel/check-single.cmake b/Tests/RunCMake/InstallParallel/check-single.cmake new file mode 100644 index 0000000..79c4d5c --- /dev/null +++ b/Tests/RunCMake/InstallParallel/check-single.cmake @@ -0,0 +1,5 @@ +include(read-ninja-install.cmake) +list(LENGTH lines len) +if (NOT ${len} STREQUAL "1") + message(FATAL_ERROR "Expected single installation call") +endif() diff --git a/Tests/RunCMake/InstallParallel/install.cmake b/Tests/RunCMake/InstallParallel/install.cmake new file mode 100644 index 0000000..54b5078 --- /dev/null +++ b/Tests/RunCMake/InstallParallel/install.cmake @@ -0,0 +1,6 @@ +install(CODE "message(installing:${CMAKE_CURRENT_SOURCE_DIR})") +if (INSTALL_PARALLEL) + set_property(GLOBAL PROPERTY INSTALL_PARALLEL ON) +endif() +add_subdirectory(subdir-1) +add_subdirectory(subdir-2) diff --git a/Tests/RunCMake/InstallParallel/no-parallel-install-stderr.txt b/Tests/RunCMake/InstallParallel/no-parallel-install-stderr.txt new file mode 100644 index 0000000..8f69a04 --- /dev/null +++ b/Tests/RunCMake/InstallParallel/no-parallel-install-stderr.txt @@ -0,0 +1,5 @@ +installing:.* +installing:.* +installing:.* +installing:.* +installing:.* diff --git a/Tests/RunCMake/InstallParallel/parallel-install-stdout.txt b/Tests/RunCMake/InstallParallel/parallel-install-stdout.txt new file mode 100644 index 0000000..e0d2a56 --- /dev/null +++ b/Tests/RunCMake/InstallParallel/parallel-install-stdout.txt @@ -0,0 +1,15 @@ +\[1\/5\] Installing only the local directory... +\-\- Install configuration: \"Debug\" +installing:.* +\[2\/5\] Installing only the local directory... +\-\- Install configuration: \"Debug\" +installing:.* +\[3\/5\] Installing only the local directory... +\-\- Install configuration: \"Debug\" +installing:.* +\[4\/5\] Installing only the local directory... +\-\- Install configuration: \"Debug\" +installing:.* +\[5\/5\] Installing only the local directory... +\-\- Install configuration: \"Debug\" +installing:.* diff --git a/Tests/RunCMake/InstallParallel/read-ninja-install.cmake b/Tests/RunCMake/InstallParallel/read-ninja-install.cmake new file mode 100644 index 0000000..731c5eb --- /dev/null +++ b/Tests/RunCMake/InstallParallel/read-ninja-install.cmake @@ -0,0 +1,4 @@ +set(ninja_log ${CMAKE_ARGV3}) +file(STRINGS ${ninja_log} lines) +list(POP_FRONT lines) +list(FILTER lines INCLUDE REGEX ".*install.*util") diff --git a/Tests/RunCMake/InstallParallel/subdir-1/CMakeLists.txt b/Tests/RunCMake/InstallParallel/subdir-1/CMakeLists.txt new file mode 100644 index 0000000..6b235c4 --- /dev/null +++ b/Tests/RunCMake/InstallParallel/subdir-1/CMakeLists.txt @@ -0,0 +1,3 @@ +install(CODE "message(installing:${CMAKE_CURRENT_SOURCE_DIR})") +add_subdirectory(subdir-3) +add_subdirectory(subdir-4) diff --git a/Tests/RunCMake/InstallParallel/subdir-1/subdir-3/CMakeLists.txt b/Tests/RunCMake/InstallParallel/subdir-1/subdir-3/CMakeLists.txt new file mode 100644 index 0000000..dd7eac3 --- /dev/null +++ b/Tests/RunCMake/InstallParallel/subdir-1/subdir-3/CMakeLists.txt @@ -0,0 +1 @@ +install(CODE "message(installing:${CMAKE_CURRENT_SOURCE_DIR})") diff --git a/Tests/RunCMake/InstallParallel/subdir-1/subdir-4/CMakeLists.txt b/Tests/RunCMake/InstallParallel/subdir-1/subdir-4/CMakeLists.txt new file mode 100644 index 0000000..dd7eac3 --- /dev/null +++ b/Tests/RunCMake/InstallParallel/subdir-1/subdir-4/CMakeLists.txt @@ -0,0 +1 @@ +install(CODE "message(installing:${CMAKE_CURRENT_SOURCE_DIR})") diff --git a/Tests/RunCMake/InstallParallel/subdir-2/CMakeLists.txt b/Tests/RunCMake/InstallParallel/subdir-2/CMakeLists.txt new file mode 100644 index 0000000..dd7eac3 --- /dev/null +++ b/Tests/RunCMake/InstallParallel/subdir-2/CMakeLists.txt @@ -0,0 +1 @@ +install(CODE "message(installing:${CMAKE_CURRENT_SOURCE_DIR})") |