1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-19 11:18:40 +08:00

install: Write manifest file in parallel install

Updates the parallel install to generate the install_manifest.txt file.
This commit is contained in:
Martin Duffy
2024-07-18 14:57:40 -04:00
parent d39b8044b6
commit 9799491c7e
20 changed files with 225 additions and 111 deletions

View File

@@ -16,6 +16,11 @@
#include <cm3p/json/value.h> #include <cm3p/json/value.h>
#include <cm3p/uv.h> #include <cm3p/uv.h>
#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"
#include "cmCryptoHash.h"
#include "cmGeneratedFileStream.h"
#include "cmJSONState.h" #include "cmJSONState.h"
#include "cmProcessOutput.h" #include "cmProcessOutput.h"
#include "cmStringAlgorithms.h" #include "cmStringAlgorithms.h"
@@ -26,15 +31,19 @@
using InstallScript = cmInstallScriptHandler::InstallScript; using InstallScript = cmInstallScriptHandler::InstallScript;
cmInstallScriptHandler::cmInstallScriptHandler(const std::string& binary_dir, cmInstallScriptHandler::cmInstallScriptHandler(std::string _binaryDir,
std::string _component,
std::vector<std::string>& args) std::vector<std::string>& args)
: binaryDir(std::move(_binaryDir))
, component(std::move(_component))
{ {
const std::string& file = const std::string& file =
cmStrCat(binary_dir, "/CMakeFiles/InstallScripts.json"); cmStrCat(this->binaryDir, "/CMakeFiles/InstallScripts.json");
if (cmSystemTools::FileExists(file)) { if (cmSystemTools::FileExists(file)) {
int compare; int compare;
cmSystemTools::FileTimeCompare( cmSystemTools::FileTimeCompare(
cmStrCat(binary_dir, "/CMakeFiles/cmake.check_cache"), file, &compare); cmStrCat(this->binaryDir, "/CMakeFiles/cmake.check_cache"), file,
&compare);
if (compare < 1) { if (compare < 1) {
args.insert(args.end() - 1, "-DCMAKE_INSTALL_LOCAL_ONLY=1"); args.insert(args.end() - 1, "-DCMAKE_INSTALL_LOCAL_ONLY=1");
Json::CharReaderBuilder rbuilder; Json::CharReaderBuilder rbuilder;
@@ -46,6 +55,8 @@ cmInstallScriptHandler::cmInstallScriptHandler(const std::string& binary_dir,
for (auto const& script : value["InstallScripts"]) { for (auto const& script : value["InstallScripts"]) {
this->commands.push_back(args); this->commands.push_back(args);
this->commands.back().emplace_back(script.asCString()); this->commands.back().emplace_back(script.asCString());
this->directories.push_back(
cmSystemTools::GetFilenamePath(script.asCString()));
} }
} }
} }
@@ -79,6 +90,36 @@ int cmInstallScriptHandler::install(unsigned int j)
} }
uv_run(loop, UV_RUN_DEFAULT); uv_run(loop, UV_RUN_DEFAULT);
} }
// Write install manifest
std::string install_manifest;
if (this->component.empty()) {
install_manifest = "install_manifest.txt";
} else {
cmsys::RegularExpression regEntry;
if (regEntry.compile("^[a-zA-Z0-9_.+-]+$") &&
regEntry.find(this->component)) {
install_manifest =
cmStrCat("install_manifest_", this->component, ".txt");
} else {
cmCryptoHash md5(cmCryptoHash::AlgoMD5);
md5.Initialize();
install_manifest =
cmStrCat("install_manifest_", md5.HashString(this->component), ".txt");
}
}
cmGeneratedFileStream fout(cmStrCat(this->binaryDir, "/", install_manifest));
fout.SetCopyIfDifferent(true);
for (auto const& dir : this->directories) {
auto local_manifest = cmStrCat(dir, "/install_local_manifest.txt");
if (cmSystemTools::FileExists(local_manifest)) {
cmsys::ifstream fin(local_manifest.c_str());
std::string line;
while (std::getline(fin, line)) {
fout << line << "\n";
}
}
}
return 0; return 0;
} }

View File

@@ -16,7 +16,7 @@ class cmInstallScriptHandler
{ {
public: public:
cmInstallScriptHandler() = default; cmInstallScriptHandler() = default;
cmInstallScriptHandler(const std::string&, std::vector<std::string>&); cmInstallScriptHandler(std::string, std::string, std::vector<std::string>&);
bool isParallel(); bool isParallel();
int install(unsigned int j); int install(unsigned int j);
class InstallScript class InstallScript
@@ -37,4 +37,7 @@ public:
private: private:
std::vector<std::vector<std::string>> commands; std::vector<std::vector<std::string>> commands;
std::vector<std::string> directories;
std::string binaryDir;
std::string component;
}; };

View File

@@ -713,32 +713,40 @@ void cmLocalGenerator::GenerateInstallRules()
break; break;
} }
// Record the install manifest. /* clang-format off */
if (toplevel_install) {
/* clang-format off */
fout << fout <<
"if(CMAKE_INSTALL_COMPONENT)\n" "string(REPLACE \";\" \"\\n\" CMAKE_INSTALL_MANIFEST_CONTENT\n"
" if(CMAKE_INSTALL_COMPONENT MATCHES \"^[a-zA-Z0-9_.+-]+$\")\n"
" set(CMAKE_INSTALL_MANIFEST \"install_manifest_"
"${CMAKE_INSTALL_COMPONENT}.txt\")\n"
" else()\n"
" string(MD5 CMAKE_INST_COMP_HASH \"${CMAKE_INSTALL_COMPONENT}\")\n"
" set(CMAKE_INSTALL_MANIFEST \"install_manifest_"
"${CMAKE_INST_COMP_HASH}.txt\")\n"
" unset(CMAKE_INST_COMP_HASH)\n"
" endif()\n"
"else()\n"
" set(CMAKE_INSTALL_MANIFEST \"install_manifest.txt\")\n"
"endif()\n"
"\n"
"if(NOT CMAKE_INSTALL_LOCAL_ONLY)\n"
" string(REPLACE \";\" \"\\n\" CMAKE_INSTALL_MANIFEST_CONTENT\n"
" \"${CMAKE_INSTALL_MANIFEST_FILES}\")\n" " \"${CMAKE_INSTALL_MANIFEST_FILES}\")\n"
" file(WRITE \"" << homedir << "/${CMAKE_INSTALL_MANIFEST}\"\n" "if(CMAKE_INSTALL_LOCAL_ONLY)\n"
" file(WRITE \"" <<
this->StateSnapshot.GetDirectory().GetCurrentBinary() <<
"/install_local_manifest.txt\"\n"
" \"${CMAKE_INSTALL_MANIFEST_CONTENT}\")\n" " \"${CMAKE_INSTALL_MANIFEST_CONTENT}\")\n"
"endif()\n"; "endif()\n";
/* clang-format on */
} if (toplevel_install) {
fout <<
"if(CMAKE_INSTALL_COMPONENT)\n"
" if(CMAKE_INSTALL_COMPONENT MATCHES \"^[a-zA-Z0-9_.+-]+$\")\n"
" set(CMAKE_INSTALL_MANIFEST \"install_manifest_"
"${CMAKE_INSTALL_COMPONENT}.txt\")\n"
" else()\n"
" string(MD5 CMAKE_INST_COMP_HASH \"${CMAKE_INSTALL_COMPONENT}\")\n"
" set(CMAKE_INSTALL_MANIFEST \"install_manifest_"
"${CMAKE_INST_COMP_HASH}.txt\")\n"
" unset(CMAKE_INST_COMP_HASH)\n"
" endif()\n"
"else()\n"
" set(CMAKE_INSTALL_MANIFEST \"install_manifest.txt\")\n"
"endif()\n"
"\n"
"if(NOT CMAKE_INSTALL_LOCAL_ONLY)\n"
" file(WRITE \"" << homedir << "/${CMAKE_INSTALL_MANIFEST}\"\n"
" \"${CMAKE_INSTALL_MANIFEST_CONTENT}\")\n"
"endif()\n";
}
/* clang-format on */
} }
void cmLocalGenerator::AddGeneratorTarget( void cmLocalGenerator::AddGeneratorTarget(

View File

@@ -922,7 +922,7 @@ int do_install(int ac, char const* const* av)
args.emplace_back("-P"); args.emplace_back("-P");
auto handler = cmInstallScriptHandler(dir, args); auto handler = cmInstallScriptHandler(dir, component, args);
int ret = 0; int ret = 0;
if (!handler.isParallel()) { if (!handler.isParallel()) {
args.emplace_back(cmStrCat(dir, "/cmake_install.cmake")); args.emplace_back(cmStrCat(dir, "/cmake_install.cmake"));

View File

@@ -1,36 +1,59 @@
include(RunCMake) include(RunCMake)
function(install_test test parallel install_arg) function(install_test test)
cmake_parse_arguments(ARGS "NINJA;TOUCH_CACHE" "VERIFY_SCRIPT" "" ${ARGN}) cmake_parse_arguments(ARGS "PARALLEL;NINJA;TOUCH_CACHE" "ARGS;COMPONENT" "" ${ARGN})
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-install) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-install)
set(RunCMake_TEST_OPTIONS -DINSTALL_PARALLEL=${parallel}) set(RunCMake_TEST_OPTIONS -DINSTALL_PARALLEL=${ARGS_PARALLEL} -DCMAKE_INSTALL_PREFIX=install)
set(RunCMake_TEST_OUTPUT_MERGE 1) set(RunCMake_TEST_OUTPUT_MERGE 1)
if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug) list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
endif() endif()
if (ARGS_COMPONENT)
list(APPEND ARGS_ARGS "--component ${ARGS_COMPONENT}")
endif()
run_cmake(install) run_cmake(install)
set(RunCMake_TEST_NO_CLEAN 1) set(RunCMake_TEST_NO_CLEAN 1)
if (ARGS_TOUCH_CACHE) if (ARGS_TOUCH_CACHE)
run_cmake_command(${test}-sleep ${CMAKE_COMMAND} -E sleep 2)
run_cmake_command(${test}-touch run_cmake_command(${test}-touch
${CMAKE_COMMAND} -E touch ${RunCMake_TEST_BINARY_DIR}/CMakeFiles/cmake.check_cache) ${CMAKE_COMMAND} -E touch ${RunCMake_TEST_BINARY_DIR}/CMakeFiles/cmake.check_cache)
endif() endif()
if (ARGS_NINJA) if (ARGS_NINJA)
run_cmake_command(${test}-install ${CMAKE_COMMAND} --build . --config Debug -t ${install_arg}) if (ARGS_PARALLEL)
set(INSTALL_COUNT 5)
else()
set(INSTALL_COUNT 1)
endif()
set(RunCMake-check-file check-num-installs.cmake)
run_cmake_command(${test}-install ${CMAKE_COMMAND} --build . --config Debug ${ARGS_ARGS})
unset(RunCMake-check-file)
else() else()
run_cmake_command(${test}-install ${CMAKE_COMMAND} --install . -j ${install_arg}) if (ARGS_COMPONENT)
if(ARGS_COMPONENT MATCHES "^[a-zA-Z0-9_.+-]+$")
set(INSTALL_MANIFEST "install_manifest_${ARGS_COMPONENT}.txt")
else()
string(MD5 COMPONENT_HASH "${ARGS_COMPONENT}")
set(INSTALL_MANIFEST "install_manifest_${COMPONENT_HASH}.txt")
endif()
set(INSTALL_COUNT 0)
else()
set(INSTALL_MANIFEST "install_manifest.txt")
set(INSTALL_COUNT 5)
endif()
set(INSTALL_MANIFEST ${RunCMake_TEST_BINARY_DIR}/${INSTALL_MANIFEST})
set(RunCMake-check-file check-manifest.cmake)
run_cmake_command(${test}-install ${CMAKE_COMMAND} --install . ${ARGS_ARGS})
unset(RunCMake-check-file)
endif() endif()
set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY ${RunCMake_SOURCE_DIR})
if (ARGS_VERIFY_SCRIPT)
run_cmake_command(${test}-verify-parallel
${CMAKE_COMMAND} -P ${ARGS_VERIFY_SCRIPT} ${RunCMake_TEST_BINARY_DIR}/.ninja_log)
endif()
endfunction() endfunction()
install_test(parallel 1 4) install_test(parallel PARALLEL ARGS "-j 4")
install_test(no-parallel 0 4) install_test(no-parallel ARGS "-j 4")
install_test(out-of-date-json 1 4 TOUCH_CACHE) install_test(out-of-date-json TOUCH_CACHE PARALLEL ARGS "-j 4")
install_test(component PARALLEL ARGS "-j 4" COMPONENT "ALPHANUMERIC123")
install_test(component-hash PARALLEL ARGS "-j 4" COMPONENT "@#$")
if(RunCMake_GENERATOR MATCHES "Ninja") if(RunCMake_GENERATOR MATCHES "Ninja")
install_test(ninja-parallel 1 install/parallel VERIFY_SCRIPT check-parallel.cmake NINJA) install_test(ninja-parallel ARGS "-t install/parallel" NINJA PARALLEL)
install_test(ninja-no-parallel 0 install VERIFY_SCRIPT check-single.cmake NINJA) install_test(ninja-no-parallel ARGS "-t install" NINJA)
endif() endif()

