Merge topic 'normalize-install-destination-paths'

6a1fac1450 install: Normalize DESTINATION paths
2184fcfb00 Tests: Configure RunCMake.install cases with correct build type
5a8a6dfe81 cmGeneratorExpression: Change Find() parameter type to cm::string_view
d810374b3d install(PACKAGE_INFO): Remove outdated TODO comment
d13ed01d54 Tests: Remove unused files from RunCMake.install

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !9800
This commit is contained in:
Brad King
2024-09-20 10:27:30 -04:00
committed by Kitware Robot
26 changed files with 357 additions and 58 deletions
+13 -1
View File
@@ -58,7 +58,7 @@ signatures that specify them. The common options are:
``<dir>`` should be a relative path. An absolute path is allowed,
but not recommended.
When a relative path is given it is interpreted relative to the value
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``
mechanism explained in the :variable:`CMAKE_INSTALL_PREFIX` variable
@@ -75,6 +75,11 @@ signatures that specify them. The common options are:
If an absolute path (with a leading slash or drive letter) is given
it is used verbatim.
.. versionchanged:: 3.31
``<dir>`` will be normalized according to the same
:ref:`normalization rules <Normalization>` as the
:command:`cmake_path` command.
``PERMISSIONS <permission>...``
Specify permissions for installed files. Valid permissions are
``OWNER_READ``, ``OWNER_WRITE``, ``OWNER_EXECUTE``, ``GROUP_READ``,
@@ -396,6 +401,12 @@ Signatures
If a relative path is specified, it is treated as relative to the
:genex:`$<INSTALL_PREFIX>`.
Unlike other ``DESTINATION`` arguments for the various ``install()``
subcommands, paths given after ``INCLUDES DESTINATION`` are used as
given. They are not normalized, nor assumed to be normalized, although
it is recommended that they are given in normalized form (see
:ref:`Normalization`).
``RUNTIME_DEPENDENCY_SET <set-name>``
.. versionadded:: 3.21
@@ -815,6 +826,7 @@ Signatures
the generated file will be called ``<export-name>.cmake`` but the ``FILE``
option may be used to specify a different name. The value given to
the ``FILE`` option must be a file name with the ``.cmake`` extension.
If a ``CONFIGURATIONS`` option is given then the file will only be installed
when one of the named configurations is installed. Additionally, the
generated import file will reference only the matching target
+1
View File
@@ -57,6 +57,7 @@ Policies Introduced by CMake 3.31
.. toctree::
:maxdepth: 1
CMP0177: install() DESTINATION paths are normalized. </policy/CMP0177>
CMP0176: execute_process() ENCODING is UTF-8 by default. </policy/CMP0176>
CMP0175: add_custom_command() rejects invalid arguments. </policy/CMP0175>
CMP0174: cmake_parse_arguments(PARSE_ARGV) defines a variable for an empty string after a single-value keyword. </policy/CMP0174>
+38
View File
@@ -0,0 +1,38 @@
CMP0177
-------
.. versionadded:: 3.31
:command:`install` ``DESTINATION`` paths are normalized.
The :command:`install` command has a number of different forms, and most of
them take a ``DESTINATION`` keyword, some in more than one place.
CMake 3.30 and earlier used the value given after the ``DESTINATION`` keyword
as provided with no transformations. The :command:`install(EXPORT)` form
assumes the path contains no ``..`` or ``.`` path components when computing
a path relative to the ``DESTINATION``, and if the project provided a path
that violated that assumption, the computed path would be incorrect.
CMake 3.31 normalizes all ``DESTINATION`` values given in any form of the
:command:`install` command, except for the ``INCLUDES DESTINATION`` of the
:command:`install(TARGETS)` form. The normalization performed is the same
as for the :command:`cmake_path` command (see :ref:`Normalization`).
The ``OLD`` behavior of this policy performs no translation on the
``DESTINATION`` values of any :command:`install` command. They are used
exactly as provided. If a destination path contains ``..`` or ``.`` path
components, :command:`install(EXPORT)` will use the same wrong paths as
CMake 3.30 and earlier.
The ``NEW`` behavior will normalize all ``DESTINATION`` values except for
``INCLUDES DESTINATION``. If a destination path contains a generator
expression, it will be wrapped in a ``$<PATH:CMAKE_PATH,NORMALIZE,...>``
generator expression.
This policy was introduced in CMake version 3.31.
It may be set by :command:`cmake_policy` or :command:`cmake_minimum_required`.
If it is not set, CMake will warn if it detects a path that would be different
if normalized, and uses ``OLD`` behavior. If a destination path contains a
generator expression, no such warning will be issued regardless of the value.
.. include:: DEPRECATED.txt
@@ -0,0 +1,6 @@
normalize-install-destination-paths
-----------------------------------
* All ``DESTINATION`` arguments in :command:`install` commands
are now :ref:`normalized <Normalization>`, with the exception
of ``INCLUDES DESTINATION`` arguments in the ``TARGETS`` form.
+6 -5
View File
@@ -375,14 +375,15 @@ std::string cmGeneratorExpression::Preprocess(const std::string& input,
return std::string();
}
std::string::size_type cmGeneratorExpression::Find(const std::string& input)
cm::string_view::size_type cmGeneratorExpression::Find(
const cm::string_view& input)
{
const std::string::size_type openpos = input.find("$<");
if (openpos != std::string::npos &&
input.find('>', openpos) != std::string::npos) {
const cm::string_view::size_type openpos = input.find("$<");
if (openpos != cm::string_view::npos &&
input.find('>', openpos) != cm::string_view::npos) {
return openpos;
}
return std::string::npos;
return cm::string_view::npos;
}
bool cmGeneratorExpression::IsValidTargetName(const std::string& input)
+1 -1
View File
@@ -66,7 +66,7 @@ public:
static void Split(const std::string& input,
std::vector<std::string>& output);
static std::string::size_type Find(const std::string& input);
static cm::string_view::size_type Find(const cm::string_view& input);
static bool IsValidTargetName(const std::string& input);
+81 -34
View File
@@ -20,6 +20,7 @@
#include "cmArgumentParser.h"
#include "cmArgumentParserTypes.h"
#include "cmCMakePath.h"
#include "cmExecutionStatus.h"
#include "cmExperimental.h"
#include "cmExportSet.h"
@@ -455,7 +456,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
runtimeDependenciesArgVector;
std::string runtimeDependencySetArg;
std::vector<std::string> unknownArgs;
cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
cmInstallCommandArguments genericArgs(helper.DefaultComponentName,
*helper.Makefile);
genericArgs.Bind("TARGETS"_s, targetList);
genericArgs.Bind("EXPORT"_s, exports);
genericArgs.Bind("RUNTIME_DEPENDENCIES"_s, runtimeDependenciesArgVector);
@@ -469,19 +471,31 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
&unknownArgs)
: RuntimeDependenciesArgs();
cmInstallCommandArguments archiveArgs(helper.DefaultComponentName);
cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName);
cmInstallCommandArguments objectArgs(helper.DefaultComponentName);
cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName);
cmInstallCommandArguments bundleArgs(helper.DefaultComponentName);
cmInstallCommandArguments privateHeaderArgs(helper.DefaultComponentName);
cmInstallCommandArguments publicHeaderArgs(helper.DefaultComponentName);
cmInstallCommandArguments resourceArgs(helper.DefaultComponentName);
cmInstallCommandArguments archiveArgs(helper.DefaultComponentName,
*helper.Makefile);
cmInstallCommandArguments libraryArgs(helper.DefaultComponentName,
*helper.Makefile);
cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName,
*helper.Makefile);
cmInstallCommandArguments objectArgs(helper.DefaultComponentName,
*helper.Makefile);
cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName,
*helper.Makefile);
cmInstallCommandArguments bundleArgs(helper.DefaultComponentName,
*helper.Makefile);
cmInstallCommandArguments privateHeaderArgs(helper.DefaultComponentName,
*helper.Makefile);
cmInstallCommandArguments publicHeaderArgs(helper.DefaultComponentName,
*helper.Makefile);
cmInstallCommandArguments resourceArgs(helper.DefaultComponentName,
*helper.Makefile);
cmInstallCommandIncludesArgument includesArgs;
std::vector<cmInstallCommandFileSetArguments> fileSetArgs(
argVectors.FileSets.size(), { helper.DefaultComponentName });
cmInstallCommandArguments cxxModuleBmiArgs(helper.DefaultComponentName);
argVectors.FileSets.size(),
{ cmInstallCommandFileSetArguments(helper.DefaultComponentName,
*helper.Makefile) });
cmInstallCommandArguments cxxModuleBmiArgs(helper.DefaultComponentName,
*helper.Makefile);
// now parse the args for specific parts of the target (e.g. LIBRARY,
// RUNTIME, ARCHIVE etc.
@@ -501,7 +515,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// cmArgumentParser<void>::Bind() binds to a specific address, but the
// objects in the vector can move around. So we parse in an object with a
// fixed address and then copy the data into the vector.
cmInstallCommandFileSetArguments fileSetArg(helper.DefaultComponentName);
cmInstallCommandFileSetArguments fileSetArg(helper.DefaultComponentName,
*helper.Makefile);
fileSetArg.Parse(argVectors.FileSets[i], &unknownArgs);
fileSetArgs[i] = std::move(fileSetArg);
}
@@ -1312,16 +1327,21 @@ bool HandleImportedRuntimeArtifactsMode(std::vector<std::string> const& args,
ArgumentParser::MaybeEmpty<std::vector<std::string>> targetList;
std::string runtimeDependencySetArg;
std::vector<std::string> unknownArgs;
cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
cmInstallCommandArguments genericArgs(helper.DefaultComponentName,
*helper.Makefile);
genericArgs.Bind("IMPORTED_RUNTIME_ARTIFACTS"_s, targetList)
.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg);
genericArgs.Parse(genericArgVector, &unknownArgs);
bool success = genericArgs.Finalize();
cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName);
cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName);
cmInstallCommandArguments bundleArgs(helper.DefaultComponentName);
cmInstallCommandArguments libraryArgs(helper.DefaultComponentName,
*helper.Makefile);
cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName,
*helper.Makefile);
cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName,
*helper.Makefile);
cmInstallCommandArguments bundleArgs(helper.DefaultComponentName,
*helper.Makefile);
// now parse the args for specific parts of the target (e.g. LIBRARY,
// RUNTIME etc.
@@ -1549,7 +1569,7 @@ bool HandleFilesMode(std::vector<std::string> const& args,
// This is the FILES mode.
bool programs = (args[0] == "PROGRAMS");
cmInstallCommandArguments ica(helper.DefaultComponentName);
cmInstallCommandArguments ica(helper.DefaultComponentName, *helper.Makefile);
ArgumentParser::MaybeEmpty<std::vector<std::string>> files;
ica.Bind(programs ? "PROGRAMS"_s : "FILES"_s, files);
std::vector<std::string> unknownArgs;
@@ -1683,7 +1703,7 @@ bool HandleDirectoryMode(std::vector<std::string> const& args,
bool exclude_from_all = false;
bool message_never = false;
std::vector<std::string> dirs;
const std::string* destination = nullptr;
cm::optional<std::string> destination;
std::string permissions_file;
std::string permissions_dir;
std::vector<std::string> configurations;
@@ -1841,7 +1861,33 @@ bool HandleDirectoryMode(std::vector<std::string> const& args,
} else if (doing == DoingConfigurations) {
configurations.push_back(args[i]);
} else if (doing == DoingDestination) {
destination = &args[i];
// A trailing slash is meaningful for this form, but normalization
// preserves it if present
switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0177)) {
case cmPolicies::NEW:
destination = cmCMakePath(args[i]).Normal().String();
break;
case cmPolicies::WARN:
// We can't be certain if a warning is appropriate if there are any
// generator expressions
if (cmGeneratorExpression::Find(args[i]) == cm::string_view::npos &&
args[i] != cmCMakePath(args[i]).Normal().String()) {
status.GetMakefile().IssueMessage(
MessageType::AUTHOR_WARNING,
cmPolicies::GetPolicyWarning(cmPolicies::CMP0177));
}
CM_FALLTHROUGH;
case cmPolicies::OLD:
destination = args[i];
break;
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::REQUIRED_IF_USED:
// We should never get here, only OLD, WARN, and NEW are used
status.GetMakefile().IssueMessage(
MessageType::FATAL_ERROR,
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0177));
return false;
}
doing = DoingNone;
} else if (doing == DoingType) {
if (allowedTypes.count(args[i]) == 0) {
@@ -1911,7 +1957,7 @@ bool HandleDirectoryMode(std::vector<std::string> const& args,
}
// Support installing an empty directory.
if (dirs.empty() && destination) {
if (dirs.empty() && destination.has_value()) {
dirs.emplace_back();
}
@@ -1919,15 +1965,13 @@ bool HandleDirectoryMode(std::vector<std::string> const& args,
if (dirs.empty()) {
return true;
}
std::string destinationStr;
if (!destination) {
if (!destination.has_value()) {
if (type.empty()) {
// A destination is required.
status.SetError(cmStrCat(args[0], " given no DESTINATION!"));
return false;
}
destinationStr = helper.GetDestinationForType(nullptr, type);
destination = &destinationStr;
destination = helper.GetDestinationForType(nullptr, type);
} else if (!type.empty()) {
status.SetError(cmStrCat(args[0],
" given both TYPE and DESTINATION "
@@ -1959,7 +2003,7 @@ bool HandleExportAndroidMKMode(std::vector<std::string> const& args,
Helper helper(status);
// This is the EXPORT mode.
cmInstallCommandArguments ica(helper.DefaultComponentName);
cmInstallCommandArguments ica(helper.DefaultComponentName, *helper.Makefile);
std::string exp;
std::string name_space;
@@ -2052,7 +2096,7 @@ bool HandleExportMode(std::vector<std::string> const& args,
Helper helper(status);
// This is the EXPORT mode.
cmInstallCommandArguments ica(helper.DefaultComponentName);
cmInstallCommandArguments ica(helper.DefaultComponentName, *helper.Makefile);
std::string exp;
std::string name_space;
@@ -2178,7 +2222,7 @@ bool HandlePackageInfoMode(std::vector<std::string> const& args,
Helper helper(status);
// This is the PACKAGE_INFO mode.
cmInstallCommandArguments ica(helper.DefaultComponentName);
cmInstallCommandArguments ica(helper.DefaultComponentName, *helper.Makefile);
ArgumentParser::NonEmpty<std::string> pkg;
ArgumentParser::NonEmpty<std::string> appendix;
@@ -2191,7 +2235,6 @@ bool HandlePackageInfoMode(std::vector<std::string> const& args,
ArgumentParser::NonEmpty<std::vector<std::string>> defaultConfigs;
ArgumentParser::NonEmpty<std::string> cxxModulesDirectory;
// TODO: Support DESTINATION.
ica.Bind("PACKAGE_INFO"_s, pkg);
ica.Bind("EXPORT"_s, exportName);
ica.Bind("APPENDIX"_s, appendix);
@@ -2338,14 +2381,18 @@ bool HandleRuntimeDependencySetMode(std::vector<std::string> const& args,
// These generic args also contain the runtime dependency set
std::string runtimeDependencySetArg;
std::vector<std::string> runtimeDependencyArgVector;
cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
cmInstallCommandArguments genericArgs(helper.DefaultComponentName,
*helper.Makefile);
genericArgs.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg);
genericArgs.Parse(genericArgVector, &runtimeDependencyArgVector);
bool success = genericArgs.Finalize();
cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName);
cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName);
cmInstallCommandArguments libraryArgs(helper.DefaultComponentName,
*helper.Makefile);
cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName,
*helper.Makefile);
cmInstallCommandArguments frameworkArgs(helper.DefaultComponentName,
*helper.Makefile);
// Now also parse the file(GET_RUNTIME_DEPENDENCY) args
std::vector<std::string> unknownArgs;
+55 -4
View File
@@ -3,11 +3,19 @@
#include "cmInstallCommandArguments.h"
#include <algorithm>
#include <functional>
#include <utility>
#include <cm/string_view>
#include <cmext/string_view>
#include "cmCMakePath.h"
#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
// Table of valid permissions.
@@ -20,10 +28,53 @@ const char* cmInstallCommandArguments::PermissionsTable[] = {
const std::string cmInstallCommandArguments::EmptyString;
cmInstallCommandArguments::cmInstallCommandArguments(
std::string defaultComponent)
std::string defaultComponent, cmMakefile& makefile)
: DefaultComponentName(std::move(defaultComponent))
{
this->Bind("DESTINATION"_s, this->Destination);
std::function<ArgumentParser::Continue(cm::string_view)> normalizeDest;
switch (makefile.GetPolicyStatus(cmPolicies::CMP0177)) {
case cmPolicies::OLD:
normalizeDest = [this](cm::string_view arg) -> ArgumentParser::Continue {
this->Destination = std::string(arg.begin(), arg.end());
return ArgumentParser::Continue::Yes;
};
break;
case cmPolicies::WARN:
normalizeDest =
[this, &makefile](cm::string_view arg) -> ArgumentParser::Continue {
this->Destination = std::string(arg.begin(), arg.end());
// We can't be certain if a warning is appropriate if there are any
// generator expressions
if (cmGeneratorExpression::Find(arg) == cm::string_view::npos &&
arg != cmCMakePath(arg).Normal().String()) {
makefile.IssueMessage(
MessageType::AUTHOR_WARNING,
cmPolicies::GetPolicyWarning(cmPolicies::CMP0177));
}
return ArgumentParser::Continue::Yes;
};
break;
case cmPolicies::NEW:
normalizeDest = [this](cm::string_view arg) -> ArgumentParser::Continue {
if (cmGeneratorExpression::Find(arg) == cm::string_view::npos) {
this->Destination = cmCMakePath(arg).Normal().String();
} else {
this->Destination =
cmStrCat("$<PATH:CMAKE_PATH,NORMALIZE,", arg, '>');
}
return ArgumentParser::Continue::Yes;
};
break;
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::REQUIRED_IF_USED:
// We should never get here, only OLD, WARN, and NEW are used
makefile.IssueMessage(
MessageType::FATAL_ERROR,
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0177));
}
this->Bind("DESTINATION"_s, normalizeDest);
this->Bind("COMPONENT"_s, this->Component);
this->Bind("NAMELINK_COMPONENT"_s, this->NamelinkComponent);
this->Bind("EXCLUDE_FROM_ALL"_s, this->ExcludeFromAll);
@@ -227,8 +278,8 @@ void cmInstallCommandIncludesArgument::Parse(
}
cmInstallCommandFileSetArguments::cmInstallCommandFileSetArguments(
std::string defaultComponent)
: cmInstallCommandArguments(std::move(defaultComponent))
std::string defaultComponent, cmMakefile& makefile)
: cmInstallCommandArguments(std::move(defaultComponent), makefile)
{
this->Bind("FILE_SET"_s, this->FileSet);
}
+6 -2
View File
@@ -10,10 +10,13 @@
#include "cmArgumentParser.h"
#include "cmArgumentParserTypes.h"
class cmMakefile;
class cmInstallCommandArguments : public cmArgumentParser<void>
{
public:
cmInstallCommandArguments(std::string defaultComponent);
cmInstallCommandArguments(std::string defaultComponent,
cmMakefile& makefile);
void SetGenericArguments(cmInstallCommandArguments* args)
{
this->GenericArguments = args;
@@ -78,7 +81,8 @@ private:
class cmInstallCommandFileSetArguments : public cmInstallCommandArguments
{
public:
cmInstallCommandFileSetArguments(std::string defaultComponent);
cmInstallCommandFileSetArguments(std::string defaultComponent,
cmMakefile& makefile);
void Parse(std::vector<std::string> args,
std::vector<std::string>* unconsumedArgs);
+3 -1
View File
@@ -541,7 +541,9 @@ class cmMakefile;
SELECT(POLICY, CMP0175, "add_custom_command() rejects invalid arguments.", \
3, 31, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0176, "execute_process() ENCODING is UTF-8 by default.", \
3, 31, 0, cmPolicies::WARN)
3, 31, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0177, "install() DESTINATION paths are normalized.", 3, \
31, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
@@ -0,0 +1,36 @@
set(installBase ${RunCMake_TEST_BINARY_DIR}/root-all)
foreach(i RANGE 1 5)
set(subdir shouldNotRemain${i})
if(IS_DIRECTORY ${installBase}/${subdir})
set(RunCMake_TEST_FAILED "Check failed.")
string(APPEND RunCMake_TEST_FAILURE_MESSAGE
"\nUnexpectedly created install path that should have disappeared with "
"normalization:\n"
" ${installBase}/${subdir}"
)
endif()
endforeach()
file(GLOB perConfigFiles ${installBase}/lib/cmake/pkg/pkg-config-*.cmake)
foreach(file IN LISTS perConfigFiles ITEMS ${installBase}/lib/cmake/pkg/pkg-config.cmake)
file(STRINGS ${file} matches REGEX shouldNotRemain)
if(NOT matches STREQUAL "")
set(RunCMake_TEST_FAILED "Check failed.")
string(APPEND RunCMake_TEST_FAILURE_MESSAGE
"\nNon-normalized path found in ${file}:"
)
foreach(match IN LISTS matches)
string(APPEND RunCMake_TEST_FAILURE_MESSAGE "\n ${match}")
endforeach()
endif()
endforeach()
if(NOT EXISTS "${installBase}/dirs/dir/empty.txt")
set(RunCMake_TEST_FAILED "Check failed.")
string(APPEND RunCMake_TEST_FAILURE_MESSAGE
"\nNon-normalized DIRECTORY destination not handled correctly. "
"Expected to find the following file, but it was missing:\n"
" ${installBase}/dirs/dir/empty.txt"
)
endif()
@@ -0,0 +1,2 @@
enable_language(C)
find_package(pkg REQUIRED)
+2
View File
@@ -0,0 +1,2 @@
cmake_policy(SET CMP0177 NEW)
include(${CMAKE_CURRENT_LIST_DIR}/CMP0177.cmake)
@@ -0,0 +1 @@
1
@@ -0,0 +1,13 @@
CMake Error at [^
]*CMP0177-OLD-build/root-all/lib/cmake/pkg/pkg-config\.cmake:[0-9]+ \(message\):
The imported target "foo1" references the file
+ ".*/shouldNotRemain1/\.\./lib/(libfoo1\.a|foo1\.l(ib)?)"
+ but this file does not exist\. Possible reasons include:
+ \* The file was deleted, renamed, or moved to another location\.
+ \* An install or uninstall procedure did not complete successfully\.
+ \* The installation package was faulty and contained
+ ".*/Tests/RunCMake/install/CMP0177-OLD-build/root-all/lib/cmake/pkg/pkg-config\.cmake"
+ but not all the files it references\.
+Call Stack \(most recent call first\):
CMP0177-OLD-verify\.cmake:2 \(find_package\)
CMakeLists\.txt:3 \(include\)
@@ -0,0 +1,2 @@
enable_language(C)
find_package(pkg REQUIRED)
+2
View File
@@ -0,0 +1,2 @@
cmake_policy(SET CMP0177 OLD)
include(${CMAKE_CURRENT_LIST_DIR}/CMP0177.cmake)
@@ -0,0 +1,35 @@
CMake Warning \(dev\) at CMP0177\.cmake:[0-9]+ \(install\):
Policy CMP0177 is not set: install\(\) DESTINATION paths are normalized\. Run
"cmake --help-policy CMP0177" for policy details\. Use the cmake_policy
command to set the policy and suppress this warning\.
Call Stack \(most recent call first\):
CMP0177-WARN\.cmake:1 \(include\)
CMakeLists\.txt:3 \(include\)
This warning is for project developers\. Use -Wno-dev to suppress it\.
CMake Warning \(dev\) at CMP0177\.cmake:[0-9]+ \(install\):
Policy CMP0177 is not set: install\(\) DESTINATION paths are normalized\. Run
"cmake --help-policy CMP0177" for policy details\. Use the cmake_policy
command to set the policy and suppress this warning\.
Call Stack \(most recent call first\):
CMP0177-WARN\.cmake:1 \(include\)
CMakeLists\.txt:3 \(include\)
This warning is for project developers\. Use -Wno-dev to suppress it\.
CMake Warning \(dev\) at CMP0177\.cmake:[0-9]+ \(install\):
Policy CMP0177 is not set: install\(\) DESTINATION paths are normalized\. Run
"cmake --help-policy CMP0177" for policy details\. Use the cmake_policy
command to set the policy and suppress this warning\.
Call Stack \(most recent call first\):
CMP0177-WARN\.cmake:1 \(include\)
CMakeLists\.txt:3 \(include\)
This warning is for project developers\. Use -Wno-dev to suppress it\.
CMake Warning \(dev\) at CMP0177\.cmake:[0-9]+ \(install\):
Policy CMP0177 is not set: install\(\) DESTINATION paths are normalized\. Run
"cmake --help-policy CMP0177" for policy details\. Use the cmake_policy
command to set the policy and suppress this warning\.
Call Stack \(most recent call first\):
CMP0177-WARN\.cmake:1 \(include\)
CMakeLists\.txt:3 \(include\)
This warning is for project developers\. Use -Wno-dev to suppress it\.
@@ -0,0 +1 @@
1
@@ -0,0 +1,13 @@
CMake Error at [^
]*CMP0177-WARN-build/root-all/lib/cmake/pkg/pkg-config\.cmake:[0-9]+ \(message\):
The imported target "foo1" references the file
+ ".*/shouldNotRemain1/\.\./lib/(libfoo1\.a|foo1\.l(ib)?)"
+ but this file does not exist\. Possible reasons include:
+ \* The file was deleted, renamed, or moved to another location\.
+ \* An install or uninstall procedure did not complete successfully\.
+ \* The installation package was faulty and contained
+ ".*/Tests/RunCMake/install/CMP0177-WARN-build/root-all/lib/cmake/pkg/pkg-config\.cmake"
+ but not all the files it references\.
+Call Stack \(most recent call first\):
CMP0177-WARN-verify\.cmake:2 \(find_package\)
CMakeLists\.txt:3 \(include\)
@@ -0,0 +1,2 @@
enable_language(C)
find_package(pkg REQUIRED)
@@ -0,0 +1 @@
include(${CMAKE_CURRENT_LIST_DIR}/CMP0177.cmake)
+29
View File
@@ -0,0 +1,29 @@
enable_language(C)
add_library(foo1 STATIC obj1.c)
add_library(foo2 STATIC obj2.c)
set_target_properties(foo2 PROPERTIES HIDDEN_DOUBLE_DOT "..")
# All the shouldNotRemainX path components below should be normalized out when
# CMP0177 is set to NEW, and retained for OLD and WARN.
install(TARGETS foo1
EXPORT pkg
ARCHIVE DESTINATION shouldNotRemain1/../lib
)
install(TARGETS foo2
EXPORT pkg
ARCHIVE DESTINATION shouldNotRemain2/$<TARGET_PROPERTY:foo2,HIDDEN_DOUBLE_DOT>/lib
)
install(EXPORT pkg
DESTINATION shouldNotRemain3/deeper/../.././lib/cmake/pkg
FILE pkg-config.cmake
)
install(FILES obj1.c
DESTINATION shouldNotRemain4/anotherSubdir/../../files
)
install(DIRECTORY dir
# Trailing slash here is significant
DESTINATION shouldNotRemain5/../dirs/more/../
)
@@ -1,5 +0,0 @@
.+
set_target_properties\(pkg1::foo PROPERTIES
.+INTERFACE_INCLUDE_DIRECTORIES "\${_IMPORT_PREFIX}/pkg1/inc"
\)
.+
@@ -1,5 +0,0 @@
.+
set_target_properties\(pkg2::foo PROPERTIES
.+INTERFACE_INCLUDE_DIRECTORIES "\${_IMPORT_PREFIX}/pkg2/inc"
\)
.+
@@ -7,7 +7,9 @@ function(run_install_test case)
set(RunCMake_TEST_NO_CLEAN 1)
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
set(RunCMake_TEST_RAW_ARGS -DCMAKE_BUILD_TYPE:STRING=Debug)
run_cmake(${case})
unset(RunCMake_TEST_RAW_ARGS)
set(RunCMake_TEST_OUTPUT_MERGE 1)
run_cmake_command(${case}-build ${CMAKE_COMMAND} --build . --config Debug)
unset(RunCMake_TEST_OUTPUT_MERGE)
@@ -92,6 +94,12 @@ run_cmake(CMP0062-WARN)
run_cmake(CMP0087-OLD)
run_cmake(CMP0087-NEW)
run_cmake(CMP0087-WARN)
foreach(policy IN ITEMS NEW OLD WARN)
run_install_test(CMP0177-${policy})
run_cmake_with_options(CMP0177-${policy}-verify
-DCMAKE_PREFIX_PATH=${RunCMake_BINARY_DIR}/CMP0177-${policy}-build/root-all
)
endforeach()
run_cmake(TARGETS-ImportedGlobal)
run_cmake(TARGETS-NAMELINK_COMPONENT-bad-all)
run_cmake(TARGETS-NAMELINK_COMPONENT-bad-exc)