mirror of
https://github.com/Kitware/CMake.git
synced 2026-11-06 05:16:58 +00:00
FASTBuild: Add install_prep targets for minimal builds
Extend the `install_prep/<component>` and `install_prep/all` targets to the FASTBuild generator. Co-authored-by: Tyler Yankee <tyler.yankee@kitware.com> Issue: #27643
This commit is contained in:
1 parent
62e4f1577d
commit
e36cd0ac29
10 files changed
+136
-9
No files matched your search
@@ -32,6 +32,22 @@ This writes a FASTBuild configuration file named ``fbuild.bff`` into
|
||||
Built-in Targets
|
||||
----------------
|
||||
|
||||
.. versionadded:: 4.5
|
||||
|
||||
If the project has install rules, the generated build file provides the
|
||||
following targets, unless :variable:`CMAKE_SKIP_INSTALL_PREP_TARGETS` or
|
||||
:variable:`CMAKE_SKIP_INSTALL_RULES` is enabled:
|
||||
|
||||
``install_prep/<component>``
|
||||
Builds all known build dependencies for the install component named
|
||||
``<component>`` added by :command:`install`. Components whose names cannot
|
||||
be represented safely are excluded. See :ref:`Install Preparation Targets`
|
||||
and :ref:`Target Names`.
|
||||
|
||||
``install_prep/all``
|
||||
Builds all known build dependencies needed for an installation that does
|
||||
not select a component. See :ref:`Install Preparation Targets`.
|
||||
|
||||
.. versionadded:: 4.5
|
||||
|
||||
When the :variable:`CMAKE_TEST_BUILD_DEPENDS` variable is enabled, the
|
||||
|
||||
@@ -1782,9 +1782,9 @@ target properties with a limited set of names:
|
||||
Preparation Targets
|
||||
===================
|
||||
|
||||
The :ref:`Ninja Generators` and :ref:`Makefile Generators` provide convenience
|
||||
targets that build only the prerequisites of a later step, such as running
|
||||
tests or installing.
|
||||
The :ref:`Ninja Generators`, :ref:`Makefile Generators`, and
|
||||
:generator:`FASTBuild` generator provide convenience targets that build only
|
||||
the prerequisites of a later step, such as running tests or installing.
|
||||
|
||||
.. _`Install Preparation Targets`:
|
||||
|
||||
@@ -1860,11 +1860,11 @@ and custom targets. How such a file is prepared depends on how it is produced:
|
||||
* Any other generated file, such as a byproduct or the output of a custom
|
||||
command attached to more than one target, is prepared by depending on the
|
||||
file itself, which runs whatever produces it. The
|
||||
:ref:`Makefile Generators` cannot do so, so they warn. If a target
|
||||
installs the file (or the file set to which the file belongs), they build
|
||||
that target instead, which must therefore depend on the producer, e.g.,
|
||||
through :command:`add_dependencies`. Otherwise, they do not prepare the
|
||||
file.
|
||||
:ref:`Makefile Generators` and :generator:`FASTBuild` cannot do so, so they
|
||||
warn. If a target installs the file (or the file set to which the file
|
||||
belongs), they build that target instead, which must therefore depend on
|
||||
the producer, e.g., through :command:`add_dependencies`. Otherwise, they
|
||||
do not prepare the file.
|
||||
|
||||
For example:
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <cstdlib>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
||||
#include <cm/memory>
|
||||
@@ -1588,6 +1589,67 @@ void cmGlobalFastbuildGenerator::AddTargetAll()
|
||||
this->AddTarget(std::move(allAliasNode));
|
||||
}
|
||||
|
||||
void cmGlobalFastbuildGenerator::WriteInstallPrepTargets()
|
||||
{
|
||||
if (!this->AreInstallPrepTargetsEnabled()) {
|
||||
return;
|
||||
}
|
||||
this->CheckInstallPrepTargets();
|
||||
|
||||
cmGlobalGenerator::InstallPrepTargets prepTargets =
|
||||
this->GetInstallPrepTargets(this->GetConfigNames().front());
|
||||
|
||||
// FASTBuild target names are case-insensitive, so merge preparation targets
|
||||
// whose names differ only in case. Each of them then prepares a superset of
|
||||
// what its installation needs.
|
||||
std::map<std::string, FastbuildAliasNode> aliases;
|
||||
std::set<std::string> unownedGeneratedFiles;
|
||||
auto addAlias =
|
||||
[this, &aliases, &unownedGeneratedFiles](
|
||||
std::string const& name,
|
||||
cmGlobalGenerator::InstallPrepTargets::TargetMap const& targets) {
|
||||
FastbuildAliasNode& alias = aliases[cmSystemTools::LowerCase(name)];
|
||||
if (alias.Name.empty()) {
|
||||
alias.Name = name;
|
||||
alias.Hidden = false;
|
||||
}
|
||||
for (auto const& dependency : targets) {
|
||||
cmGeneratorTarget const* target = dependency.first;
|
||||
bool buildTarget =
|
||||
dependency.second.Normal || dependency.second.InstallArtifact;
|
||||
// FASTBuild has no node for a generated file that is not the unique
|
||||
// output of a target, such as a byproduct, so build its installing
|
||||
// target instead.
|
||||
for (std::string const& file : dependency.second.GeneratedFiles) {
|
||||
if (this->CheckInstallPrepGeneratedFile(target, file,
|
||||
unownedGeneratedFiles)) {
|
||||
alias.PreBuildDependencies.emplace(
|
||||
this->ConvertToFastbuildPath(file));
|
||||
} else if (target->IsInBuildSystem()) {
|
||||
buildTarget = true;
|
||||
}
|
||||
}
|
||||
if (buildTarget) {
|
||||
alias.PreBuildDependencies.emplace(target->GetName());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Add install_prep/all first so that it keeps its spelling.
|
||||
addAlias("install_prep/all", prepTargets.All);
|
||||
for (auto const& component : prepTargets.Components) {
|
||||
addAlias(cmStrCat("install_prep/", component.first), component.second);
|
||||
}
|
||||
|
||||
for (auto& entry : aliases) {
|
||||
FastbuildAliasNode& alias = entry.second;
|
||||
if (alias.PreBuildDependencies.empty()) {
|
||||
alias.PreBuildDependencies.emplace(FASTBUILD_NOOP_FILE_NAME);
|
||||
}
|
||||
this->WriteAlias(alias);
|
||||
}
|
||||
}
|
||||
|
||||
void cmGlobalFastbuildGenerator::WriteTestPrepTargets()
|
||||
{
|
||||
if (!this->Makefiles.front()->IsOn("CMAKE_TEST_BUILD_DEPENDS")) {
|
||||
@@ -1978,6 +2040,7 @@ void cmGlobalFastbuildGenerator::WriteTargets()
|
||||
*BuildFileStream << "}\n";
|
||||
}
|
||||
|
||||
WriteInstallPrepTargets();
|
||||
WriteTestPrepTargets();
|
||||
|
||||
if (!this->GetCMakeInstance()->GetIsInTryCompile()) {
|
||||
|
||||
@@ -543,6 +543,7 @@ public:
|
||||
void WriteTargetClean();
|
||||
|
||||
void AddTargetAll();
|
||||
void WriteInstallPrepTargets();
|
||||
void WriteTestPrepTargets();
|
||||
void AddGlobCheckExec();
|
||||
|
||||
|
||||
@@ -292,7 +292,7 @@ if(CMAKE_GENERATOR MATCHES "Ninja")
|
||||
-DRunCMake_GENERATOR_IS_MULTI_CONFIG=${_isMultiConfig})
|
||||
endif()
|
||||
add_RunCMake_test(InstallParallel)
|
||||
if(CMAKE_GENERATOR MATCHES "Make|Ninja")
|
||||
if(CMAKE_GENERATOR MATCHES "Make|Ninja|FASTBuild")
|
||||
add_RunCMake_test(InstallPrep)
|
||||
endif()
|
||||
add_RunCMake_test(CTest)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
check_prepared(${dependency}_case_dependency)
|
||||
@@ -6,6 +6,19 @@ install(TARGETS colon_dependency
|
||||
COMPONENT "Colon:Name"
|
||||
)
|
||||
|
||||
# Component names that differ only in case each get a working preparation
|
||||
# target, even where the build tool's target names are case-insensitive.
|
||||
foreach(case IN ITEMS "Mixed;upper" "mixed;lower" "All;all")
|
||||
list(GET case 0 component)
|
||||
list(GET case 1 dependency)
|
||||
add_library(${dependency}_case_dependency STATIC EXCLUDE_FROM_ALL lib.c)
|
||||
install(TARGETS ${dependency}_case_dependency
|
||||
ARCHIVE DESTINATION lib
|
||||
COMPONENT ${component}
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# Components whose names are not representable get no preparation target,
|
||||
# which is diagnosed when they have build dependencies.
|
||||
add_library(unsafe_dependency STATIC EXCLUDE_FROM_ALL lib.c)
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
^CMake Warning \(author\) at GeneratedByDependency\.cmake:[0-9]+ \(add_library\):
|
||||
Target "generated_headers" installs file
|
||||
|
||||
[^
|
||||
]*/GeneratedByDependency-build/generated\.h
|
||||
|
||||
which is generated but is not the unique output of a build target, so
|
||||
"install_prep/" targets cannot build it with this generator\. They build
|
||||
target "generated_headers" instead, which must depend on the target that
|
||||
produces the file \(for example via add_dependencies\)\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
This warning is for project developers\. Use -Wno-author to suppress it\.$
|
||||
@@ -0,0 +1,11 @@
|
||||
^CMake Warning \(author\) at GeneratedFilesByproduct\.cmake:[0-9]+ \(install\):
|
||||
An install rule installs or depends on file
|
||||
|
||||
[^
|
||||
]*/GeneratedFilesByproduct-build/byproduct\.txt
|
||||
|
||||
which is generated but is not the unique output of a build target, so
|
||||
"install_prep/" targets cannot build it with this generator\..*
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
This warning is for project developers\. Use -Wno-author to suppress it\.$
|
||||
@@ -65,6 +65,8 @@ macro(configure_install_prep test config)
|
||||
set(stderr_variant "")
|
||||
if(RunCMake_GENERATOR MATCHES "Make")
|
||||
set(stderr_variant make)
|
||||
elseif(RunCMake_GENERATOR STREQUAL "FASTBuild")
|
||||
set(stderr_variant fastbuild)
|
||||
endif()
|
||||
if(stderr_variant AND
|
||||
EXISTS "${RunCMake_SOURCE_DIR}/${test}-stderr-${stderr_variant}.txt")
|
||||
@@ -152,6 +154,13 @@ block()
|
||||
run_missing_install_prep(ComponentNames-empty-segment
|
||||
install_prep/Empty//Segment)
|
||||
run_missing_install_prep(ComponentNames-dot install_prep/./Dot)
|
||||
foreach(case IN ITEMS "Mixed;upper" "mixed;lower" "All;all")
|
||||
list(GET case 0 component)
|
||||
list(GET case 1 dependency)
|
||||
set(RunCMake-check-file ComponentNames-case-build-check.cmake)
|
||||
run_cmake_command(ComponentNames-case-${dependency}-build ${CMAKE_COMMAND}
|
||||
--build . --config Debug --target install_prep/${component})
|
||||
endforeach()
|
||||
endblock()
|
||||
|
||||
function(run_configured_install_prep test config)
|
||||
|
||||
Reference in new issue
Block a user