View File

@@ -0,0 +1,10 @@
if (NOT EXISTS ${INSTALL_MANIFEST})
set(RunCMake_TEST_FAILED "Install manifest not generated: ${INSTALL_MANIFEST}")
endif()
file(STRINGS ${INSTALL_MANIFEST} lines ENCODING UTF-8)
list(LENGTH lines len)
if (NOT len EQUAL ${INSTALL_COUNT})
set(RunCMake_TEST_FAILED "Install manifest missing content: ${len}/${INSTALL_COUNT}")
endif()

View File

@@ -0,0 +1,7 @@
file(STRINGS ${RunCMake_TEST_BINARY_DIR}/.ninja_log lines ENCODING UTF-8)
list(FILTER lines INCLUDE REGEX ".*install.*util")
list(LENGTH lines len)
if (NOT ${len} STREQUAL ${INSTALL_COUNT})
set(RunCMake_TEST_FAILED "Wrong number of cmake -P calls to install: ${len}/${INSTALL_COUNT}")
endif()

View File

@@ -1,15 +0,0 @@
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()

View File

@@ -1,5 +0,0 @@
include(read-ninja-install.cmake)
list(LENGTH lines len)
if (NOT ${len} STREQUAL "1")
message(FATAL_ERROR "Expected single installation call")
endif()

