diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 7dbf6688c1..ce2f53625e 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -1525,6 +1525,7 @@ bool cmFindPackageCommand::HandlePackageMode( bool result = true; bool found = false; bool configFileSetFOUNDFalse = false; + std::vector missingTargets; if (fileFound) { if (this->Makefile->IsDefinitionSet(foundVar) && @@ -1559,6 +1560,17 @@ bool cmFindPackageCommand::HandlePackageMode( notFoundMessage = 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 { // The configuration file is invalid. result = false; @@ -1593,10 +1605,18 @@ bool cmFindPackageCommand::HandlePackageMode( if (!notFoundMessage.empty()) { e << " Reason given by package: \n" << notFoundMessage << "\n"; } - } - // If there are files in ConsideredConfigs, it means that FooConfig.cmake - // have been found, but they didn't have appropriate versions. - else if (!this->ConsideredConfigs.empty()) { + } else if (!missingTargets.empty()) { + e << "Found package configuration file:\n" + " " + << 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); e << "Could not find a configuration file for package \"" << this->Name << "\" that " @@ -1903,7 +1923,7 @@ bool cmFindPackageCommand::ReadPackage() return false; } - auto const hasComponentsRequested = + bool const hasComponentsRequested = !this->RequiredComponents.empty() || !this->OptionalComponents.empty(); cmMakefile::CallRAII scope{ this->Makefile, this->FileFound, this->Status }; @@ -1994,8 +2014,9 @@ bool cmFindPackageCommand::FindPackageDependencies( fp.VersionPatch, fp.VersionTweak); fp.Components = cmJoin(cmMakeRange(dep.Components), ";"_s); - fp.RequiredComponents = + fp.OptionalComponents = std::set{ dep.Components.begin(), dep.Components.end() }; + fp.RequiredTargets = fp.OptionalComponents; // TODO set hints @@ -2793,10 +2814,14 @@ bool cmFindPackageCommand::CheckVersion(std::string const& config_file) } // Verify that all required components are available. + std::set requiredComponents = this->RequiredComponents; + requiredComponents.insert(this->RequiredTargets.begin(), + this->RequiredTargets.end()); + std::vector missingComponents; - std::set_difference(this->RequiredComponents.begin(), - this->RequiredComponents.end(), - allComponents.begin(), allComponents.end(), + std::set_difference(requiredComponents.begin(), + requiredComponents.end(), allComponents.begin(), + allComponents.end(), std::back_inserter(missingComponents)); if (!missingComponents.empty()) { result = false; @@ -2833,6 +2858,7 @@ bool cmFindPackageCommand::CheckVersion(std::string const& config_file) } this->CpsReader = std::move(reader); this->CpsAppendices = std::move(appendices); + this->RequiredComponents = std::move(requiredComponents); } } } else { diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index 096fc07d9c..bac09ee567 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -254,6 +254,7 @@ private: std::string Components; std::set RequiredComponents; std::set OptionalComponents; + std::set RequiredTargets; std::string DebugBuffer; struct ConfigName diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 34d917c512..beca10d0e0 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1728,6 +1728,15 @@ std::string const& cmMakefile::GetCurrentBinaryDirectory() const 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 cmMakefile::GetImportedTargets() const { std::vector tgts; diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index bfc34964df..89b3c2b681 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -477,6 +477,8 @@ public: } std::vector GetImportedTargets() const; + cmTarget* FindImportedTarget(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 diff --git a/Tests/FindPackageCpsTest/cps/bar.cps b/Tests/FindPackageCpsTest/cps/bar.cps index aeeebdae7e..eb0e1d3548 100644 --- a/Tests/FindPackageCpsTest/cps/bar.cps +++ b/Tests/FindPackageCpsTest/cps/bar.cps @@ -3,8 +3,12 @@ "name": "Bar", "cps_path": "@prefix@/cps", "requires": { - "Dep1": null, - "Dep2": null + "Dep1": { + "components": [ "Target" ] + }, + "Dep2": { + "components": [ "Target" ] + } }, "components": { "Target1": { diff --git a/Tests/RunCMake/find_package-CPS/MissingTransitiveComponent-result.txt b/Tests/RunCMake/find_package-CPS/MissingTransitiveComponentCMake-result.txt similarity index 100% rename from Tests/RunCMake/find_package-CPS/MissingTransitiveComponent-result.txt rename to Tests/RunCMake/find_package-CPS/MissingTransitiveComponentCMake-result.txt diff --git a/Tests/RunCMake/find_package-CPS/MissingTransitiveComponentCMake-stderr.txt b/Tests/RunCMake/find_package-CPS/MissingTransitiveComponentCMake-stderr.txt new file mode 100644 index 0000000000..12253c1247 --- /dev/null +++ b/Tests/RunCMake/find_package-CPS/MissingTransitiveComponentCMake-stderr.txt @@ -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\) diff --git a/Tests/RunCMake/find_package-CPS/MissingTransitiveComponentCMake.cmake b/Tests/RunCMake/find_package-CPS/MissingTransitiveComponentCMake.cmake new file mode 100644 index 0000000000..459bf942b3 --- /dev/null +++ b/Tests/RunCMake/find_package-CPS/MissingTransitiveComponentCMake.cmake @@ -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) diff --git a/Tests/RunCMake/find_package-CPS/MissingTransitiveComponentCPS-result.txt b/Tests/RunCMake/find_package-CPS/MissingTransitiveComponentCPS-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/find_package-CPS/MissingTransitiveComponentCPS-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_package-CPS/MissingTransitiveComponent-stderr.txt b/Tests/RunCMake/find_package-CPS/MissingTransitiveComponentCPS-stderr.txt similarity index 60% rename from Tests/RunCMake/find_package-CPS/MissingTransitiveComponent-stderr.txt rename to Tests/RunCMake/find_package-CPS/MissingTransitiveComponentCPS-stderr.txt index 50c4afe19b..1a2b9e8485 100644 --- a/Tests/RunCMake/find_package-CPS/MissingTransitiveComponent-stderr.txt +++ b/Tests/RunCMake/find_package-CPS/MissingTransitiveComponentCPS-stderr.txt @@ -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 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)+ Call Stack \(most recent call first\): - MissingTransitiveComponent\.cmake:[0-9]+ \(find_package\) + MissingTransitiveComponentCPS\.cmake:[0-9]+ \(find_package\) CMakeLists\.txt:[0-9]+ \(include\) + -CMake Error at MissingTransitiveComponent\.cmake:[0-9]+ \(find_package\): - find_package could not find ComponentTest, required by TransitiveMissing\. +CMake Error at MissingTransitiveComponentCPS\.cmake:[0-9]+ \(find_package\): + find_package could not find ComponentTest, required by + TransitiveMissingCPS\. Call Stack \(most recent call first\): CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_package-CPS/MissingTransitiveComponent.cmake b/Tests/RunCMake/find_package-CPS/MissingTransitiveComponentCPS.cmake similarity index 82% rename from Tests/RunCMake/find_package-CPS/MissingTransitiveComponent.cmake rename to Tests/RunCMake/find_package-CPS/MissingTransitiveComponentCPS.cmake index e6951a9c57..feca4f796d 100644 --- a/Tests/RunCMake/find_package-CPS/MissingTransitiveComponent.cmake +++ b/Tests/RunCMake/find_package-CPS/MissingTransitiveComponentCPS.cmake @@ -4,4 +4,4 @@ include(Setup.cmake) ############################################################################### # Test depending on components of another package which are unavailable. -find_package(TransitiveMissing REQUIRED) +find_package(TransitiveMissingCPS REQUIRED) diff --git a/Tests/RunCMake/find_package-CPS/RunCMakeTest.cmake b/Tests/RunCMake/find_package-CPS/RunCMakeTest.cmake index 8df4f6008f..c77bed5b51 100644 --- a/Tests/RunCMake/find_package-CPS/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_package-CPS/RunCMakeTest.cmake @@ -27,5 +27,6 @@ run_cmake(VersionLimit4) run_cmake(MissingTransitiveDependency) run_cmake(MissingComponent) run_cmake(MissingComponentDependency) -run_cmake(MissingTransitiveComponent) +run_cmake(MissingTransitiveComponentCPS) +run_cmake(MissingTransitiveComponentCMake) run_cmake(MissingTransitiveComponentDependency) diff --git a/Tests/RunCMake/find_package-CPS/cmake/cmaketestpackage-config.cmake b/Tests/RunCMake/find_package-CPS/cmake/cmaketestpackage-config.cmake new file mode 100644 index 0000000000..deffa57294 --- /dev/null +++ b/Tests/RunCMake/find_package-CPS/cmake/cmaketestpackage-config.cmake @@ -0,0 +1 @@ +# Test config file. diff --git a/Tests/RunCMake/find_package-CPS/cps/transitivemissingcmake.cps b/Tests/RunCMake/find_package-CPS/cps/transitivemissingcmake.cps new file mode 100644 index 0000000000..f24a25b9ea --- /dev/null +++ b/Tests/RunCMake/find_package-CPS/cps/transitivemissingcmake.cps @@ -0,0 +1,11 @@ +{ + "cps_version": "0.13", + "name": "TransitiveMissingCMake", + "cps_path": "@prefix@/cps", + "requires": { + "CMakeTestPackage": { + "components": [ "DoesNotExist" ] + } + }, + "components": {} +} diff --git a/Tests/RunCMake/find_package-CPS/cps/transitivemissing.cps b/Tests/RunCMake/find_package-CPS/cps/transitivemissingcps.cps similarity index 83% rename from Tests/RunCMake/find_package-CPS/cps/transitivemissing.cps rename to Tests/RunCMake/find_package-CPS/cps/transitivemissingcps.cps index 2a294aa108..199aeeb58c 100644 --- a/Tests/RunCMake/find_package-CPS/cps/transitivemissing.cps +++ b/Tests/RunCMake/find_package-CPS/cps/transitivemissingcps.cps @@ -1,6 +1,6 @@ { "cps_version": "0.13", - "name": "TransitiveMissing", + "name": "TransitiveMissingCPS", "cps_path": "@prefix@/cps", "requires": { "ComponentTest": {