From fd76089631a1940e168316a4262a8f19466030b5 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Wed, 25 Mar 2026 15:16:25 -0400 Subject: [PATCH 1/2] cmInstallFileSetGenerator: Only support per config Destination. --- .../cmExportInstallCMakeConfigGenerator.cxx | 17 +++++++--------- .../cmExportInstallPackageInfoGenerator.cxx | 18 +++++++---------- Source/cmExportInstallSbomGenerator.cxx | 16 ++++++--------- Source/cmInstallFileSetGenerator.cxx | 20 +++++++++++++++++-- Source/cmInstallFileSetGenerator.h | 14 +++++++++++-- 5 files changed, 50 insertions(+), 35 deletions(-) diff --git a/Source/cmExportInstallCMakeConfigGenerator.cxx b/Source/cmExportInstallCMakeConfigGenerator.cxx index eae42b6ee5..2e2f2c66b5 100644 --- a/Source/cmExportInstallCMakeConfigGenerator.cxx +++ b/Source/cmExportInstallCMakeConfigGenerator.cxx @@ -284,23 +284,20 @@ std::string cmExportInstallCMakeConfigGenerator::GetFileSetDirectories( auto configs = gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); - cmGeneratorExpression ge(*gte->Makefile->GetCMakeInstance()); - auto cge = - ge.Parse(te->FileSetGenerators.at(fileSet->GetName())->GetDestination()); - for (auto const& config : configs) { - auto unescapedDest = cge->Evaluate(gte->LocalGenerator, config, gte); + auto result = te->FileSetGenerators.at(fileSet->GetName()) + ->GetDestination(gte, config); + auto dest = cmOutputConverter::EscapeForCMake( - unescapedDest, cmOutputConverter::WrapQuotes::NoWrap); - if (!cmSystemTools::FileIsFullPath(unescapedDest)) { + 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 (cge->GetHadContextSensitiveCondition() && - type == cm::FileSetMetadata::CXX_MODULES) { + if (result.isConfigDependent && type == cm::FileSetMetadata::CXX_MODULES) { auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile(); std::ostringstream e; e << "The \"" << gte->GetName() << "\" target's interface file set \"" @@ -311,7 +308,7 @@ std::string cmExportInstallCMakeConfigGenerator::GetFileSetDirectories( return std::string{}; } - if (cge->GetHadContextSensitiveCondition() && configs.size() != 1) { + if (result.isConfigDependent && configs.size() != 1) { resultVector.push_back( cmStrCat("\"$<$:", dest, ">\"")); } else { diff --git a/Source/cmExportInstallPackageInfoGenerator.cxx b/Source/cmExportInstallPackageInfoGenerator.cxx index 78eb146299..dd824ab61e 100644 --- a/Source/cmExportInstallPackageInfoGenerator.cxx +++ b/Source/cmExportInstallPackageInfoGenerator.cxx @@ -224,18 +224,14 @@ cmExportInstallPackageInfoGenerator::GetFileSetDirectory( cmGeneratorTarget* gte, cmTargetExport const* te, cmGeneratorFileSet const* fileSet, cm::optional const& config) { - cmGeneratorExpression ge(*gte->Makefile->GetCMakeInstance()); - auto cge = - ge.Parse(te->FileSetGenerators.at(fileSet->GetName())->GetDestination()); + auto config_value = config.value_or(""); + auto result = te->FileSetGenerators.at(fileSet->GetName()) + ->GetDestination(gte, config_value); - std::string const unescapedDest = - cge->Evaluate(gte->LocalGenerator, config.value_or(""), gte); - bool const isConfigDependent = cge->GetHadContextSensitiveCondition(); - - if (config && !isConfigDependent) { + if (config && !result.isConfigDependent) { return {}; } - if (!config && isConfigDependent) { + if (!config && result.isConfigDependent) { this->RequiresConfigFiles = true; return {}; } @@ -255,9 +251,9 @@ cmExportInstallPackageInfoGenerator::GetFileSetDirectory( } cm::optional dest = cmOutputConverter::EscapeForCMake( - unescapedDest, cmOutputConverter::WrapQuotes::NoWrap); + result.unescapedDestination, cmOutputConverter::WrapQuotes::NoWrap); - if (!cmSystemTools::FileIsFullPath(unescapedDest)) { + if (!cmSystemTools::FileIsFullPath(result.unescapedDestination)) { dest = cmStrCat("@prefix@/"_s, *dest); } diff --git a/Source/cmExportInstallSbomGenerator.cxx b/Source/cmExportInstallSbomGenerator.cxx index d944383902..3f5f172fd7 100644 --- a/Source/cmExportInstallSbomGenerator.cxx +++ b/Source/cmExportInstallSbomGenerator.cxx @@ -216,15 +216,11 @@ cm::optional cmExportInstallSbomGenerator::GetFileSetDirectory( cmGeneratorTarget* gte, cmTargetExport const* te, cmGeneratorFileSet const* fileSet, cm::optional const& config) { - cmGeneratorExpression ge(*gte->Makefile->GetCMakeInstance()); - auto cge = - ge.Parse(te->FileSetGenerators.at(fileSet->GetName())->GetDestination()); + auto config_value = config.value_or(""); + auto result = te->FileSetGenerators.at(fileSet->GetName()) + ->GetDestination(gte, config_value); - std::string const unescapedDest = - cge->Evaluate(gte->LocalGenerator, config.value_or(""), gte); - bool const isConfigDependent = cge->GetHadContextSensitiveCondition(); - - if (config && !isConfigDependent) { + if (config && !result.isConfigDependent) { return {}; } @@ -241,9 +237,9 @@ cm::optional cmExportInstallSbomGenerator::GetFileSetDirectory( } cm::optional dest = cmOutputConverter::EscapeForCMake( - unescapedDest, cmOutputConverter::WrapQuotes::NoWrap); + result.unescapedDestination, cmOutputConverter::WrapQuotes::NoWrap); - if (!cmSystemTools::FileIsFullPath(unescapedDest)) { + if (!cmSystemTools::FileIsFullPath(result.unescapedDestination)) { dest = cmStrCat("@prefix@/"_s, *dest); } diff --git a/Source/cmInstallFileSetGenerator.cxx b/Source/cmInstallFileSetGenerator.cxx index 85b8275ca3..cbe55136e5 100644 --- a/Source/cmInstallFileSetGenerator.cxx +++ b/Source/cmInstallFileSetGenerator.cxx @@ -21,6 +21,7 @@ #include "cmList.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" +#include "cmMakefile.h" #include "cmMessageType.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" @@ -91,11 +92,26 @@ bool cmInstallFileSetGenerator::Compute(cmLocalGenerator* lg) return true; } +std::string cmInstallFileSetGenerator::GetDestination() const +{ + return this->Destination; +} + std::string cmInstallFileSetGenerator::GetDestination( std::string const& config) const { - return cmGeneratorExpression::Evaluate(this->Destination, - this->LocalGenerator, config); + return this->GetDestination(this->Target, config).unescapedDestination; +} + +cmInstallFileSetGenerator::DestinationContext +cmInstallFileSetGenerator::GetDestination(cmGeneratorTarget* gte, + std::string const& config) const +{ + cmGeneratorExpression ge(*gte->Makefile->GetCMakeInstance()); + auto cge = ge.Parse(this->Destination); + + std::string const dest = cge->Evaluate(gte->LocalGenerator, config, gte); + return { dest, cge->GetHadContextSensitiveCondition() }; } void cmInstallFileSetGenerator::GenerateScriptForConfig( diff --git a/Source/cmInstallFileSetGenerator.h b/Source/cmInstallFileSetGenerator.h index ff562011f8..82fe47074c 100644 --- a/Source/cmInstallFileSetGenerator.h +++ b/Source/cmInstallFileSetGenerator.h @@ -9,8 +9,9 @@ #include "cmInstallGenerator.h" -class cmGeneratorTarget; +class cmExportInstallCMakeConfigGenerator; class cmGeneratorFileSet; +class cmGeneratorTarget; class cmListFileBacktrace; class cmLocalGenerator; @@ -28,14 +29,23 @@ public: bool Compute(cmLocalGenerator* lg) override; + struct DestinationContext + { + std::string unescapedDestination; + bool isConfigDependent; + }; std::string GetDestination(std::string const& config) const; - std::string GetDestination() const { return this->Destination; } + DestinationContext GetDestination(cmGeneratorTarget* gt, + std::string const& config) const; bool GetOptional() const { return this->Optional; } std::string GetFileSetName() const { return this->FileSetName; } cmGeneratorFileSet const* GetFileSet() const { return this->FileSet; }; cmGeneratorTarget* GetTarget() const { return this->Target; } protected: + friend cmExportInstallCMakeConfigGenerator; + std::string GetDestination() const; + void GenerateScriptForConfig(std::ostream& os, std::string const& config, Indent indent) override; From 39a56136a3a189eca6bf08063932820cd061d7e7 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Wed, 25 Mar 2026 09:56:59 -0400 Subject: [PATCH 2/2] 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. --- Help/command/install.rst | 5 +++++ Help/manual/cmake-diagnostics.7.rst | 12 ++++++++++++ Help/manual/cmake-presets.7.rst | 3 +++ Help/manual/presets/errors-properties.rst | 9 +++++++++ Help/manual/presets/schema.json | 14 ++++++++++++++ Help/manual/presets/warnings-properties.rst | 9 +++++++++ .../dev/install-absolute-dest-configure-time.rst | 10 ++++++++++ ...AKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION.rst | 8 ++++++++ ...MAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION.rst | 8 ++++++++ Source/cmDiagnostics.h | 1 + Source/cmExportInstallCMakeConfigGenerator.cxx | 16 +++++++++------- Source/cmExportInstallPackageInfoGenerator.cxx | 14 +++++++------- Source/cmExportInstallSbomGenerator.cxx | 12 ++++++------ Source/cmInstallCommand.cxx | 9 +++++++++ Source/cmInstallCommandArguments.h | 2 +- Source/cmInstallDirectoryGenerator.cxx | 7 +++++-- Source/cmInstallFileSetGenerator.cxx | 11 +++++++++-- Source/cmInstallFileSetGenerator.h | 4 ++-- Source/cmInstallFilesGenerator.cxx | 7 +++++-- Source/cmInstallGenerator.cxx | 16 ++++++++++++++++ Source/cmInstallGenerator.h | 3 +++ Source/cmInstallTargetGenerator.cxx | 7 +++++-- .../CMakePresets/ErrorAbsInstallPath-stderr.txt | 5 +++++ .../CMakePresets/ErrorAbsInstallPath.cmake | 6 ++++++ Tests/RunCMake/CMakePresets/RunCMakeTest.cmake | 2 ++ .../WarningAbsInstallPath-stderr.txt | 5 +++++ .../CMakePresets/WarningAbsInstallPath.cmake | 6 ++++++ Tests/RunCMake/CMakePresets/Warnings12.json.in | 14 ++++++++++++++ Tests/RunCMake/Diagnostics/CacheInit.cmake | 1 + Tests/RunCMake/Diagnostics/CommandLine3.cmake | 2 ++ Tests/RunCMake/Diagnostics/RunCMakeTest.cmake | 2 +- .../DIRECTORY-AbsoluteDest-error-result.txt | 1 + .../DIRECTORY-AbsoluteDest-error-stderr.txt | 2 ++ .../install/DIRECTORY-AbsoluteDest-error.cmake | 1 + .../install/FILES-AbsoluteDest-error-result.txt | 1 + .../install/FILES-AbsoluteDest-error-stderr.txt | 2 ++ .../install/FILES-AbsoluteDest-error.cmake | 1 + .../install/FILES-AbsoluteDest-warn-stderr.txt | 2 ++ .../install/FILES-AbsoluteDest-warn.cmake | 1 + Tests/RunCMake/install/RunCMakeTest.cmake | 8 ++++++++ ...TARGETS-AbsoluteDest-archive-error-result.txt | 1 + ...TARGETS-AbsoluteDest-archive-error-stderr.txt | 2 ++ .../TARGETS-AbsoluteDest-archive-error.cmake | 3 +++ .../TARGETS-AbsoluteDest-error-result.txt | 1 + .../TARGETS-AbsoluteDest-error-stderr.txt | 2 ++ .../install/TARGETS-AbsoluteDest-error.cmake | 12 ++++++++++++ ...TARGETS-AbsoluteDest-library-error-result.txt | 1 + ...TARGETS-AbsoluteDest-library-error-stderr.txt | 2 ++ .../TARGETS-AbsoluteDest-library-error.cmake | 3 +++ ...TARGETS-AbsoluteDest-runtime-error-result.txt | 1 + ...TARGETS-AbsoluteDest-runtime-error-stderr.txt | 2 ++ .../TARGETS-AbsoluteDest-runtime-error.cmake | 3 +++ .../install/TARGETS-AbsoluteDest-warn-stderr.txt | 2 ++ .../install/TARGETS-AbsoluteDest-warn.cmake | 3 +++ 54 files changed, 255 insertions(+), 32 deletions(-) create mode 100644 Help/release/dev/install-absolute-dest-configure-time.rst create mode 100644 Tests/RunCMake/CMakePresets/ErrorAbsInstallPath-stderr.txt create mode 100644 Tests/RunCMake/CMakePresets/ErrorAbsInstallPath.cmake create mode 100644 Tests/RunCMake/CMakePresets/WarningAbsInstallPath-stderr.txt create mode 100644 Tests/RunCMake/CMakePresets/WarningAbsInstallPath.cmake create mode 100644 Tests/RunCMake/install/DIRECTORY-AbsoluteDest-error-result.txt create mode 100644 Tests/RunCMake/install/DIRECTORY-AbsoluteDest-error-stderr.txt create mode 100644 Tests/RunCMake/install/DIRECTORY-AbsoluteDest-error.cmake create mode 100644 Tests/RunCMake/install/FILES-AbsoluteDest-error-result.txt create mode 100644 Tests/RunCMake/install/FILES-AbsoluteDest-error-stderr.txt create mode 100644 Tests/RunCMake/install/FILES-AbsoluteDest-error.cmake create mode 100644 Tests/RunCMake/install/FILES-AbsoluteDest-warn-stderr.txt create mode 100644 Tests/RunCMake/install/FILES-AbsoluteDest-warn.cmake create mode 100644 Tests/RunCMake/install/TARGETS-AbsoluteDest-archive-error-result.txt create mode 100644 Tests/RunCMake/install/TARGETS-AbsoluteDest-archive-error-stderr.txt create mode 100644 Tests/RunCMake/install/TARGETS-AbsoluteDest-archive-error.cmake create mode 100644 Tests/RunCMake/install/TARGETS-AbsoluteDest-error-result.txt create mode 100644 Tests/RunCMake/install/TARGETS-AbsoluteDest-error-stderr.txt create mode 100644 Tests/RunCMake/install/TARGETS-AbsoluteDest-error.cmake create mode 100644 Tests/RunCMake/install/TARGETS-AbsoluteDest-library-error-result.txt create mode 100644 Tests/RunCMake/install/TARGETS-AbsoluteDest-library-error-stderr.txt create mode 100644 Tests/RunCMake/install/TARGETS-AbsoluteDest-library-error.cmake create mode 100644 Tests/RunCMake/install/TARGETS-AbsoluteDest-runtime-error-result.txt create mode 100644 Tests/RunCMake/install/TARGETS-AbsoluteDest-runtime-error-stderr.txt create mode 100644 Tests/RunCMake/install/TARGETS-AbsoluteDest-runtime-error.cmake create mode 100644 Tests/RunCMake/install/TARGETS-AbsoluteDest-warn-stderr.txt create mode 100644 Tests/RunCMake/install/TARGETS-AbsoluteDest-warn.cmake diff --git a/Help/command/install.rst b/Help/command/install.rst index 7ed27e7546..0d6ccb6116 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -60,6 +60,11 @@ signatures that specify them. The common options are: ```` should be a relative path. An absolute path is allowed, but not recommended. + .. versionadded:: 4.4 + The :ref:`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`` diff --git a/Help/manual/cmake-diagnostics.7.rst b/Help/manual/cmake-diagnostics.7.rst index 66a08d5409..5612299aae 100644 --- a/Help/manual/cmake-diagnostics.7.rst +++ b/Help/manual/cmake-diagnostics.7.rst @@ -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. diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst index e135cdf86f..4c672135ce 100644 --- a/Help/manual/cmake-presets.7.rst +++ b/Help/manual/cmake-presets.7.rst @@ -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} `_ macro now always expands to diff --git a/Help/manual/presets/errors-properties.rst b/Help/manual/presets/errors-properties.rst index 3f1216f9b3..7bf5dacba7 100644 --- a/Help/manual/presets/errors-properties.rst +++ b/Help/manual/presets/errors-properties.rst @@ -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`` diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json index 70f5024e5a..cd52447067 100644 --- a/Help/manual/presets/schema.json +++ b/Help/manual/presets/schema.json @@ -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." diff --git a/Help/manual/presets/warnings-properties.rst b/Help/manual/presets/warnings-properties.rst index acfce8ffe5..0a311908ab 100644 --- a/Help/manual/presets/warnings-properties.rst +++ b/Help/manual/presets/warnings-properties.rst @@ -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 ` or + :option:`-Wno-install-absolute-destination ` on the command line. + This may not be set to ``false`` if ``errors.installAbsoluteDestination`` is set to ``true``. + .. _`CMakePresets.configurePresets.warnings.uninitialized`: ``uninitialized`` diff --git a/Help/release/dev/install-absolute-dest-configure-time.rst b/Help/release/dev/install-absolute-dest-configure-time.rst new file mode 100644 index 0000000000..25a9c0add3 --- /dev/null +++ b/Help/release/dev/install-absolute-dest-configure-time.rst @@ -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 ` + diagnostic category. This diagnostic may be controlled with the + :option:`-Winstall-absolute-destination ` command-line option, the + ``installAbsoluteDestination`` field in a :manual:`cmake-presets(7)` + ``warnings`` object, or the :command:`cmake_diagnostic` command. diff --git a/Help/variable/CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION.rst b/Help/variable/CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION.rst index 38e9b7b365..84a27e5fe0 100644 --- a/Help/variable/CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION.rst +++ b/Help/variable/CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION.rst @@ -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 ` + diagnostic can be used to to generate errors for absolute install destinations + at generate time. + +See also :variable:`CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION`. diff --git a/Help/variable/CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION.rst b/Help/variable/CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION.rst index 81c1158c26..fac680ea95 100644 --- a/Help/variable/CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION.rst +++ b/Help/variable/CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION.rst @@ -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 ` + diagnostic can be used to to generate warnings for absolute install destinations + at generate time. + +See also :variable:`CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION`. diff --git a/Source/cmDiagnostics.h b/Source/cmDiagnostics.h index 3ab2239e1f..bad732b216 100644 --- a/Source/cmDiagnostics.h +++ b/Source/cmDiagnostics.h @@ -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) diff --git a/Source/cmExportInstallCMakeConfigGenerator.cxx b/Source/cmExportInstallCMakeConfigGenerator.cxx index 2e2f2c66b5..2f87099323 100644 --- a/Source/cmExportInstallCMakeConfigGenerator.cxx +++ b/Source/cmExportInstallCMakeConfigGenerator.cxx @@ -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("\"$<$:", dest, ">\"")); } else { diff --git a/Source/cmExportInstallPackageInfoGenerator.cxx b/Source/cmExportInstallPackageInfoGenerator.cxx index dd824ab61e..202594a754 100644 --- a/Source/cmExportInstallPackageInfoGenerator.cxx +++ b/Source/cmExportInstallPackageInfoGenerator.cxx @@ -224,14 +224,14 @@ cmExportInstallPackageInfoGenerator::GetFileSetDirectory( cmGeneratorTarget* gte, cmTargetExport const* te, cmGeneratorFileSet const* fileSet, cm::optional 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 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); } diff --git a/Source/cmExportInstallSbomGenerator.cxx b/Source/cmExportInstallSbomGenerator.cxx index 3f5f172fd7..f9641a1b48 100644 --- a/Source/cmExportInstallSbomGenerator.cxx +++ b/Source/cmExportInstallSbomGenerator.cxx @@ -216,11 +216,11 @@ cm::optional cmExportInstallSbomGenerator::GetFileSetDirectory( cmGeneratorTarget* gte, cmTargetExport const* te, cmGeneratorFileSet const* fileSet, cm::optional 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 cmExportInstallSbomGenerator::GetFileSetDirectory( } cm::optional 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); } diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 1fb9d4b5dd..8137d69b1b 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -1912,6 +1912,15 @@ bool HandleDirectoryMode(std::vector 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( diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h index 7bf861ea3e..c8b1ad94c7 100644 --- a/Source/cmInstallCommandArguments.h +++ b/Source/cmInstallCommandArguments.h @@ -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; diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx index cf1fac91fc..bd62dd372c 100644 --- a/Source/cmInstallDirectoryGenerator.cxx +++ b/Source/cmInstallDirectoryGenerator.cxx @@ -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; } diff --git a/Source/cmInstallFileSetGenerator.cxx b/Source/cmInstallFileSetGenerator.cxx index cbe55136e5..e6e9f031e8 100644 --- a/Source/cmInstallFileSetGenerator.cxx +++ b/Source/cmInstallFileSetGenerator.cxx @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -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 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() }; } diff --git a/Source/cmInstallFileSetGenerator.h b/Source/cmInstallFileSetGenerator.h index 82fe47074c..b0488fb3d5 100644 --- a/Source/cmInstallFileSetGenerator.h +++ b/Source/cmInstallFileSetGenerator.h @@ -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, diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx index 6da1862ba4..f5613fad28 100644 --- a/Source/cmInstallFilesGenerator.cxx +++ b/Source/cmInstallFilesGenerator.cxx @@ -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 diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx index dd9ade73c6..9317f94f5f 100644 --- a/Source/cmInstallGenerator.cxx +++ b/Source/cmInstallGenerator.cxx @@ -7,6 +7,9 @@ #include +#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) { diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h index 572d192361..d35a4b6bf0 100644 --- a/Source/cmInstallGenerator.h +++ b/Source/cmInstallGenerator.h @@ -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); diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 6b89f86df2..e2e7924b35 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -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( diff --git a/Tests/RunCMake/CMakePresets/ErrorAbsInstallPath-stderr.txt b/Tests/RunCMake/CMakePresets/ErrorAbsInstallPath-stderr.txt new file mode 100644 index 0000000000..6d9315ee93 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/ErrorAbsInstallPath-stderr.txt @@ -0,0 +1,5 @@ +CMake Warning \(unused-cli\): + Manually-specified variables were not used by the project: + + RunCMake_GENERATOR + UNUSED_VARIABLE$ diff --git a/Tests/RunCMake/CMakePresets/ErrorAbsInstallPath.cmake b/Tests/RunCMake/CMakePresets/ErrorAbsInstallPath.cmake new file mode 100644 index 0000000000..d6fe2ff38c --- /dev/null +++ b/Tests/RunCMake/CMakePresets/ErrorAbsInstallPath.cmake @@ -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() diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake index e1e6ad4ecb..90e6581900 100644 --- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake @@ -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) diff --git a/Tests/RunCMake/CMakePresets/WarningAbsInstallPath-stderr.txt b/Tests/RunCMake/CMakePresets/WarningAbsInstallPath-stderr.txt new file mode 100644 index 0000000000..6d9315ee93 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/WarningAbsInstallPath-stderr.txt @@ -0,0 +1,5 @@ +CMake Warning \(unused-cli\): + Manually-specified variables were not used by the project: + + RunCMake_GENERATOR + UNUSED_VARIABLE$ diff --git a/Tests/RunCMake/CMakePresets/WarningAbsInstallPath.cmake b/Tests/RunCMake/CMakePresets/WarningAbsInstallPath.cmake new file mode 100644 index 0000000000..fc59b1ca4e --- /dev/null +++ b/Tests/RunCMake/CMakePresets/WarningAbsInstallPath.cmake @@ -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() diff --git a/Tests/RunCMake/CMakePresets/Warnings12.json.in b/Tests/RunCMake/CMakePresets/Warnings12.json.in index 64eae5d555..ebc651f999 100644 --- a/Tests/RunCMake/CMakePresets/Warnings12.json.in +++ b/Tests/RunCMake/CMakePresets/Warnings12.json.in @@ -29,6 +29,20 @@ "unusedCli": false } }, + { + "name": "WarningAbsInstallPath", + "inherits": "NoWarningFlags", + "warnings": { + "installAbsoluteDestination": true + } + }, + { + "name": "ErrorAbsInstallPath", + "inherits": "NoWarningFlags", + "errors": { + "installAbsoluteDestination": true + } + }, { "name": "ErrorDev", "inherits": "NoWarningFlags", diff --git a/Tests/RunCMake/Diagnostics/CacheInit.cmake b/Tests/RunCMake/Diagnostics/CacheInit.cmake index 1af149535a..24baac2c6b 100644 --- a/Tests/RunCMake/Diagnostics/CacheInit.cmake +++ b/Tests/RunCMake/Diagnostics/CacheInit.cmake @@ -1,4 +1,5 @@ include(Assertions.cmake) expect(CMD_AUTHOR IGNORE) +expect(CMD_INSTALL_ABSOLUTE_DESTINATION IGNORE) expect(CMD_DEPRECATED SEND_ERROR) diff --git a/Tests/RunCMake/Diagnostics/CommandLine3.cmake b/Tests/RunCMake/Diagnostics/CommandLine3.cmake index e11e17d099..96f8e1ae80 100644 --- a/Tests/RunCMake/Diagnostics/CommandLine3.cmake +++ b/Tests/RunCMake/Diagnostics/CommandLine3.cmake @@ -1,3 +1,5 @@ include(Assertions.cmake) expect_cached(CMD_UNINITIALIZED IGNORE) + +expect_cached(CMD_INSTALL_ABSOLUTE_DESTINATION WARN) diff --git a/Tests/RunCMake/Diagnostics/RunCMakeTest.cmake b/Tests/RunCMake/Diagnostics/RunCMakeTest.cmake index 5ffb6fa844..5f77f8ea98 100644 --- a/Tests/RunCMake/Diagnostics/RunCMakeTest.cmake +++ b/Tests/RunCMake/Diagnostics/RunCMakeTest.cmake @@ -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) diff --git a/Tests/RunCMake/install/DIRECTORY-AbsoluteDest-error-result.txt b/Tests/RunCMake/install/DIRECTORY-AbsoluteDest-error-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/install/DIRECTORY-AbsoluteDest-error-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/DIRECTORY-AbsoluteDest-error-stderr.txt b/Tests/RunCMake/install/DIRECTORY-AbsoluteDest-error-stderr.txt new file mode 100644 index 0000000000..d742940529 --- /dev/null +++ b/Tests/RunCMake/install/DIRECTORY-AbsoluteDest-error-stderr.txt @@ -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\)\. diff --git a/Tests/RunCMake/install/DIRECTORY-AbsoluteDest-error.cmake b/Tests/RunCMake/install/DIRECTORY-AbsoluteDest-error.cmake new file mode 100644 index 0000000000..a76ddb48d6 --- /dev/null +++ b/Tests/RunCMake/install/DIRECTORY-AbsoluteDest-error.cmake @@ -0,0 +1 @@ +install(DIRECTORY DESTINATION /absolute/path) diff --git a/Tests/RunCMake/install/FILES-AbsoluteDest-error-result.txt b/Tests/RunCMake/install/FILES-AbsoluteDest-error-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/install/FILES-AbsoluteDest-error-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/FILES-AbsoluteDest-error-stderr.txt b/Tests/RunCMake/install/FILES-AbsoluteDest-error-stderr.txt new file mode 100644 index 0000000000..689d48b42e --- /dev/null +++ b/Tests/RunCMake/install/FILES-AbsoluteDest-error-stderr.txt @@ -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\)\. diff --git a/Tests/RunCMake/install/FILES-AbsoluteDest-error.cmake b/Tests/RunCMake/install/FILES-AbsoluteDest-error.cmake new file mode 100644 index 0000000000..28cb56bcce --- /dev/null +++ b/Tests/RunCMake/install/FILES-AbsoluteDest-error.cmake @@ -0,0 +1 @@ +install(FILES empty.c DESTINATION /absolute/path) diff --git a/Tests/RunCMake/install/FILES-AbsoluteDest-warn-stderr.txt b/Tests/RunCMake/install/FILES-AbsoluteDest-warn-stderr.txt new file mode 100644 index 0000000000..f320131e0c --- /dev/null +++ b/Tests/RunCMake/install/FILES-AbsoluteDest-warn-stderr.txt @@ -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\)\. diff --git a/Tests/RunCMake/install/FILES-AbsoluteDest-warn.cmake b/Tests/RunCMake/install/FILES-AbsoluteDest-warn.cmake new file mode 100644 index 0000000000..28cb56bcce --- /dev/null +++ b/Tests/RunCMake/install/FILES-AbsoluteDest-warn.cmake @@ -0,0 +1 @@ +install(FILES empty.c DESTINATION /absolute/path) diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index ff8e812fba..5e40e88e27 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -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) diff --git a/Tests/RunCMake/install/TARGETS-AbsoluteDest-archive-error-result.txt b/Tests/RunCMake/install/TARGETS-AbsoluteDest-archive-error-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-AbsoluteDest-archive-error-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/TARGETS-AbsoluteDest-archive-error-stderr.txt b/Tests/RunCMake/install/TARGETS-AbsoluteDest-archive-error-stderr.txt new file mode 100644 index 0000000000..e091ab01d8 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-AbsoluteDest-archive-error-stderr.txt @@ -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\)\. diff --git a/Tests/RunCMake/install/TARGETS-AbsoluteDest-archive-error.cmake b/Tests/RunCMake/install/TARGETS-AbsoluteDest-archive-error.cmake new file mode 100644 index 0000000000..3ecc7e387b --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-AbsoluteDest-archive-error.cmake @@ -0,0 +1,3 @@ +enable_language(C) +add_library(mylib STATIC empty.c) +install(TARGETS mylib ARCHIVE DESTINATION /absolute/archive) diff --git a/Tests/RunCMake/install/TARGETS-AbsoluteDest-error-result.txt b/Tests/RunCMake/install/TARGETS-AbsoluteDest-error-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-AbsoluteDest-error-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/TARGETS-AbsoluteDest-error-stderr.txt b/Tests/RunCMake/install/TARGETS-AbsoluteDest-error-stderr.txt new file mode 100644 index 0000000000..22c0d98269 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-AbsoluteDest-error-stderr.txt @@ -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\)\. diff --git a/Tests/RunCMake/install/TARGETS-AbsoluteDest-error.cmake b/Tests/RunCMake/install/TARGETS-AbsoluteDest-error.cmake new file mode 100644 index 0000000000..b16af5c2e6 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-AbsoluteDest-error.cmake @@ -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) diff --git a/Tests/RunCMake/install/TARGETS-AbsoluteDest-library-error-result.txt b/Tests/RunCMake/install/TARGETS-AbsoluteDest-library-error-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-AbsoluteDest-library-error-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/TARGETS-AbsoluteDest-library-error-stderr.txt b/Tests/RunCMake/install/TARGETS-AbsoluteDest-library-error-stderr.txt new file mode 100644 index 0000000000..368434d81c --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-AbsoluteDest-library-error-stderr.txt @@ -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\)\. diff --git a/Tests/RunCMake/install/TARGETS-AbsoluteDest-library-error.cmake b/Tests/RunCMake/install/TARGETS-AbsoluteDest-library-error.cmake new file mode 100644 index 0000000000..b5be8fdd3e --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-AbsoluteDest-library-error.cmake @@ -0,0 +1,3 @@ +enable_language(C) +add_library(mylib MODULE empty.c) +install(TARGETS mylib LIBRARY DESTINATION /absolute/lib) diff --git a/Tests/RunCMake/install/TARGETS-AbsoluteDest-runtime-error-result.txt b/Tests/RunCMake/install/TARGETS-AbsoluteDest-runtime-error-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-AbsoluteDest-runtime-error-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/TARGETS-AbsoluteDest-runtime-error-stderr.txt b/Tests/RunCMake/install/TARGETS-AbsoluteDest-runtime-error-stderr.txt new file mode 100644 index 0000000000..279fb88e28 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-AbsoluteDest-runtime-error-stderr.txt @@ -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\)\. diff --git a/Tests/RunCMake/install/TARGETS-AbsoluteDest-runtime-error.cmake b/Tests/RunCMake/install/TARGETS-AbsoluteDest-runtime-error.cmake new file mode 100644 index 0000000000..638f7fba95 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-AbsoluteDest-runtime-error.cmake @@ -0,0 +1,3 @@ +enable_language(C) +add_executable(myexe empty.c) +install(TARGETS myexe RUNTIME DESTINATION /absolute/bin) diff --git a/Tests/RunCMake/install/TARGETS-AbsoluteDest-warn-stderr.txt b/Tests/RunCMake/install/TARGETS-AbsoluteDest-warn-stderr.txt new file mode 100644 index 0000000000..730a8edf95 --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-AbsoluteDest-warn-stderr.txt @@ -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\)\. diff --git a/Tests/RunCMake/install/TARGETS-AbsoluteDest-warn.cmake b/Tests/RunCMake/install/TARGETS-AbsoluteDest-warn.cmake new file mode 100644 index 0000000000..e2ca4befcd --- /dev/null +++ b/Tests/RunCMake/install/TARGETS-AbsoluteDest-warn.cmake @@ -0,0 +1,3 @@ +enable_language(C) +add_library(mylib STATIC empty.c) +install(TARGETS mylib DESTINATION /absolute/path)