View File

@@ -1,4 +1,4 @@
install(CODE "message(installing:${CMAKE_CURRENT_SOURCE_DIR})") install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt TYPE DATA RENAME root.txt)
if (INSTALL_PARALLEL) if (INSTALL_PARALLEL)
set_property(GLOBAL PROPERTY INSTALL_PARALLEL ON) set_property(GLOBAL PROPERTY INSTALL_PARALLEL ON)
endif() endif()

View File

@@ -1,5 +1,12 @@
installing:.* \-\- Install configuration:[^
installing:.* ]*
installing:.* \-\- Installing:[^
installing:.* ]*
installing:.* \-\- Installing:[^
]*
\-\- Installing:[^
]*
\-\- Installing:[^
]*
\-\- Installing:[^
]*

View File

@@ -1,15 +1,25 @@
\[1\/5\] Installing only the local directory... \[1\/5\] Installing only the local directory...
\-\- Install configuration:.* \-\- Install configuration:[^
installing:.* ]*
\-\- Installing:[^
]*
\[2\/5\] Installing only the local directory... \[2\/5\] Installing only the local directory...
\-\- Install configuration:.* \-\- Install configuration:[^
installing:.* ]*
\-\- Installing:[^
]*
\[3\/5\] Installing only the local directory... \[3\/5\] Installing only the local directory...
\-\- Install configuration:.* \-\- Install configuration:[^
installing:.* ]*
\-\- Installing:[^
]*
\[4\/5\] Installing only the local directory... \[4\/5\] Installing only the local directory...
\-\- Install configuration:.* \-\- Install configuration:[^
installing:.* ]*
\-\- Installing:[^
]*
\[5\/5\] Installing only the local directory... \[5\/5\] Installing only the local directory...
\-\- Install configuration:.* \-\- Install configuration:[^
installing:.* ]*
\-\- Installing:[^
]*

