Files
CMake/Source/cmInstallScriptHandler.h
Daksh Mamodiya ae5f506906 Install: Exit non-zero when an install script fails
`cmake --install` did not propagate per-script failures into its
process exit code.

In parallel mode, cmInstallScriptHandler::Install spawned each install
script as a child process but never inspected the child exit status or
termination signal, and always returned 0.  It now reads each child's
status after the event loop, prints the failing script's exit code or
signal, and returns non-zero if any script failed.  A failed parallel
install also no longer writes the combined install_manifest.txt, so a
partial manifest is not mistaken for a complete install.

In serial mode, GetScripts() returns the top-level cmake_install.cmake
once per component and per configuration, so multiple scripts run only
when installing several components or configurations at once.  The loop
overwrote its result on every iteration, so an earlier script that
failed via cmake_language(EXIT) was masked by a later one that
succeeded.  The loop now stops at the first failure.  This is a no-op
for a single component and configuration; it changes only installs of
multiple components or configurations, which now stop at the first
failed script and report it instead of attempting the rest.

Fixes: #27906
2026-06-30 18:06:50 +02:00

60 lines
1.5 KiB
C++

/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#pragma once
#include <cstddef>
#include <functional>
#include <memory>
#include <string>
#include <vector>
#include "cmUVProcessChain.h"
#include "cmUVStream.h"
namespace cm {
class uv_loop_ptr;
}
class cmInstrumentation;
class cmInstallScriptHandler
{
public:
cmInstallScriptHandler() = default;
cmInstallScriptHandler(std::string, std::vector<std::string>, std::string,
std::vector<std::string>&);
bool IsParallel();
int Install(unsigned int j, cmInstrumentation& instrumentation);
struct InstallScript
{
std::string path;
std::string config;
std::vector<std::string> command;
};
std::vector<InstallScript> GetScripts() const;
class InstallScriptRunner
{
public:
InstallScriptRunner(InstallScript const&);
bool start(cm::uv_loop_ptr&, std::function<void()>);
void printResult(std::size_t n, std::size_t total);
bool Failed() const;
void printFailure();
private:
std::vector<std::string> Command;
std::vector<std::string> Output;
std::string Name;
std::unique_ptr<cmUVProcessChain> Chain;
std::unique_ptr<cmUVStreamReadHandle> StreamHandler;
};
private:
std::vector<InstallScript> Scripts;
std::vector<std::string> Configs;
std::vector<std::string> Directories;
std::vector<std::string> Components;
std::string BinaryDir;
bool Parallel;
};