Diagnostic: Add warn or error on absolute install paths

Add `-Winstall-absolute-destination` diagnostic to warn or
error when an install command has an absolute destination.

This allow projects to enforce the best practice of not allowing
absolute install DESTINATIONS.
This commit is contained in:
Robert Maynard
2026-03-25 09:56:59 -04:00
committed by Brad King
parent fd76089631
commit 39a56136a3
54 changed files with 255 additions and 32 deletions

View File

@@ -60,6 +60,11 @@ signatures that specify them. The common options are:
``<dir>`` should be a relative path. An absolute path is allowed,
but not recommended.
.. versionadded:: 4.4
The :ref:`CMD_INSTALL_ABSOLUTE_DESTINATION <CMD_INSTALL_ABSOLUTE_DESTINATION>`
diagnostic can be enabled to warn or error out when an absolute destination
is provided.
When a relative path is given, it is interpreted relative to the value
of the :variable:`CMAKE_INSTALL_PREFIX` variable.
The prefix can be relocated at install time using the ``DESTDIR``

View File

@@ -88,3 +88,15 @@ Warn about variables that are declared on the command line, but not used.
Although the action of this warning category can be queried as usual, changes
made using the :command:`cmake_diagnostic` command have no effect.
.. _CMD_INSTALL_ABSOLUTE_DESTINATION:
``CMD_INSTALL_ABSOLUTE_DESTINATION`` (``-Winstall-absolute-destination``)
-------------------------------------------------------------------------
:Default: Ignore
Warn when an :command:`install` command specifies an absolute
``DESTINATION`` path. Absolute destinations are typically undesirable
because they prevent the installation prefix from being overridden at
install time.

View File

@@ -474,6 +474,9 @@ they were added and a summary of the new features and changes is given below.
* The ``uninitialized`` and ``unusedCli`` fields were added to
:preset:`configurePresets.errors`.
* The ``installAbsoluteDestination`` field was added to
:preset:`configurePresets.warnings` and :preset:`configurePresets.errors`.
* Changes to `Macro Expansion`_
* The `${fileDir} <CMakePresets fileDir_>`_ macro now always expands to

View File

@@ -32,6 +32,15 @@
This may not be set to ``true``
if ``warnings.dev`` is set to ``false``.
.. _`CMakePresets.configurePresets.errors.installAbsoluteDestination`:
``installAbsoluteDestination``
.. presets-versionadded:: 12
An optional boolean. Equivalent to passing :cmake-option:`-Werror=install-absolute-destination` or
:cmake-option:`-Wno-error=install-absolute-destination` on the command line.
This may not be set to ``true`` if ``warnings.installAbsoluteDestination`` is set to ``false``.
.. _`CMakePresets.configurePresets.errors.uninitialized`:
``uninitialized``

View File