View File

@@ -1,5 +1,12 @@
installing:.* \-\- Install configuration:[^
installing:.* ]*
installing:.* \-\- Installing:[^
installing:.* ]*
installing:.* \-\- Installing:[^
]*
\-\- Installing:[^
]*
\-\- Installing:[^
]*
\-\- Installing:[^
]*

View File

@@ -1,5 +1,12 @@
installing:.* \-\- Install configuration:[^
installing:.* ]*
installing:.* \-\- Installing:[^
installing:.* ]*
installing:.* \-\- Installing:[^
]*
\-\- Installing:[^
]*
\-\- Installing:[^
]*
\-\- Installing:[^
]*

View File

@@ -1,15 +1,30 @@
\[1\/5\] .* \[1\/5\] [^
\-\- Install configuration:.* ]*
installing:.* \-\- Install configuration:[^
\[2\/5\] .* ]*
\-\- Install configuration:.* \-\- Installing:[^
installing:.* ]*
\[3\/5\] .* \[2\/5\] [^
\-\- Install configuration:.* ]*
installing:.* \-\- Install configuration:[^
\[4\/5\] .* ]*
\-\- Install configuration:.* \-\- Installing:[^
installing:.* ]*
\[5\/5\] .* \[3\/5\] [^
\-\- Install configuration:.* ]*
installing:.* \-\- Install configuration:[^
]*
\-\- Installing:[^
]*
\[4\/5\] [^
]*
\-\- Install configuration:[^
]*
\-\- Installing:[^
]*
\[5\/5\] [^
]*
\-\- Install configuration:[^
]*
\-\- Installing:[^
]*

View File

@@ -1,4 +0,0 @@
set(ninja_log ${CMAKE_ARGV3})
file(STRINGS ${ninja_log} lines)
list(POP_FRONT lines)
list(FILTER lines INCLUDE REGEX ".*install.*util")

View File

@@ -1,3 +1,3 @@
install(CODE "message(installing:${CMAKE_CURRENT_SOURCE_DIR})") install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt TYPE DATA RENAME 1.txt)
add_subdirectory(subdir-3) add_subdirectory(subdir-3)
add_subdirectory(subdir-4) add_subdirectory(subdir-4)

View File

@@ -1 +1 @@
install(CODE "message(installing:${CMAKE_CURRENT_SOURCE_DIR})") install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt TYPE DATA RENAME 3.txt)

View File

@@ -1 +1 @@
install(CODE "message(installing:${CMAKE_CURRENT_SOURCE_DIR})") install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt TYPE DATA RENAME 4.txt)

View File

@@ -1 +1 @@
install(CODE "message(installing:${CMAKE_CURRENT_SOURCE_DIR})") install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt TYPE DATA RENAME 2.txt)