find_package: CPS component requirements != CMake components
Modify how CMake handles required components of a CPS transitive dependency to not pass them as COMPONENTS if a CMake-script package is found as the resolved dependency. This is necessary as many CMake-script package description files do not treat component requests as target requests (which, in CPS-land, they effectively are), but do implement logic to mark themselves 'not found' if requested components are missing. As a result, passing in the required targets as required components is likely to cause the dependency to be spuriously not found if it is only available via a CMake-script package configuration file. Fix this by introducing a new 'required targets' concept, and by passing CPS component requirements as both required targets and optional components. The latter serves as a hint for packages that might provide only a subset of themselves. The former is used to post-validate a CMake-script package, or is folded on-the-fly into required components when considering CPS packages. Note that this functionality is not exposed to the user at this time, and is only used when resolving transitive dependencies for a CPS package.
This commit is contained in:
parent
bc51d06814
commit
c3d279841b
@ -1525,6 +1525,7 @@ bool cmFindPackageCommand::HandlePackageMode(
|
|||||||
bool result = true;
|
bool result = true;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
bool configFileSetFOUNDFalse = false;
|
bool configFileSetFOUNDFalse = false;
|
||||||
|
std::vector<std::string> missingTargets;
|
||||||
|
|
||||||
if (fileFound) {
|
if (fileFound) {
|
||||||
if (this->Makefile->IsDefinitionSet(foundVar) &&
|
if (this->Makefile->IsDefinitionSet(foundVar) &&
|
||||||
@ -1559,6 +1560,17 @@ bool cmFindPackageCommand::HandlePackageMode(
|
|||||||
notFoundMessage =
|
notFoundMessage =
|
||||||
this->Makefile->GetSafeDefinition(notFoundMessageVar);
|
this->Makefile->GetSafeDefinition(notFoundMessageVar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check whether the required targets are defined.
|
||||||
|
if (found && !this->RequiredTargets.empty()) {
|
||||||
|
for (std::string const& t : this->RequiredTargets) {
|
||||||
|
std::string qualifiedTarget = cmStrCat(this->Name, "::"_s, t);
|
||||||
|
if (!this->Makefile->FindImportedTarget(qualifiedTarget)) {
|
||||||
|
missingTargets.emplace_back(std::move(qualifiedTarget));
|
||||||
|
found = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// The configuration file is invalid.
|
// The configuration file is invalid.
|
||||||
result = false;
|
result = false;
|
||||||
@ -1593,10 +1605,18 @@ bool cmFindPackageCommand::HandlePackageMode(
|
|||||||
if (!notFoundMessage.empty()) {
|
if (!notFoundMessage.empty()) {
|
||||||
e << " Reason given by package: \n" << notFoundMessage << "\n";
|
e << " Reason given by package: \n" << notFoundMessage << "\n";
|
||||||
}
|
}
|
||||||
}
|
} else if (!missingTargets.empty()) {
|
||||||
// If there are files in ConsideredConfigs, it means that FooConfig.cmake
|
e << "Found package configuration file:\n"
|
||||||
// have been found, but they didn't have appropriate versions.
|
" "
|
||||||
else if (!this->ConsideredConfigs.empty()) {
|
<< this->FileFound
|
||||||
|
<< "\n"
|
||||||
|
"but the following required targets were not found:\n"
|
||||||
|
" "
|
||||||
|
<< cmJoin(cmMakeRange(missingTargets), ", "_s);
|
||||||
|
} else if (!this->ConsideredConfigs.empty()) {
|
||||||
|
// If there are files in ConsideredConfigs, it means that
|
||||||
|
// FooConfig.cmake have been found, but they didn't have appropriate
|
||||||
|
// versions.
|
||||||
auto duplicate_end = cmRemoveDuplicates(this->ConsideredConfigs);
|
auto duplicate_end = cmRemoveDuplicates(this->ConsideredConfigs);
|
||||||
e << "Could not find a configuration file for package \"" << this->Name
|
e << "Could not find a configuration file for package \"" << this->Name
|
||||||
<< "\" that "
|
<< "\" that "
|
||||||
@ -1903,7 +1923,7 @@ bool cmFindPackageCommand::ReadPackage()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const hasComponentsRequested =
|
bool const hasComponentsRequested =
|
||||||
!this->RequiredComponents.empty() || !this->OptionalComponents.empty();
|
!this->RequiredComponents.empty() || !this->OptionalComponents.empty();
|
||||||
|
|
||||||
cmMakefile::CallRAII scope{ this->Makefile, this->FileFound, this->Status };
|
cmMakefile::CallRAII scope{ this->Makefile, this->FileFound, this->Status };
|
||||||
@ -1994,8 +2014,9 @@ bool cmFindPackageCommand::FindPackageDependencies(
|
|||||||
fp.VersionPatch, fp.VersionTweak);
|
fp.VersionPatch, fp.VersionTweak);
|
||||||
|
|
||||||
fp.Components = cmJoin(cmMakeRange(dep.Components), ";"_s);
|
fp.Components = cmJoin(cmMakeRange(dep.Components), ";"_s);
|
||||||
fp.RequiredComponents =
|
fp.OptionalComponents =
|
||||||
std::set<std::string>{ dep.Components.begin(), dep.Components.end() };
|
std::set<std::string>{ dep.Components.begin(), dep.Components.end() };
|
||||||
|
fp.RequiredTargets = fp.OptionalComponents;
|
||||||
|
|
||||||
// TODO set hints
|
// TODO set hints
|
||||||
|
|
||||||
@ -2793,10 +2814,14 @@ bool cmFindPackageCommand::CheckVersion(std::string const& config_file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify that all required components are available.
|
// Verify that all required components are available.
|
||||||
|
std::set<std::string> requiredComponents = this->RequiredComponents;
|
||||||
|
requiredComponents.insert(this->RequiredTargets.begin(),
|
||||||
|
this->RequiredTargets.end());
|
||||||
|
|
||||||
std::vector<std::string> missingComponents;
|
std::vector<std::string> missingComponents;
|
||||||
std::set_difference(this->RequiredComponents.begin(),
|
std::set_difference(requiredComponents.begin(),
|
||||||
this->RequiredComponents.end(),
|
requiredComponents.end(), allComponents.begin(),
|
||||||
allComponents.begin(), allComponents.end(),
|
allComponents.end(),
|
||||||
std::back_inserter(missingComponents));
|
std::back_inserter(missingComponents));
|
||||||
if (!missingComponents.empty()) {
|
if (!missingComponents.empty()) {
|
||||||
result = false;
|
result = false;
|
||||||
@ -2833,6 +2858,7 @@ bool cmFindPackageCommand::CheckVersion(std::string const& config_file)
|
|||||||
}
|
}
|
||||||
this->CpsReader = std::move(reader);
|
this->CpsReader = std::move(reader);
|
||||||
this->CpsAppendices = std::move(appendices);
|
this->CpsAppendices = std::move(appendices);
|
||||||
|
this->RequiredComponents = std::move(requiredComponents);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -254,6 +254,7 @@ private:
|
|||||||
std::string Components;
|
std::string Components;
|
||||||
std::set<std::string> RequiredComponents;
|
std::set<std::string> RequiredComponents;
|
||||||
std::set<std::string> OptionalComponents;
|
std::set<std::string> OptionalComponents;
|
||||||
|
std::set<std::string> RequiredTargets;
|
||||||
std::string DebugBuffer;
|
std::string DebugBuffer;
|
||||||
|
|
||||||
struct ConfigName
|
struct ConfigName
|
||||||
|
@ -1728,6 +1728,15 @@ std::string const& cmMakefile::GetCurrentBinaryDirectory() const
|
|||||||
return this->StateSnapshot.GetDirectory().GetCurrentBinary();
|
return this->StateSnapshot.GetDirectory().GetCurrentBinary();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmTarget* cmMakefile::FindImportedTarget(std::string const& name) const
|
||||||
|
{
|
||||||
|
auto const i = this->ImportedTargets.find(name);
|
||||||
|
if (i != this->ImportedTargets.end()) {
|
||||||
|
return i->second;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<cmTarget*> cmMakefile::GetImportedTargets() const
|
std::vector<cmTarget*> cmMakefile::GetImportedTargets() const
|
||||||
{
|
{
|
||||||
std::vector<cmTarget*> tgts;
|
std::vector<cmTarget*> tgts;
|
||||||
|
@ -477,6 +477,8 @@ public:
|
|||||||
}
|
}
|
||||||
std::vector<cmTarget*> GetImportedTargets() const;
|
std::vector<cmTarget*> GetImportedTargets() const;
|
||||||
|
|
||||||
|
cmTarget* FindImportedTarget(std::string const& name) const;
|
||||||
|
|
||||||
cmTarget* FindLocalNonAliasTarget(std::string const& name) const;
|
cmTarget* FindLocalNonAliasTarget(std::string const& name) const;
|
||||||
|
|
||||||
/** Find a target to use in place of the given name. The target
|
/** Find a target to use in place of the given name. The target
|
||||||
|
@ -3,8 +3,12 @@
|
|||||||
"name": "Bar",
|
"name": "Bar",
|
||||||
"cps_path": "@prefix@/cps",
|
"cps_path": "@prefix@/cps",
|
||||||
"requires": {
|
"requires": {
|
||||||
"Dep1": null,
|
"Dep1": {
|
||||||
"Dep2": null
|
"components": [ "Target" ]
|
||||||
|
},
|
||||||
|
"Dep2": {
|
||||||
|
"components": [ "Target" ]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
"Target1": {
|
"Target1": {
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
CMake Error in cps/[Tt]ransitive[Mm]issing[Cc][Mm]ake\.cps:
|
||||||
|
Found package configuration file:
|
||||||
|
(
|
||||||
|
[^
|
||||||
|
]*/Tests/RunCMake/find_package-CPS/cmake/cmaketestpackage-config.cmake)+
|
||||||
|
|
||||||
|
but the following required targets were not found:[
|
||||||
|
]+CMakeTestPackage::DoesNotExist
|
||||||
|
Call Stack \(most recent call first\):
|
||||||
|
MissingTransitiveComponentCMake\.cmake:[0-9]+ \(find_package\)
|
||||||
|
CMakeLists\.txt:[0-9]+ \(include\)
|
@ -0,0 +1,7 @@
|
|||||||
|
cmake_minimum_required(VERSION 4.0)
|
||||||
|
|
||||||
|
include(Setup.cmake)
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Test depending on components of another package which are unavailable.
|
||||||
|
find_package(TransitiveMissingCMake REQUIRED)
|
@ -0,0 +1 @@
|
|||||||
|
1
|
@ -1,4 +1,4 @@
|
|||||||
CMake Error in cps/[Tt]ransitive[Mm]issing\.cps:
|
CMake Error in cps/[Tt]ransitive[Mm]issing[Cc][Pp][Ss]\.cps:
|
||||||
Could not find a configuration file for package "ComponentTest" that is
|
Could not find a configuration file for package "ComponentTest" that is
|
||||||
compatible with requested version ""\.
|
compatible with requested version ""\.
|
||||||
|
|
||||||
@ -8,10 +8,11 @@ CMake Error in cps/[Tt]ransitive[Mm]issing\.cps:
|
|||||||
]*/Tests/RunCMake/find_package-CPS/cps/[Cc]omponent[Tt]est\.cps, version: 1\.0)+
|
]*/Tests/RunCMake/find_package-CPS/cps/[Cc]omponent[Tt]est\.cps, version: 1\.0)+
|
||||||
|
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
MissingTransitiveComponent\.cmake:[0-9]+ \(find_package\)
|
MissingTransitiveComponentCPS\.cmake:[0-9]+ \(find_package\)
|
||||||
CMakeLists\.txt:[0-9]+ \(include\)
|
CMakeLists\.txt:[0-9]+ \(include\)
|
||||||
+
|
+
|
||||||
CMake Error at MissingTransitiveComponent\.cmake:[0-9]+ \(find_package\):
|
CMake Error at MissingTransitiveComponentCPS\.cmake:[0-9]+ \(find_package\):
|
||||||
find_package could not find ComponentTest, required by TransitiveMissing\.
|
find_package could not find ComponentTest, required by
|
||||||
|
TransitiveMissingCPS\.
|
||||||
Call Stack \(most recent call first\):
|
Call Stack \(most recent call first\):
|
||||||
CMakeLists\.txt:[0-9]+ \(include\)
|
CMakeLists\.txt:[0-9]+ \(include\)
|
@ -4,4 +4,4 @@ include(Setup.cmake)
|
|||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Test depending on components of another package which are unavailable.
|
# Test depending on components of another package which are unavailable.
|
||||||
find_package(TransitiveMissing REQUIRED)
|
find_package(TransitiveMissingCPS REQUIRED)
|
@ -27,5 +27,6 @@ run_cmake(VersionLimit4)
|
|||||||
run_cmake(MissingTransitiveDependency)
|
run_cmake(MissingTransitiveDependency)
|
||||||
run_cmake(MissingComponent)
|
run_cmake(MissingComponent)
|
||||||
run_cmake(MissingComponentDependency)
|
run_cmake(MissingComponentDependency)
|
||||||
run_cmake(MissingTransitiveComponent)
|
run_cmake(MissingTransitiveComponentCPS)
|
||||||
|
run_cmake(MissingTransitiveComponentCMake)
|
||||||
run_cmake(MissingTransitiveComponentDependency)
|
run_cmake(MissingTransitiveComponentDependency)
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
# Test config file.
|
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"cps_version": "0.13",
|
||||||
|
"name": "TransitiveMissingCMake",
|
||||||
|
"cps_path": "@prefix@/cps",
|
||||||
|
"requires": {
|
||||||
|
"CMakeTestPackage": {
|
||||||
|
"components": [ "DoesNotExist" ]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"cps_version": "0.13",
|
"cps_version": "0.13",
|
||||||
"name": "TransitiveMissing",
|
"name": "TransitiveMissingCPS",
|
||||||
"cps_path": "@prefix@/cps",
|
"cps_path": "@prefix@/cps",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ComponentTest": {
|
"ComponentTest": {
|
Loading…
Reference in New Issue
Block a user