@@ -1286,6 +1286,9 @@
"deprecated": {
"$ref": "#/definitions/configurePresets.warnings.deprecated@v1.."
},
"installAbsoluteDestination": {
"$ref": "#/definitions/configurePresets.warnings.installAbsoluteDestination@v12"
},
"uninitialized": {
"$ref": "#/definitions/configurePresets.warnings.uninitialized@v1.."
},
@@ -1312,6 +1315,10 @@
"type": "boolean",
"description": "An optional boolean. Equivalent to passing -Wdev or -Wno-dev on the command line. This may not be set to false if errors.dev is set to true."
},
"configurePresets.warnings.installAbsoluteDestination@v12": {
"type": "boolean",
"description": "An optional boolean. Equivalent to passing -Winstall-absolute-destination or -Wno-install-absolute-destination on the command line. This may not be set to false if errors.installAbsoluteDestination is set to true."
},
"configurePresets.warnings.uninitialized@v1..": {
"type": "boolean",
"description": "An optional boolean. Equivalent to passing -Wuninitialized or -Wno-uninitialized on the command line. This may not be set to false if errors.uninitialized is set to true."
@@ -1364,6 +1371,9 @@
"deprecated": {
"$ref": "#/definitions/configurePresets.errors.deprecated@v1.."
},
"installAbsoluteDestination": {
"$ref": "#/definitions/configurePresets.errors.installAbsoluteDestination@v12"
},
"uninitialized": {
"$ref": "#/definitions/configurePresets.errors.uninitialized@v12"
},
@@ -1387,6 +1397,10 @@
"type": "boolean",
"description": "An optional boolean. Equivalent to passing -Werror=dev or -Wno-error=dev on the command line. This may not be set to true if warnings.dev is set to false."
},
"configurePresets.errors.installAbsoluteDestination@v12": {
"type": "boolean",
"description": "An optional boolean. Equivalent to passing -Werror=install-absolute-destination or -Wno-error=install-absolute-destination on the command line. This may not be set to true if warnings.installAbsoluteDestination is set to false."
},
"configurePresets.errors.uninitialized@v12": {
"type": "boolean",
"description": "An optional boolean. Equivalent to passing -Werror=uninitialized or -Wno-error=uninitialized on the command line. This may not be set to true if warnings.uninitialized is set to false."

View File

@@ -32,6 +32,15 @@
This may not be set to ``false``
if ``errors.dev`` is set to ``true``.
.. _`CMakePresets.configurePresets.warnings.installAbsoluteDestination`:
``installAbsoluteDestination``
.. presets-versionadded:: 12
An optional boolean. Equivalent to passing :option:`-Winstall-absolute-destination <cmake -W>` or
:option:`-Wno-install-absolute-destination <cmake -Wno->` on the command line.
This may not be set to ``false`` if ``errors.installAbsoluteDestination`` is set to ``true``.
.. _`CMakePresets.configurePresets.warnings.uninitialized`:
``uninitialized``

View File

@@ -0,0 +1,10 @@
install-absolute-dest-configure-time
-------------------------------------
* CMake gained the ability to diagnose :command:`install` commands that
specify an absolute ``DESTINATION`` path via the
:ref:`CMD_INSTALL_ABSOLUTE_DESTINATION <CMD_INSTALL_ABSOLUTE_DESTINATION>`
diagnostic category. This diagnostic may be controlled with the
:option:`-Winstall-absolute-destination <cmake -W>` command-line option, the
``installAbsoluteDestination`` field in a :manual:`cmake-presets(7)`
``warnings`` object, or the :command:`cmake_diagnostic` command.

View File

@@ -8,3 +8,11 @@ The fatal error is emitted before the installation of the offending
file takes place. This variable is used by CMake-generated
``cmake_install.cmake`` scripts. If one sets this variable to ``ON`` while
running the script, it may get fatal error messages from the script.
.. versionadded:: 4.4
The :ref:`CMD_INSTALL_ABSOLUTE_DESTINATION <CMD_INSTALL_ABSOLUTE_DESTINATION>`
diagnostic can be used to to generate errors for absolute install destinations
at generate time.
See also :variable:`CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION`.

View File

@@ -7,3 +7,11 @@ Ask ``cmake_install.cmake`` script to warn each time a file with absolute
This variable is used by CMake-generated ``cmake_install.cmake`` scripts.
If one sets this variable to ``ON`` while running the script, it may get
warning messages from the script.
.. versionadded:: 4.4
The :ref:`CMD_INSTALL_ABSOLUTE_DESTINATION <CMD_INSTALL_ABSOLUTE_DESTINATION>`
diagnostic can be used to to generate warnings for absolute install destinations
at generate time.
See also :variable:`CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION`.

View File

@@ -28,6 +28,7 @@
#define CM_FOR_EACH_DIAGNOSTIC_TABLE(ACTION, SELECT) \
SELECT(ACTION, Warn, CMD_NONE, CMD_AUTHOR, 12) \
SELECT(ACTION, Warn, CMD_AUTHOR, CMD_DEPRECATED, 1) \
SELECT(ACTION, Ignore, CMD_AUTHOR, CMD_INSTALL_ABSOLUTE_DESTINATION, 12) \
SELECT(ACTION, Ignore, CMD_NONE, CMD_UNINITIALIZED, 1) \
SELECT(ACTION, Warn, CMD_NONE, CMD_UNUSED_CLI, 1)

View File

@@ -285,19 +285,21 @@ std::string cmExportInstallCMakeConfigGenerator::GetFileSetDirectories(
gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
for (auto const& config : configs) {
auto result = te->FileSetGenerators.at(fileSet->GetName())
->GetDestination(gte, config);
cmInstallFileSetGenerator::DestinationContext result =
te->FileSetGenerators.at(fileSet->GetName())
->GetDestination(gte, config);
auto dest = cmOutputConverter::EscapeForCMake(
result.unescapedDestination, cmOutputConverter::WrapQuotes::NoWrap);
if (!cmSystemTools::FileIsFullPath(result.unescapedDestination)) {
std::string dest = cmOutputConverter::EscapeForCMake(
result.UnescapedDestination, cmOutputConverter::WrapQuotes::NoWrap);
if (!cmSystemTools::FileIsFullPath(result.UnescapedDestination)) {
dest = cmStrCat("${_IMPORT_PREFIX}/", dest);
}
auto const& type = fileSet->GetType();
// C++ modules do not support interface file sets which are dependent upon
// the configuration.
if (result.isConfigDependent && type == cm::FileSetMetadata::CXX_MODULES) {
if (result.HadContextSensitiveCondition &&
type == cm::FileSetMetadata::CXX_MODULES) {
auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile();
std::ostringstream e;
e << "The \"" << gte->GetName() << "\" target's interface file set \""
@@ -308,7 +310,7 @@ std::string cmExportInstallCMakeConfigGenerator::GetFileSetDirectories(
return std::string{};
}
if (result.isConfigDependent && configs.size() != 1) {
if (result.HadContextSensitiveCondition && configs.size() != 1) {
resultVector.push_back(
cmStrCat("\"$<$<CONFIG:", config, ">:", dest, ">\""));
} else {

View File

@@ -224,14 +224,14 @@ cmExportInstallPackageInfoGenerator::GetFileSetDirectory(
cmGeneratorTarget* gte, cmTargetExport const* te,
cmGeneratorFileSet const* fileSet, cm::optional<std::string> const& config)
{
auto config_value = config.value_or("");
auto result = te->FileSetGenerators.at(fileSet->GetName())
->GetDestination(gte, config_value);
cmInstallFileSetGenerator::DestinationContext result =
te->FileSetGenerators.at(fileSet->GetName())
->GetDestination(gte, config.value_or(""));
if (config && !result.isConfigDependent) {
if (config && !result.HadContextSensitiveCondition) {
return {};
}
if (!config && result.isConfigDependent) {
if (!config && result.HadContextSensitiveCondition) {
this->RequiresConfigFiles = true;
return {};
}
@@ -251,9 +251,9 @@ cmExportInstallPackageInfoGenerator::GetFileSetDirectory(
}
cm::optional<std::string> dest = cmOutputConverter::EscapeForCMake(
result.unescapedDestination, cmOutputConverter::WrapQuotes::NoWrap);
result.UnescapedDestination, cmOutputConverter::WrapQuotes::NoWrap);
if (!cmSystemTools::FileIsFullPath(result.unescapedDestination)) {
if (!cmSystemTools::FileIsFullPath(result.UnescapedDestination)) {
dest = cmStrCat("@prefix@/"_s, *dest);
}

View File

@@ -216,11 +216,11 @@ cm::optional<std::string> cmExportInstallSbomGenerator::GetFileSetDirectory(
cmGeneratorTarget* gte, cmTargetExport const* te,
cmGeneratorFileSet const* fileSet, cm::optional<std::string> const& config)
{
auto config_value = config.value_or("");
auto result = te->FileSetGenerators.at(fileSet->GetName())
->GetDestination(gte, config_value);
cmInstallFileSetGenerator::DestinationContext result =
te->FileSetGenerators.at(fileSet->GetName())
->GetDestination(gte, config.value_or(""));
if (config && !result.isConfigDependent) {
if (config && !result.HadContextSensitiveCondition) {
return {};
}
@@ -237,9 +237,9 @@ cm::optional<std::string> cmExportInstallSbomGenerator::GetFileSetDirectory(
}
cm::optional<std::string> dest = cmOutputConverter::EscapeForCMake(
result.unescapedDestination, cmOutputConverter::WrapQuotes::NoWrap);
result.UnescapedDestination, cmOutputConverter::WrapQuotes::NoWrap);
if (!cmSystemTools::FileIsFullPath(result.unescapedDestination)) {
if (!cmSystemTools::FileIsFullPath(result.UnescapedDestination)) {
dest = cmStrCat("@prefix@/"_s, *dest);
}

View File

@@ -1912,6 +1912,15 @@ bool HandleDirectoryMode(std::vector<std::string> const& args,
cmInstallGenerator::MessageLevel message =
cmInstallGenerator::SelectMessageLevel(helper.Makefile, message_never);
// Check for an absolute destination.
if (cmGeneratorExpression::Find(*destination) == std::string::npos &&
cmSystemTools::FileIsFullPath(*destination)) {
helper.Makefile->IssueDiagnostic(
cmDiagnostics::CMD_INSTALL_ABSOLUTE_DESTINATION,
cmStrCat("INSTALL command given absolute DESTINATION path (",
*destination, ").\n"));
}
// Create the directory install generator.
helper.Makefile->AddInstallGenerator(
cm::make_unique<cmInstallDirectoryGenerator>(

View File

@@ -22,7 +22,7 @@ public:
this->GenericArguments = args;
}
// Compute destination path.and check permissions
// Compute destination path and check permissions.
bool Finalize();
std::string const& GetDestination() const;

View File

@@ -118,6 +118,9 @@ void cmInstallDirectoryGenerator::AddDirectoryInstallRule(
std::string cmInstallDirectoryGenerator::GetDestination(
std::string const& config) const
{
return cmGeneratorExpression::Evaluate(this->Destination,
this->LocalGenerator, config);
std::string dest = cmGeneratorExpression::Evaluate(
this->Destination, this->LocalGenerator, config);
cmInstallGenerator::CheckAbsoluteDestination(dest, this->LocalGenerator,
this->Backtrace);
return dest;
}

View File

@@ -4,6 +4,7 @@
#include <algorithm>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
@@ -94,13 +95,15 @@ bool cmInstallFileSetGenerator::Compute(cmLocalGenerator* lg)
std::string cmInstallFileSetGenerator::GetDestination() const
{
cmInstallGenerator::CheckAbsoluteDestination(
this->Destination, this->LocalGenerator, this->Backtrace);
return this->Destination;
}
std::string cmInstallFileSetGenerator::GetDestination(
std::string const& config) const
{
return this->GetDestination(this->Target, config).unescapedDestination;
return this->GetDestination(this->Target, config).UnescapedDestination;
}
cmInstallFileSetGenerator::DestinationContext
@@ -108,9 +111,13 @@ cmInstallFileSetGenerator::GetDestination(cmGeneratorTarget* gte,
std::string const& config) const
{
cmGeneratorExpression ge(*gte->Makefile->GetCMakeInstance());
auto cge = ge.Parse(this->Destination);
std::unique_ptr<cmCompiledGeneratorExpression> cge =
ge.Parse(this->Destination);
std::string const dest = cge->Evaluate(gte->LocalGenerator, config, gte);
cmInstallGenerator::CheckAbsoluteDestination(dest, gte->LocalGenerator,
this->Backtrace);
return { dest, cge->GetHadContextSensitiveCondition() };
}

View File

@@ -31,8 +31,8 @@ public:
struct DestinationContext
{
std::string unescapedDestination;
bool isConfigDependent;
std::string UnescapedDestination;
bool HadContextSensitiveCondition;
};
std::string GetDestination(std::string const& config) const;
DestinationContext GetDestination(cmGeneratorTarget* gt,

View File

@@ -54,8 +54,11 @@ bool cmInstallFilesGenerator::Compute(cmLocalGenerator* lg)
std::string cmInstallFilesGenerator::GetDestination(
std::string const& config) const
{
return cmGeneratorExpression::Evaluate(this->Destination,
this->LocalGenerator, config);
std::string dest = cmGeneratorExpression::Evaluate(
this->Destination, this->LocalGenerator, config);
cmInstallGenerator::CheckAbsoluteDestination(dest, this->LocalGenerator,
this->Backtrace);
return dest;
}
std::string cmInstallFilesGenerator::GetRename(std::string const& config) const

View File

@@ -7,6 +7,9 @@
#include <cm/string_view>
#include "cmDiagnostics.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
@@ -229,6 +232,19 @@ std::string cmInstallGenerator::ConvertToAbsoluteDestination(
return result;
}
void cmInstallGenerator::CheckAbsoluteDestination(
std::string const& dest, cmLocalGenerator* lg, cmListFileBacktrace const& bt)
{
if (!cmSystemTools::FileIsFullPath(dest)) {
return;
}
lg->IssueDiagnostic(
cmDiagnostics::CMD_INSTALL_ABSOLUTE_DESTINATION,
cmStrCat("INSTALL command given absolute DESTINATION path (", dest,
").\n"),
bt);
}
cmInstallGenerator::MessageLevel cmInstallGenerator::SelectMessageLevel(
cmMakefile* mf, bool never)
{

View File

@@ -56,6 +56,9 @@ public:
/** Get the install destination as it should appear in the
installation script. */
static std::string ConvertToAbsoluteDestination(std::string const& dest);
static void CheckAbsoluteDestination(std::string const& dest,
cmLocalGenerator* lg,
cmListFileBacktrace const& bt);
/** Test if this generator installs something for a given configuration. */
bool InstallsForConfig(std::string const& config);

View File

@@ -479,8 +479,11 @@ void cmInstallTargetGenerator::GetInstallObjectNames(
std::string cmInstallTargetGenerator::GetDestination(
std::string const& config) const
{
return cmGeneratorExpression::Evaluate(
this->Destination, this->Target->GetLocalGenerator(), config);
cmLocalGenerator* lg = this->Target->GetLocalGenerator();
std::string dest =
cmGeneratorExpression::Evaluate(this->Destination, lg, config);
cmInstallGenerator::CheckAbsoluteDestination(dest, lg, this->Backtrace);
return dest;
}
std::string cmInstallTargetGenerator::GetInstallFilename(

View File

@@ -0,0 +1,5 @@
CMake Warning \(unused-cli\):
Manually-specified variables were not used by the project:
RunCMake_GENERATOR
UNUSED_VARIABLE$

View File

@@ -0,0 +1,6 @@
cmake_diagnostic(GET CMD_INSTALL_ABSOLUTE_DESTINATION action)
if(NOT "${action}" STREQUAL SEND_ERROR)
message(SEND_ERROR
"wrong action for diagnostic CMD_INSTALL_ABSOLUTE_DESTINATION"
" (expected 'SEND_ERROR', actual '${action}')")
endif()

View File

@@ -361,7 +361,9 @@ run_cmake_presets(ErrorDeprecated)
set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/Warnings12.json.in")
run_cmake_presets(NoWarningFlags)
run_cmake_presets(WarningFlags)
run_cmake_presets(WarningAbsInstallPath)
run_cmake_presets(DisableWarningFlags)
run_cmake_presets(ErrorAbsInstallPath)
run_cmake_presets(ErrorDev)
run_cmake_presets(ErrorUninitialized)
run_cmake_presets(ErrorUnusedCli)

View File

@@ -0,0 +1,5 @@
CMake Warning \(unused-cli\):
Manually-specified variables were not used by the project:
RunCMake_GENERATOR
UNUSED_VARIABLE$

View File

@@ -0,0 +1,6 @@
cmake_diagnostic(GET CMD_INSTALL_ABSOLUTE_DESTINATION action)
if(NOT "${action}" STREQUAL WARN)
message(SEND_ERROR
"wrong action for diagnostic CMD_INSTALL_ABSOLUTE_DESTINATION"
" (expected 'WARN', actual '${action}')")
endif()

View File

@@ -29,6 +29,20 @@
"unusedCli": false
}
},
{
"name": "WarningAbsInstallPath",
"inherits": "NoWarningFlags",
"warnings": {
"installAbsoluteDestination": true
}
},
{
"name": "ErrorAbsInstallPath",
"inherits": "NoWarningFlags",
"errors": {
"installAbsoluteDestination": true
}
},
{
"name": "ErrorDev",
"inherits": "NoWarningFlags",

View File

@@ -1,4 +1,5 @@
include(Assertions.cmake)
expect(CMD_AUTHOR IGNORE)
expect(CMD_INSTALL_ABSOLUTE_DESTINATION IGNORE)
expect(CMD_DEPRECATED SEND_ERROR)

View File

@@ -1,3 +1,5 @@
include(Assertions.cmake)
expect_cached(CMD_UNINITIALIZED IGNORE)
expect_cached(CMD_INSTALL_ABSOLUTE_DESTINATION WARN)

View File

@@ -12,4 +12,4 @@ run_cmake_with_options(CommandLine1 -Werror=author)
run_cmake_with_options(CommandLine1 -Werror=author -Wdeprecated)
run_cmake_with_options(CommandLine1 -Wno-deprecated -Werror=author)
run_cmake_with_options(CommandLine2 -Werror=author -Wno-deprecated)
run_cmake_with_options(CommandLine3 -Wno-error=uninitialized)
run_cmake_with_options(CommandLine3 -Wno-error=uninitialized -Winstall-absolute-destination)

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,2 @@
CMake Error \(install-absolute-destination\) at DIRECTORY-AbsoluteDest-error\.cmake:[0-9]+ \(install\):
INSTALL command given absolute DESTINATION path \(/absolute/path\)\.

View File

@@ -0,0 +1 @@
install(DIRECTORY DESTINATION /absolute/path)

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,2 @@
CMake Error \(install-absolute-destination\) at FILES-AbsoluteDest-error\.cmake:[0-9]+ \(install\):
INSTALL command given absolute DESTINATION path \(/absolute/path\)\.

View File

@@ -0,0 +1 @@
install(FILES empty.c DESTINATION /absolute/path)

View File

@@ -0,0 +1,2 @@
CMake Warning \(install-absolute-destination\) at FILES-AbsoluteDest-warn\.cmake:[0-9]+ \(install\):
INSTALL command given absolute DESTINATION path \(/absolute/path\)\.

View File

@@ -0,0 +1 @@
install(FILES empty.c DESTINATION /absolute/path)

View File

@@ -82,6 +82,14 @@ run_cmake(DIRECTORY-DESTINATION-bad)
run_cmake(FILES-DESTINATION-bad)
run_cmake(FILES-RENAME-bad)
run_cmake(TARGETS-DESTINATION-bad)
run_cmake_with_options(DIRECTORY-AbsoluteDest-error -Werror=install-absolute-destination)
run_cmake_with_options(FILES-AbsoluteDest-error -Werror=install-absolute-destination)
run_cmake_with_options(FILES-AbsoluteDest-warn -Winstall-absolute-destination)
run_cmake_with_options(TARGETS-AbsoluteDest-error -Werror=install-absolute-destination)
run_cmake_with_options(TARGETS-AbsoluteDest-warn -Winstall-absolute-destination)
run_cmake_with_options(TARGETS-AbsoluteDest-archive-error -Werror=install-absolute-destination)
run_cmake_with_options(TARGETS-AbsoluteDest-library-error -Werror=install-absolute-destination)
run_cmake_with_options(TARGETS-AbsoluteDest-runtime-error -Werror=install-absolute-destination)
run_cmake(EXPORT-Component)
run_cmake(EXPORT-FindDependencyExportGate)
run_cmake(EXPORT-OldIFace)

View File

@@ -0,0 +1,2 @@
CMake Error \(install-absolute-destination\) at TARGETS-AbsoluteDest-archive-error\.cmake:[0-9]+ \(install\):
INSTALL command given absolute DESTINATION path \(/absolute/archive\)\.

View File

@@ -0,0 +1,3 @@
enable_language(C)
add_library(mylib STATIC empty.c)
install(TARGETS mylib ARCHIVE DESTINATION /absolute/archive)

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,2 @@
CMake Error \(install-absolute-destination\) at TARGETS-AbsoluteDest-error\.cmake:[0-9]+ \(install\):
INSTALL command given absolute DESTINATION path \(/absolute/path\)\.

View File

@@ -0,0 +1,12 @@
enable_language(C)
add_library(mylib STATIC empty.c)
# FIXME(#27770): This diagnostic is issued at generate time. Currently, the
# install generator doesn't capture the immediate diagnostic state, only the
# top-most state of the current subdirectory, which we cannot affect (because
# this test was include()d. When we fix that, we should test by changing the
# diagnostic action here rather than by -W... in the test CLI arguments.
# cmake_diagnostic(SET CMD_INSTALL_ABSOLUTE_DESTINATION SEND_ERROR)
cmake_diagnostic(PROMOTE CMD_INSTALL_ABSOLUTE_DESTINATION WARN)
install(TARGETS mylib DESTINATION /absolute/path)

View File

@@ -0,0 +1,2 @@
CMake Error \(install-absolute-destination\) at TARGETS-AbsoluteDest-library-error\.cmake:[0-9]+ \(install\):
INSTALL command given absolute DESTINATION path \(/absolute/lib\)\.

View File

@@ -0,0 +1,3 @@
enable_language(C)
add_library(mylib MODULE empty.c)
install(TARGETS mylib LIBRARY DESTINATION /absolute/lib)

View File

@@ -0,0 +1,2 @@
CMake Error \(install-absolute-destination\) at TARGETS-AbsoluteDest-runtime-error\.cmake:[0-9]+ \(install\):
INSTALL command given absolute DESTINATION path \(/absolute/bin\)\.

View File

@@ -0,0 +1,3 @@
enable_language(C)
add_executable(myexe empty.c)
install(TARGETS myexe RUNTIME DESTINATION /absolute/bin)

View File

@@ -0,0 +1,2 @@
CMake Warning \(install-absolute-destination\) at TARGETS-AbsoluteDest-warn\.cmake:[0-9]+ \(install\):
INSTALL command given absolute DESTINATION path \(/absolute/path\)\.

View File

@@ -0,0 +1,3 @@
enable_language(C)
add_library(mylib STATIC empty.c)
install(TARGETS mylib DESTINATION /absolute/path)