Ninja Multi-Config: Provide {test,install}_prep default config aliases

Fixes: #28168
This commit is contained in:
Tyler Yankee committed 2026-10-14 09:12:56 -04:00
1 parent c739e7ae98
commit 3882e26cef
9 files changed
+192 -22

No files matched your search

+86 -21
View File
@@ -1306,14 +1306,17 @@ void cmGlobalNinjaGenerator::WriteInstallPrepTargets()
}
this->CheckInstallPrepTargets();
auto writeConfig = [this](std::string const& config, std::ostream& os) {
std::map<std::string, std::set<std::string>> configsByName;
auto writeConfig = [this, &configsByName](std::string const& config) {
auto writePrepTarget =
[this, &config,
&os](std::string const& name,
cmGlobalGenerator::InstallPrepTargets::TargetMap const& targets,
std::set<std::string> const& files) {
[this, &config, &configsByName](
std::string const& name,
cmGlobalGenerator::InstallPrepTargets::TargetMap const& targets,
std::set<std::string> const& files) {
std::string const prepName = this->ConvertToNinjaPath(name);
configsByName[prepName].insert(config);
cmNinjaBuild build("phony");
build.Outputs.push_back(this->ConvertToNinjaPath(name));
build.Outputs.push_back(this->BuildAlias(prepName, config));
for (std::string const& file : files) {
build.ExplicitDeps.push_back(this->ConvertToNinjaPath(file));
}
@@ -1330,7 +1333,7 @@ void cmGlobalNinjaGenerator::WriteInstallPrepTargets()
build.ExplicitDeps.erase(
std::unique(build.ExplicitDeps.begin(), build.ExplicitDeps.end()),
build.ExplicitDeps.end());
this->WriteBuild(os, build);
this->WritePerConfigPhony(config, build);
};
InstallPrepTargets const prepTargets = this->GetInstallPrepTargets(config);
@@ -1347,16 +1350,18 @@ void cmGlobalNinjaGenerator::WriteInstallPrepTargets()
if (this->IsMultiConfig()) {
for (std::string const& config : this->GetConfigNames()) {
writeConfig(config, *this->GetConfigFileStream(config));
writeConfig(config);
}
} else {
writeConfig(this->GetConfigNames().front(), *this->GetCommonFileStream());
writeConfig(this->GetConfigNames().front());
}
this->WritePerConfigPhonyAliases(configsByName);
}
void cmGlobalNinjaGenerator::WriteTestPrepTargets()
{
auto writeConfig = [this](std::string const& config, std::ostream& os) {
std::map<std::string, std::set<std::string>> configsByName;
auto writeConfig = [this, &configsByName](std::string const& config) {
struct TestPrepTarget
{
std::string Comment;
@@ -1414,9 +1419,10 @@ void cmGlobalNinjaGenerator::WriteTestPrepTargets()
std::vector<std::string> allDeps;
for (auto& prepTarget : testPrepTargets) {
configsByName[prepTarget.first].insert(config);
cmNinjaBuild build("phony");
build.Comment = prepTarget.second.Comment;
build.Outputs.push_back(prepTarget.first);
build.Outputs.push_back(this->BuildAlias(prepTarget.first, config));
// Avoid duplicate dependencies when merging test_prep/ targets
auto& explicitDeps = prepTarget.second.ExplicitDeps;
@@ -1425,16 +1431,17 @@ void cmGlobalNinjaGenerator::WriteTestPrepTargets()
explicitDeps.end());
build.ExplicitDeps = std::move(explicitDeps);
allDeps.push_back(prepTarget.first);
this->WriteBuild(os, build);
allDeps.push_back(build.Outputs.front());
this->WritePerConfigPhony(config, build);
}
std::string const allName = this->ConvertToNinjaPath("test_prep/all");
configsByName[allName].insert(config);
cmNinjaBuild build("phony");
build.Comment = "Build dependencies for all tests";
build.Outputs.push_back(this->ConvertToNinjaPath("test_prep/all"));
build.Outputs.push_back(this->BuildAlias(allName, config));
build.ExplicitDeps = std::move(allDeps);
this->WriteBuild(os, build);
return true;
this->WritePerConfigPhony(config, build);
};
if (!this->Makefiles.front()->IsOn("CMAKE_TEST_BUILD_DEPENDS")) {
@@ -1442,13 +1449,71 @@ void cmGlobalNinjaGenerator::WriteTestPrepTargets()
}
if (this->IsMultiConfig()) {
for (std::string const& config : this->GetConfigNames()) {
if (!writeConfig(config, *this->GetConfigFileStream(config))) {
return;
}
writeConfig(config);
}
} else {
writeConfig(this->Makefiles.front()->GetSafeDefinition("CMAKE_BUILD_TYPE"),
*this->GetCommonFileStream());
writeConfig(
this->Makefiles.front()->GetSafeDefinition("CMAKE_BUILD_TYPE"));
}
this->WritePerConfigPhonyAliases(configsByName);
}
void cmGlobalNinjaGenerator::WritePerConfigPhony(std::string const& config,
cmNinjaBuild const& build)
{
this->WriteBuild(this->EnableCrossConfigBuild() &&
this->CrossConfigs.count(config)
? *this->GetCommonFileStream()
: *this->GetImplFileStream(config),
build);
}
void cmGlobalNinjaGenerator::WritePerConfigPhonyAliases(
std::map<std::string, std::set<std::string>> const& configsByName)
{
if (!this->IsMultiConfig()) {
return;
}
cmNinjaBuild build("phony");
build.Outputs.emplace_back();
for (auto const& entry : configsByName) {
std::string const& name = entry.first;
std::set<std::string> const& configs = entry.second;
// Add shortcut target in each config's build file
build.Outputs.front() = name;
for (std::string const& config : configs) {
build.ExplicitDeps = { this->BuildAlias(name, config) };
this->WriteBuild(*this->GetConfigFileStream(config), build);
}
// Add shortcut target in the default build file
if (!this->DefaultConfigs.empty()) {
build.ExplicitDeps.clear();
for (std::string const& config : this->DefaultConfigs) {
if (configs.count(config)) {
build.ExplicitDeps.push_back(this->BuildAlias(name, config));
}
}
if (!build.ExplicitDeps.empty()) {
this->WriteBuild(*this->GetDefaultFileStream(), build);
}
}
// Add target for all configs
if (this->EnableCrossConfigBuild()) {
build.ExplicitDeps.clear();
for (std::string const& config : this->CrossConfigs) {
if (configs.count(config)) {
build.ExplicitDeps.push_back(this->BuildAlias(name, config));
}
}
if (!build.ExplicitDeps.empty()) {
build.Outputs.front() = this->BuildAlias(name, "all");
this->WriteBuild(*this->GetCommonFileStream(), build);
}
}
}
}
+5
View File
@@ -537,6 +537,11 @@ private:
void WriteInstallPrepTargets();
void WriteTestPrepTargets();
void WritePerConfigPhony(std::string const& config,
cmNinjaBuild const& build);
void WritePerConfigPhonyAliases(
std::map<std::string, std::set<std::string>> const& configsByName);
void WriteTargetAliases(std::ostream& os);
void WriteFolderTargets(std::ostream& os);
@@ -0,0 +1,16 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_FILE_installlib_Debug}
${TARGET_OBJECT_FILES_installlib_Debug}
${TARGET_FILE_installlib_Release}
${TARGET_OBJECT_FILES_installlib_Release}
${TARGET_FILE_installlib_RelWithDebInfo}
${TARGET_OBJECT_FILES_installlib_RelWithDebInfo}
EXCLUDE
${TARGET_OBJECT_FILES_testexe_Debug}
${TARGET_OBJECT_FILES_testexe_Release}
${TARGET_OBJECT_FILES_testexe_RelWithDebInfo}
)
@@ -0,0 +1,13 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_FILE_testexe_Debug}
${TARGET_OBJECT_FILES_testexe_Debug}
EXCLUDE
${TARGET_OBJECT_FILES_testexe_Release}
${TARGET_OBJECT_FILES_testexe_RelWithDebInfo}
${TARGET_OBJECT_FILES_installlib_Debug}
${TARGET_OBJECT_FILES_installlib_Release}
${TARGET_OBJECT_FILES_installlib_RelWithDebInfo}
)
@@ -0,0 +1,15 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_FILE_installlib_Debug}
${TARGET_OBJECT_FILES_installlib_Debug}
${TARGET_FILE_installlib_Release}
${TARGET_OBJECT_FILES_installlib_Release}
EXCLUDE
${TARGET_OBJECT_FILES_testexe_Debug}
${TARGET_OBJECT_FILES_testexe_Release}
${TARGET_OBJECT_FILES_testexe_RelWithDebInfo}
${TARGET_OBJECT_FILES_installlib_RelWithDebInfo}
)
@@ -0,0 +1,15 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_FILE_testexe_Debug}
${TARGET_OBJECT_FILES_testexe_Debug}
${TARGET_FILE_testexe_Release}
${TARGET_OBJECT_FILES_testexe_Release}
EXCLUDE
${TARGET_OBJECT_FILES_testexe_RelWithDebInfo}
${TARGET_OBJECT_FILES_installlib_Debug}
${TARGET_OBJECT_FILES_installlib_Release}
${TARGET_OBJECT_FILES_installlib_RelWithDebInfo}
)
@@ -0,0 +1,13 @@
check_files("${RunCMake_TEST_BINARY_DIR}"
INCLUDE
${TARGET_FILE_testexe_Release}
${TARGET_OBJECT_FILES_testexe_Release}
EXCLUDE
${TARGET_OBJECT_FILES_testexe_Debug}
${TARGET_OBJECT_FILES_testexe_RelWithDebInfo}
${TARGET_OBJECT_FILES_installlib_Debug}
${TARGET_OBJECT_FILES_installlib_Release}
${TARGET_OBJECT_FILES_installlib_RelWithDebInfo}
)
@@ -0,0 +1,13 @@
enable_language(C)
set(CMAKE_TEST_BUILD_DEPENDS ON)
enable_testing()
add_executable(testexe main.c)
add_test(NAME prep COMMAND testexe)
add_library(installlib STATIC simplelib.c)
install(TARGETS installlib DESTINATION lib/$<CONFIG> COMPONENT Dev)
include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake)
generate_output_files(testexe installlib)
@@ -17,7 +17,7 @@ function(check_files dir)
list(SORT expected)
file(GLOB_RECURSE actual "${dir}/*")
list(FILTER actual EXCLUDE REGEX "/CMakeFiles/|\\.ninja$|/CMakeCache\\.txt$|/target_files[^/]*\\.cmake$|/\\.ninja_[^/]*$|/cmake_install\\.cmake$|\\.ilk$|\\.manifest$|\\.odx$|\\.pdb$|\\.exp$|/install_manifest\\.txt$|/\\.qt/(QtDeploySupport|QtDeployTargets)[^/]*\\.cmake$")
list(FILTER actual EXCLUDE REGEX "/CMakeFiles/|\\.ninja$|/CMakeCache\\.txt$|/target_files[^/]*\\.cmake$|/\\.ninja_[^/]*$|/cmake_install\\.cmake$|/CTestTestfile\\.cmake$|\\.ilk$|\\.manifest$|\\.odx$|\\.pdb$|\\.exp$|/install_manifest\\.txt$|/\\.qt/(QtDeploySupport|QtDeployTargets)[^/]*\\.cmake$")
foreach(f IN LISTS _check_files_INCLUDE _check_files_EXCLUDE)
if(EXISTS ${f})
list(APPEND actual ${f})
@@ -435,6 +435,21 @@ run_ninja(Install default-install build.ninja install)
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}/install")
run_ninja(Install all-install build.ninja install:all)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/PrepTargets-build)
set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release\\;RelWithDebInfo;-DCMAKE_CROSS_CONFIGS=all;-DCMAKE_DEFAULT_CONFIGS=Debug\\;Release")
run_cmake_configure(PrepTargets)
unset(RunCMake_TEST_OPTIONS)
include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake)
run_ninja(PrepTargets default-test build.ninja test_prep/prep)
run_ninja(PrepTargets default-test-clean build.ninja clean:all)
run_ninja(PrepTargets default-install build.ninja install_prep/Dev)
run_ninja(PrepTargets default-install-clean build.ninja clean:all)
run_ninja(PrepTargets release-test build-Release.ninja test_prep/all)
run_ninja(PrepTargets release-test-clean build.ninja clean:all)
run_ninja(PrepTargets debug-in-relwithdebinfo-graph-test build-RelWithDebInfo.ninja test_prep/all:Debug)
run_ninja(PrepTargets debug-in-relwithdebinfo-graph-test-clean build.ninja clean:all)
run_ninja(PrepTargets all-install build.ninja install_prep/all:all)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ExcludeFromAll-build)
run_cmake_configure(ExcludeFromAll)
include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake)