export: Add build-tree CPS support

Add Common Package Specification support to export(EXPORT).
This commit is contained in:
Matthew Woehlke 2025-02-25 15:42:23 -05:00
parent 4577e06d91
commit c8ccd5a9e3
91 changed files with 1032 additions and 28 deletions

View File

@ -89,10 +89,10 @@ Exporting Targets to Android.mk
.. versionadded:: 3.7
This signature exports cmake built targets to the android ndk build system
This signature exports CMake built targets to the android ndk build system
by creating an ``Android.mk`` file that references the prebuilt targets. The
Android NDK supports the use of prebuilt libraries, both static and shared.
This allows cmake to build the libraries of a project and make them available
This allows CMake to build the libraries of a project and make them available
to an ndk build system complete with transitive dependencies, include flags
and defines required to use the libraries. The signature takes a list of
targets and puts them in the ``Android.mk`` file specified by the
@ -127,6 +127,36 @@ of the :command:`install(TARGETS)` command.
Specify that :command:`find_dependency` calls should be exported. See
:command:`install(EXPORT)` for details on how this works.
Exporting Targets to the |CPS|
""""""""""""""""""""""""""""""
.. code-block:: cmake
export(EXPORT <export-name> PACKAGE_INFO <package-name>
[APPENDIX <appendix-name>]
[LOWER_CASE_FILE]
[VERSION <version>
[COMPAT_VERSION <version>]
[VERSION_SCHEMA <string>]]
[DEFAULT_TARGETS <target>...]
[DEFAULT_CONFIGURATIONS <config>...])
.. versionadded:: 4.1
.. note::
Experimental. Gated by ``CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO``.
Creates a file in the |CPS|_ that may be included by outside projects to import
targets named by ``<target>...`` from the current project's build tree. See
the :command:`install(PACKAGE_INFO)` command to export targets from an install
tree. The imported targets are implicitly in the namespace ``<package-name>``.
The default file name is ``<package-name>[-<appendix-name>].cps``. If the
``LOWER_CASE_FILE`` option is given, the file name will use the package name
converted to lower case.
See :command:`install(PACKAGE_INFO)` for a description of the other options.
Exporting Packages
^^^^^^^^^^^^^^^^^^
@ -221,3 +251,6 @@ Configure the parameters of an export. The arguments are as follows:
this target. If specified, the generated code will check to see if the
``.xcframework`` exists, and if it does, it will use the ``.xcframework``
as its imported location instead of the installed library.
.. _CPS: https://cps-org.github.io/cps/
.. |CPS| replace:: Common Package Specification

View File

@ -203,6 +203,8 @@ add_library(
cmExportBuildCMakeConfigGenerator.cxx
cmExportBuildFileGenerator.h
cmExportBuildFileGenerator.cxx
cmExportBuildPackageInfoGenerator.h
cmExportBuildPackageInfoGenerator.cxx
cmExportCMakeConfigGenerator.h
cmExportCMakeConfigGenerator.cxx
cmExportFileGenerator.h

View File

@ -0,0 +1,119 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmExportBuildPackageInfoGenerator.h"
#include <cassert>
#include <utility>
#include <vector>
#include <cmext/string_view>
#include <cm3p/json/value.h>
#include "cmGeneratorExpression.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
cmExportBuildPackageInfoGenerator::cmExportBuildPackageInfoGenerator(
std::string packageName, std::string version, std::string versionCompat,
std::string versionSchema, std::vector<std::string> defaultTargets,
std::vector<std::string> defaultConfigurations)
: cmExportPackageInfoGenerator(
std::move(packageName), std::move(version), std::move(versionCompat),
std::move(versionSchema), std::move(defaultTargets),
std::move(defaultConfigurations))
{
this->SetNamespace(cmStrCat(this->GetPackageName(), "::"_s));
}
bool cmExportBuildPackageInfoGenerator::GenerateMainFile(std::ostream& os)
{
if (!this->CollectExports([&](cmGeneratorTarget const*) {})) {
return false;
}
if (!this->CheckDefaultTargets()) {
return false;
}
Json::Value root = this->GeneratePackageInfo();
root["cps_path"] = "@prefix@";
Json::Value& components = root["components"];
// Create all the imported targets.
for (auto const& exp : this->Exports) {
cmGeneratorTarget* const target = exp.Target;
cmStateEnums::TargetType targetType = this->GetExportTargetType(target);
Json::Value* const component =
this->GenerateImportTarget(components, target, targetType);
if (!component) {
return false;
}
ImportPropertyMap properties;
if (!this->PopulateInterfaceProperties(target, properties)) {
return false;
}
this->PopulateInterfaceLinkLibrariesProperty(
target, cmGeneratorExpression::InstallInterface, properties);
if (targetType != cmStateEnums::INTERFACE_LIBRARY) {
auto configurations = Json::Value{ Json::objectValue };
// Add per-configuration properties.
for (std::string const& c : this->Configurations) {
this->GenerateInterfacePropertiesConfig(configurations, target, c);
}
if (!configurations.empty()) {
(*component)["configurations"] = configurations;
}
}
// Set configuration-agnostic properties for component.
this->GenerateInterfaceProperties(*component, target, properties);
}
this->GeneratePackageRequires(root);
// Write the primary packing information file.
this->WritePackageInfo(root, os);
bool result = true;
return result;
}
void cmExportBuildPackageInfoGenerator::GenerateInterfacePropertiesConfig(
Json::Value& configurations, cmGeneratorTarget* target,
std::string const& config)
{
std::string const& suffix = PropertyConfigSuffix(config);
ImportPropertyMap properties;
assert(this->GetExportTargetType(target) != cmStateEnums::INTERFACE_LIBRARY);
this->SetImportLocationProperty(config, suffix, target, properties);
if (properties.empty()) {
return;
}
this->SetImportDetailProperties(config, suffix, target, properties);
// TODO: PUBLIC_HEADER_LOCATION
Json::Value component =
this->GenerateInterfaceConfigProperties(suffix, properties);
if (!component.empty()) {
configurations[config] = std::move(component);
}
}
std::string cmExportBuildPackageInfoGenerator::GetCxxModulesDirectory() const
{
// TODO: Implement a not-CMake-specific mechanism for providing module
// information.
return {};
}

View File

@ -0,0 +1,53 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
#include <string>
#include <vector>
#include "cmExportBuildFileGenerator.h"
#include "cmExportPackageInfoGenerator.h"
namespace Json {
class Value;
}
class cmGeneratorTarget;
/** \class cmExportBuildPackageInfoGenerator
* \brief Generate a file exporting targets from a build tree.
*
* cmExportBuildCMakeConfigGenerator generates a file exporting targets from
* a build tree. This exports the targets to the Common Package Specification
* (https://cps-org.github.io/cps/).
*
* This is used to implement the export() command.
*/
class cmExportBuildPackageInfoGenerator
: public cmExportBuildFileGenerator
, public cmExportPackageInfoGenerator
{
public:
cmExportBuildPackageInfoGenerator(
std::string packageName, std::string version, std::string versionCompat,
std::string versionSchema, std::vector<std::string> defaultTargets,
std::vector<std::string> defaultConfigurations);
protected:
// Implement virtual methods from the superclass.
bool GenerateMainFile(std::ostream& os) override;
void GenerateImportTargetsConfig(std::ostream&, std::string const&,
std::string const&) override
{
}
void GenerateInterfacePropertiesConfig(Json::Value& configurations,
cmGeneratorTarget* target,
std::string const& config);
std::string GetCxxModulesDirectory() const override;
// TODO: Generate C++ module info in a not-CMake-specific format.
};

View File

@ -21,8 +21,10 @@
#include "cmExportBuildAndroidMKGenerator.h"
#include "cmExportBuildCMakeConfigGenerator.h"
#include "cmExportBuildFileGenerator.h"
#include "cmExportBuildPackageInfoGenerator.h"
#include "cmExportSet.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
@ -68,9 +70,17 @@ bool cmExportCommand(std::vector<std::string> const& args,
ArgumentParser::NonEmpty<std::string> Namespace;
ArgumentParser::NonEmpty<std::string> Filename;
ArgumentParser::NonEmpty<std::string> AndroidMKFile;
ArgumentParser::NonEmpty<std::string> PackageName;
ArgumentParser::NonEmpty<std::string> Appendix;
ArgumentParser::NonEmpty<std::string> Version;
ArgumentParser::NonEmpty<std::string> VersionCompat;
ArgumentParser::NonEmpty<std::string> VersionSchema;
ArgumentParser::NonEmpty<std::string> CxxModulesDirectory;
ArgumentParser::NonEmpty<std::vector<std::string>> DefaultTargets;
ArgumentParser::NonEmpty<std::vector<std::string>> DefaultConfigs;
bool Append = false;
bool ExportOld = false;
bool LowerCase = false;
std::vector<std::vector<std::string>> PackageDependencyArgs;
bool ExportPackageDependencies = false;
@ -92,6 +102,17 @@ bool cmExportCommand(std::vector<std::string> const& args,
parser.Bind("EXPORT_PACKAGE_DEPENDENCIES"_s,
&Arguments::ExportPackageDependencies);
}
if (cmExperimental::HasSupportEnabled(
status.GetMakefile(), cmExperimental::Feature::ExportPackageInfo)) {
parser.Bind("PACKAGE_INFO"_s, &Arguments::PackageName);
parser.Bind("LOWER_CASE_FILE"_s, &Arguments::LowerCase);
parser.Bind("APPENDIX"_s, &Arguments::Appendix);
parser.Bind("VERSION"_s, &Arguments::Version);
parser.Bind("COMPAT_VERSION"_s, &Arguments::VersionCompat);
parser.Bind("VERSION_SCHEMA"_s, &Arguments::VersionSchema);
parser.Bind("DEFAULT_TARGETS"_s, &Arguments::DefaultTargets);
parser.Bind("DEFAULT_CONFIGURATIONS"_s, &Arguments::DefaultConfigs);
}
} else if (args[0] == "SETUP") {
parser.Bind("SETUP"_s, &Arguments::ExportSetName);
if (cmExperimental::HasSupportEnabled(
@ -200,19 +221,98 @@ bool cmExportCommand(std::vector<std::string> const& args,
return true;
}
if (arguments.PackageName.empty()) {
if (arguments.LowerCase) {
status.SetError("LOWER_CASE_FILE requires PACKAGE_INFO.");
return false;
}
if (!arguments.Appendix.empty()) {
status.SetError("APPENDIX requires PACKAGE_INFO.");
return false;
}
if (!arguments.Version.empty()) {
status.SetError("VERSION requires PACKAGE_INFO.");
return false;
}
if (!arguments.DefaultTargets.empty()) {
status.SetError("DEFAULT_TARGETS requires PACKAGE_INFO.");
return false;
}
if (!arguments.DefaultConfigs.empty()) {
status.SetError("DEFAULT_CONFIGURATIONS requires PACKAGE_INFO.");
return false;
}
} else {
if (!arguments.Filename.empty()) {
status.SetError("PACKAGE_INFO and FILE are mutually exclusive.");
return false;
}
if (!arguments.Namespace.empty()) {
status.SetError("PACKAGE_INFO and NAMESPACE are mutually exclusive.");
return false;
}
if (!arguments.Appendix.empty()) {
if (!arguments.Version.empty()) {
status.SetError("APPENDIX and VERSION are mutually exclusive.");
return false;
}
if (!arguments.DefaultTargets.empty()) {
status.SetError("APPENDIX and DEFAULT_TARGETS "
"are mutually exclusive.");
return false;
}
if (!arguments.DefaultConfigs.empty()) {
status.SetError("APPENDIX and DEFAULT_CONFIGURATIONS "
"are mutually exclusive.");
return false;
}
}
}
if (arguments.Version.empty()) {
if (!arguments.VersionCompat.empty()) {
status.SetError("COMPAT_VERSION requires VERSION.");
return false;
}
if (!arguments.VersionSchema.empty()) {
status.SetError("VERSION_SCHEMA requires VERSION.");
return false;
}
}
std::string fname;
bool android = false;
bool cps = false;
if (!arguments.AndroidMKFile.empty()) {
fname = arguments.AndroidMKFile;
android = true;
}
if (arguments.Filename.empty() && fname.empty()) {
} else if (arguments.Filename.empty()) {
if (args[0] != "EXPORT") {
status.SetError("FILE <filename> option missing.");
return false;
}
fname = arguments.ExportSetName + ".cmake";
} else if (fname.empty()) {
if (arguments.PackageName.empty()) {
fname = arguments.ExportSetName + ".cmake";
} else {
// Validate the package name.
if (!cmGeneratorExpression::IsValidTargetName(arguments.PackageName) ||
arguments.PackageName.find(':') != std::string::npos) {
status.SetError(
cmStrCat(R"(PACKAGE_INFO given invalid package name ")"_s,
arguments.PackageName, R"(".)"_s));
return false;
}
std::string const pkgNameOnDisk =
(arguments.LowerCase ? cmSystemTools::LowerCase(arguments.PackageName)
: std::string{ arguments.PackageName });
if (arguments.Appendix.empty()) {
fname = cmStrCat(pkgNameOnDisk, ".cps"_s);
} else {
fname = cmStrCat(pkgNameOnDisk, '-', arguments.Appendix, ".cps"_s);
}
cps = true;
}
} else {
// Make sure the file has a .cmake extension.
if (cmSystemTools::GetFilenameLastExtension(arguments.Filename) !=
".cmake") {
@ -298,6 +398,11 @@ bool cmExportCommand(std::vector<std::string> const& args,
// and APPEND is not specified, if CMP0103 is OLD ignore previous definition
// else raise an error
if (gg->GetExportedTargetsFile(fname)) {
if (cps) {
status.SetError(cmStrCat("command already specified for the file "_s,
cmSystemTools::GetFilenameName(fname), '.'));
return false;
}
switch (mf.GetPolicyStatus(cmPolicies::CMP0103)) {
case cmPolicies::WARN:
mf.IssueMessage(
@ -316,21 +421,28 @@ bool cmExportCommand(std::vector<std::string> const& args,
}
}
// Setup export file generation.
// Set up export file generation.
std::unique_ptr<cmExportBuildFileGenerator> ebfg = nullptr;
if (android) {
auto ebag = cm::make_unique<cmExportBuildAndroidMKGenerator>();
ebag->SetNamespace(arguments.Namespace);
ebag->SetAppendMode(arguments.Append);
ebfg = std::move(ebag);
} else if (cps) {
auto ebpg = cm::make_unique<cmExportBuildPackageInfoGenerator>(
arguments.PackageName, arguments.Version, arguments.VersionCompat,
arguments.VersionSchema, arguments.DefaultTargets,
arguments.DefaultConfigs);
ebfg = std::move(ebpg);
} else {
auto ebcg = cm::make_unique<cmExportBuildCMakeConfigGenerator>();
ebcg->SetNamespace(arguments.Namespace);
ebcg->SetAppendMode(arguments.Append);
ebcg->SetExportOld(arguments.ExportOld);
ebcg->SetExportPackageDependencies(arguments.ExportPackageDependencies);
ebfg = std::move(ebcg);
}
ebfg->SetExportFile(fname.c_str());
ebfg->SetNamespace(arguments.Namespace);
ebfg->SetCxxModuleDirectory(arguments.CxxModulesDirectory);
if (exportSet) {
ebfg->SetExportSet(exportSet);

View File

@ -78,19 +78,21 @@ bool cmExportFileGenerator::GenerateImportFile()
return this->GenerateImportFile(*foutPtr);
}
std::string cmExportFileGenerator::PropertyConfigSuffix(
std::string const& config)
{
// Construct the property configuration suffix.
if (config.empty()) {
return "_NOCONFIG";
}
return cmStrCat('_', cmSystemTools::UpperCase(config));
}
void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
std::string const& config)
{
// Construct the property configuration suffix.
std::string suffix = "_";
if (!config.empty()) {
suffix += cmSystemTools::UpperCase(config);
} else {
suffix += "NOCONFIG";
}
// Generate the per-config target information.
this->GenerateImportTargetsConfig(os, config, suffix);
this->GenerateImportTargetsConfig(os, config, PropertyConfigSuffix(config));
}
bool cmExportFileGenerator::PopulateInterfaceProperties(

View File

@ -170,6 +170,8 @@ protected:
bool AddTargetNamespace(std::string& input, cmGeneratorTarget const* target,
cmLocalGenerator const* lg);
static std::string PropertyConfigSuffix(std::string const& config);
// The namespace in which the exports are placed in the generated file.
std::string Namespace;

View File

@ -71,8 +71,8 @@ bool cmExportInstallPackageInfoGenerator::GenerateMainFile(std::ostream& os)
}
root["cps_path"] = packagePath;
bool requiresConfigFiles = false;
// Create all the imported targets.
bool requiresConfigFiles = false;
for (cmTargetExport const* te : allTargets) {
cmGeneratorTarget* gt = te->Target;
cmStateEnums::TargetType targetType = this->GetExportTargetType(te);
@ -139,8 +139,11 @@ void cmExportInstallPackageInfoGenerator::GenerateImportTargetsConfig(
this->PopulateImportProperties(config, suffix, te.get(), properties,
importedLocations);
this->GenerateInterfaceConfigProperties(components, te->Target, suffix,
properties);
Json::Value component =
this->GenerateInterfaceConfigProperties(suffix, properties);
if (!component.empty()) {
components[te->Target->GetExportName()] = std::move(component);
}
}
this->WritePackageInfo(root, os);

View File

@ -277,7 +277,7 @@ bool cmExportPackageInfoGenerator::NoteLinkedTarget(
return true;
}
// Target belongs to multiple namespaces or multiple export sets.
// Target belongs to another export from this build.
auto const& exportInfo = this->FindExportInfo(linkedTarget);
if (exportInfo.Namespaces.size() == 1 && exportInfo.Sets.size() == 1) {
auto const& linkNamespace = *exportInfo.Namespaces.begin();
@ -302,6 +302,7 @@ bool cmExportPackageInfoGenerator::NoteLinkedTarget(
return true;
}
// Target belongs to multiple namespaces or multiple export sets.
// cmExportFileGenerator::HandleMissingTarget should have complained about
// this already.
return false;
@ -424,8 +425,7 @@ void cmExportPackageInfoGenerator::GenerateInterfaceListProperty(
}
}
void cmExportPackageInfoGenerator::GenerateInterfaceConfigProperties(
Json::Value& components, cmGeneratorTarget const* target,
Json::Value cmExportPackageInfoGenerator::GenerateInterfaceConfigProperties(
std::string const& suffix, ImportPropertyMap const& properties) const
{
Json::Value component;
@ -456,7 +456,5 @@ void cmExportPackageInfoGenerator::GenerateInterfaceConfigProperties(
}
}
if (!component.empty()) {
components[target->GetExportName()] = component;
}
return component;
}

View File

@ -62,8 +62,7 @@ protected:
bool GenerateInterfaceProperties(Json::Value& component,
cmGeneratorTarget const* target,
ImportPropertyMap const& properties) const;
void GenerateInterfaceConfigProperties(
Json::Value& components, cmGeneratorTarget const* target,
Json::Value GenerateInterfaceConfigProperties(
std::string const& suffix, ImportPropertyMap const& properties) const;
cm::string_view GetImportPrefixWithSlash() const override;

View File

@ -397,6 +397,7 @@ set_property(TEST RunCMake.CompilerId APPEND PROPERTY LABELS "CUDA" "HIP" "ISPC"
add_RunCMake_test(CompilerTest ${CMake_TEST_LANG_VARS})
set_property(TEST RunCMake.CompilerTest APPEND PROPERTY LABELS "CUDA" "HIP" "ISPC" "Fortran")
add_RunCMake_test(Configure -DMSVC_IDE=${MSVC_IDE})
add_RunCMake_test(CpsExportImportBuild)
add_RunCMake_test(CpsExportImportInstall)
add_RunCMake_test(DisallowedCommands)
if("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja")
@ -1205,6 +1206,7 @@ add_RunCMake_test(AutoExportDll
)
add_RunCMake_test(AndroidMK)
add_RunCMake_test(ExportPackageInfo)
add_RunCMake_test(InstallPackageInfo)
if(CMake_TEST_ANDROID_NDK OR CMake_TEST_ANDROID_STANDALONE_TOOLCHAIN)

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 4.0.20250220)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1,23 @@
include(RunCMake)
set(RunCMake_TEST_OPTIONS
-Wno-dev
"-DCMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO:STRING=b80be207-778e-46ba-8080-b23bba22639e"
"-DCMAKE_EXPERIMENTAL_FIND_CPS_PACKAGES:STRING=e82e467b-f997-4464-8ace-b00808fff261"
)
function(build_project test)
set(RunCMake_TEST_NO_CLEAN FALSE)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
list(APPEND RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
endif()
run_cmake(${test})
set(RunCMake_TEST_NO_CLEAN TRUE)
run_cmake_command(${test}-build ${CMAKE_COMMAND} --build . --config Release)
endfunction()
build_project(TestLibrary)
build_project(TestExecutable)

View File

@ -0,0 +1,12 @@
project(TestLibrary C)
set(liba_DIR "${CMAKE_BINARY_DIR}/../TestLibrary-build")
set(libb_DIR "${CMAKE_BINARY_DIR}/../TestLibrary-build")
find_package(libb REQUIRED COMPONENTS libb)
add_executable(app app.c)
target_link_libraries(app PUBLIC libb::libb)
install(TARGETS app DESTINATION bin)

View File

@ -0,0 +1,12 @@
project(TestLibrary C)
add_library(liba SHARED liba.c)
add_library(libb SHARED libb.c)
target_link_libraries(libb PUBLIC liba)
install(TARGETS liba EXPORT liba DESTINATION lib)
export(EXPORT liba PACKAGE_INFO liba)
install(TARGETS libb EXPORT libb DESTINATION lib)
export(EXPORT libb PACKAGE_INFO libb)

View File

@ -0,0 +1,13 @@
#include <stdio.h>
extern
#ifdef _WIN32
__declspec(dllimport)
#endif
int ask(void);
int main(void)
{
printf("%i\n", ask());
return 0;
}

View File

@ -0,0 +1,7 @@
#ifdef _WIN32
__declspec(dllexport)
#endif
int answer(void)
{
return 42;
}

View File

@ -0,0 +1,13 @@
extern
#ifdef _WIN32
__declspec(dllimport)
#endif
int answer(void);
#ifdef _WIN32
__declspec(dllexport)
#endif
int ask(void)
{
return answer();
}

View File

@ -0,0 +1,16 @@
include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake)
set(out_dir "${RunCMake_BINARY_DIR}/Appendix-build")
file(READ "${out_dir}/foo.cps" content)
expect_value("${content}" "foo" "name")
expect_value("${content}" "interface" "components" "mammal" "type")
expect_value("${content}" "1.0" "version")
file(READ "${out_dir}/foo-dog.cps" content)
expect_value("${content}" "foo" "name")
expect_value("${content}" "interface" "components" "canine" "type")
expect_missing("${content}" "version")
expect_array("${content}" 1 "components" "canine" "requires")
expect_value("${content}" ":mammal" "components" "canine" "requires" 0)

View File

@ -0,0 +1,9 @@
add_library(mammal INTERFACE)
add_library(canine INTERFACE)
target_link_libraries(canine INTERFACE mammal)
install(TARGETS mammal EXPORT mammal DESTINATION .)
install(TARGETS canine EXPORT canine DESTINATION .)
export(EXPORT mammal PACKAGE_INFO foo VERSION 1.0)
export(EXPORT canine PACKAGE_INFO foo APPENDIX dog)

View File

@ -0,0 +1,34 @@
macro(_expect entity op actual expected)
if(NOT "${actual}" ${op} "${expected}")
list(JOIN ARGN "." name)
set(RunCMake_TEST_FAILED
"Attribute '${name}' ${entity} '${actual}' does not match expected ${entity} '${expected}'" PARENT_SCOPE)
return()
endif()
endmacro()
function(expect_value content expected_value)
string(JSON actual_value GET "${content}" ${ARGN})
_expect("value" STREQUAL "${actual_value}" "${expected_value}" ${ARGN})
endfunction()
function(expect_array content expected_length)
string(JSON actual_type TYPE "${content}" ${ARGN})
_expect("type" STREQUAL "${actual_type}" "ARRAY" ${ARGN})
string(JSON actual_length LENGTH "${content}" ${ARGN})
_expect("length" EQUAL "${actual_length}" "${expected_length}" ${ARGN})
endfunction()
function(expect_null content)
string(JSON actual_type TYPE "${content}" ${ARGN})
_expect("type" STREQUAL "${actual_type}" "NULL" ${ARGN})
endfunction()
function(expect_missing content)
string(JSON value ERROR_VARIABLE error GET "${content}" ${ARGN})
if(NOT value MATCHES "^(.*-)?NOTFOUND$")
set(RunCMake_TEST_FAILED
"Attribute '${ARGN}' is unexpectedly present" PARENT_SCOPE)
endif()
endfunction()

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,10 @@
CMake Error at BadArgs1\.cmake:3 \(export\):
export COMPAT_VERSION requires VERSION\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs1\.cmake:4 \(export\):
export VERSION_SCHEMA requires VERSION\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)

View File

@ -0,0 +1,4 @@
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo DESTINATION .)
export(EXPORT foo PACKAGE_INFO foo COMPAT_VERSION 1.0)
export(EXPORT foo PACKAGE_INFO foo VERSION_SCHEMA simple)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,16 @@
CMake Error at BadArgs2\.cmake:3 \(export\):
export APPENDIX and VERSION are mutually exclusive\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs2\.cmake:4 \(export\):
export APPENDIX and DEFAULT_TARGETS are mutually exclusive\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs2\.cmake:5 \(export\):
export APPENDIX and DEFAULT_CONFIGURATIONS are mutually exclusive\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)

View File

@ -0,0 +1,5 @@
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo DESTINATION .)
export(EXPORT foo PACKAGE_INFO foo APPENDIX test VERSION 1.0)
export(EXPORT foo PACKAGE_INFO foo APPENDIX test DEFAULT_TARGETS foo)
export(EXPORT foo PACKAGE_INFO foo APPENDIX test DEFAULT_CONFIGURATIONS Release)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,10 @@
CMake Error at BadArgs3\.cmake:3 \(export\):
export PACKAGE_INFO and FILE are mutually exclusive\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs3\.cmake:4 \(export\):
export PACKAGE_INFO and NAMESPACE are mutually exclusive\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)

View File

@ -0,0 +1,4 @@
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo DESTINATION .)
export(EXPORT foo PACKAGE_INFO foo FILE foo.cps)
export(EXPORT foo PACKAGE_INFO foo NAMESPACE foo::)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,28 @@
CMake Error at BadArgs4\.cmake:3 \(export\):
export LOWER_CASE_FILE requires PACKAGE_INFO\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs4\.cmake:4 \(export\):
export APPENDIX requires PACKAGE_INFO\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs4\.cmake:5 \(export\):
export VERSION requires PACKAGE_INFO\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs4\.cmake:6 \(export\):
export DEFAULT_TARGETS requires PACKAGE_INFO\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)
CMake Error at BadArgs4\.cmake:7 \(export\):
export DEFAULT_CONFIGURATIONS requires PACKAGE_INFO\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)

View File

@ -0,0 +1,7 @@
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo DESTINATION .)
export(EXPORT foo LOWER_CASE_FILE)
export(EXPORT foo APPENDIX test)
export(EXPORT foo VERSION 1.0)
export(EXPORT foo DEFAULT_TARGETS foo)
export(EXPORT foo DEFAULT_CONFIGURATIONS Release)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,8 @@
CMake Error in CMakeLists.txt:
Package "test" specifies DEFAULT_TARGETS "dog", which is not a target in
the export set "foo".
CMake Error in CMakeLists.txt:
Package "test" specifies DEFAULT_TARGETS "cat", which is not a target in
the export set "foo".

View File

@ -0,0 +1,5 @@
add_library(foo INTERFACE)
add_library(dog INTERFACE)
install(TARGETS foo EXPORT foo DESTINATION .)
install(TARGETS dog EXPORT dog DESTINATION .)
export(EXPORT foo PACKAGE_INFO test DEFAULT_TARGETS dog cat)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,4 @@
CMake Error at BadName\.cmake:3 \(export\):
export PACKAGE_INFO given invalid package name "%foo"\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)

View File

@ -0,0 +1,3 @@
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo DESTINATION .)
export(EXPORT foo PACKAGE_INFO "%foo")

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 4.0.20240220)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1,3 @@
project(DependsMultiple CXX)
set(NAMESPACE foo::)
include(DependsMultipleCommon.cmake)

View File

@ -0,0 +1,11 @@
add_library(foo foo.cxx)
add_library(bar foo.cxx)
target_link_libraries(bar foo)
install(TARGETS foo EXPORT foo)
export(EXPORT foo NAMESPACE ${NAMESPACE})
export(EXPORT foo PACKAGE_INFO foo)
install(TARGETS bar EXPORT bar)
export(EXPORT bar)
export(EXPORT bar PACKAGE_INFO bar)

View File

@ -0,0 +1,22 @@
CMake Error in CMakeLists\.txt:
export called with target "bar" which requires target "foo" that is not in
this export set, but in another export set which is exported multiple times
with different namespaces:.*
.*/Tests/RunCMake/ExportPackageInfo/DependsMultipleDifferentNamespace-build/foo\.cmake,.*
.*/Tests/RunCMake/ExportPackageInfo/DependsMultipleDifferentNamespace-build/foo\.cps\.
An exported target cannot depend upon another target which is exported in
more than one export set or with more than one namespace\. Consider
consolidating the exports of the "foo" target to a single export\.
CMake Error in CMakeLists\.txt:
export called with target "bar" which requires target "foo" that is not in
this export set, but in another export set which is exported multiple times
with different namespaces:.*
.*/Tests/RunCMake/ExportPackageInfo/DependsMultipleDifferentNamespace-build/foo\.cmake,.*
.*/Tests/RunCMake/ExportPackageInfo/DependsMultipleDifferentNamespace-build/foo\.cps\.
An exported target cannot depend upon another target which is exported in
more than one export set or with more than one namespace\. Consider
consolidating the exports of the "foo" target to a single export\.

View File

@ -0,0 +1,3 @@
project(DependsMultipleDifferentNamespace CXX)
set(NAMESPACE "")
include(DependsMultipleCommon.cmake)

View File

@ -0,0 +1,22 @@
CMake Error in CMakeLists\.txt:
export called with target "bar" which requires target "foo" that is not in
this export set, but in multiple other export sets:.*
.*/Tests/RunCMake/ExportPackageInfo/DependsMultipleDifferentSets-build/foo-alt\.cmake,.*
.*/Tests/RunCMake/ExportPackageInfo/DependsMultipleDifferentSets-build/foo\.cmake,.*
.*/Tests/RunCMake/ExportPackageInfo/DependsMultipleDifferentSets-build/foo\.cps\.
An exported target cannot depend upon another target which is exported in
more than one export set or with more than one namespace\. Consider
consolidating the exports of the "foo" target to a single export\.
CMake Error in CMakeLists\.txt:
export called with target "bar" which requires target "foo" that is not in
this export set, but in multiple other export sets:.*
.*/Tests/RunCMake/ExportPackageInfo/DependsMultipleDifferentSets-build/foo-alt\.cmake,.*
.*/Tests/RunCMake/ExportPackageInfo/DependsMultipleDifferentSets-build/foo\.cmake,.*
.*/Tests/RunCMake/ExportPackageInfo/DependsMultipleDifferentSets-build/foo\.cps\.
An exported target cannot depend upon another target which is exported in
more than one export set or with more than one namespace\. Consider
consolidating the exports of the "foo" target to a single export\.

View File

@ -0,0 +1,5 @@
project(DependsMultipleDifferentSets CXX)
include(DependsMultipleCommon.cmake)
install(TARGETS foo EXPORT foo-alt)
export(EXPORT foo-alt)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,4 @@
CMake Error at DuplicateOutput\.cmake:4 \(export\):
export command already specified for the file foo\.cps\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)

View File

@ -0,0 +1,4 @@
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo DESTINATION .)
export(EXPORT foo PACKAGE_INFO foo)
export(EXPORT foo PACKAGE_INFO foo)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
CMake Error at ExperimentalGate.cmake:5 \(export\):
export Unknown argument: "PACKAGE_INFO"\.

View File

@ -0,0 +1,5 @@
unset(CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO)
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo DESTINATION .)
export(EXPORT foo PACKAGE_INFO foo)

View File

@ -0,0 +1,7 @@
CMake Warning \(dev\) at ExperimentalWarning.cmake:8 \(export\):
CMake's support for exporting package information in the Common Package
Specification format is experimental\. It is meant only for experimentation
and feedback to CMake developers\.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.

View File

@ -0,0 +1,8 @@
set(
CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO
"b80be207-778e-46ba-8080-b23bba22639e"
)
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo DESTINATION .)
export(EXPORT foo PACKAGE_INFO foo)

View File

@ -0,0 +1,24 @@
include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake)
set(out_dir "${RunCMake_BINARY_DIR}/InterfaceProperties-build")
file(READ "${out_dir}/foo.cps" content)
expect_value("${content}" "foo" "name")
string(JSON component GET "${content}" "components" "foo")
expect_value("${component}" "interface" "type")
expect_array("${component}" 1 "includes")
expect_value("${component}" "${CMAKE_CURRENT_LIST_DIR}/foo" "includes" 0)
expect_array("${component}" 1 "compile_features")
expect_value("${component}" "c++23" "compile_features" 0)
expect_array("${component}" 1 "compile_flags")
expect_value("${component}" "-ffast-math" "compile_flags" 0)
expect_null("${component}" "compile_definitions" "*" "FOO")
expect_value("${component}" "BAR" "compile_definitions" "*" "BAR")
expect_array("${component}" 1 "link_directories")
expect_value("${component}" "/opt/foo/lib" "link_directories" 0)
expect_array("${component}" 1 "link_flags")
expect_value("${component}" "--needed" "link_flags" 0)
expect_array("${component}" 1 "link_libraries")
expect_value("${component}" "/usr/lib/libm.so" "link_libraries" 0)

View File

@ -0,0 +1,15 @@
add_library(foo INTERFACE)
target_compile_features(foo INTERFACE cxx_std_23)
target_compile_options(foo INTERFACE -ffast-math)
target_compile_definitions(foo INTERFACE -DFOO -DBAR=BAR)
target_include_directories(
foo INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/foo>
)
target_link_directories(foo INTERFACE /opt/foo/lib)
target_link_options(foo INTERFACE --needed)
target_link_libraries(foo INTERFACE /usr/lib/libm.so)
install(TARGETS foo EXPORT foo DESTINATION .)
export(EXPORT foo PACKAGE_INFO foo)

View File

@ -0,0 +1,9 @@
include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake)
set(out_dir "${RunCMake_BINARY_DIR}/LowerCaseFile-build")
file(READ "${out_dir}/lowercase.cps" content)
expect_value("${content}" "LowerCase" "name")
file(READ "${out_dir}/PreserveCase.cps" content)
expect_value("${content}" "PreserveCase" "name")

View File

@ -0,0 +1,4 @@
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo DESTINATION .)
export(EXPORT foo PACKAGE_INFO LowerCase LOWER_CASE_FILE)
export(EXPORT foo PACKAGE_INFO PreserveCase)

View File

@ -0,0 +1,16 @@
include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake)
set(out_dir "${RunCMake_BINARY_DIR}/Metadata-build")
file(READ "${out_dir}/foo.cps" content)
expect_value("${content}" "foo" "name")
expect_value("${content}" "1.2.3" "version")
expect_value("${content}" "1.2.0" "compat_version")
expect_value("${content}" "simple" "version_schema")
expect_array("${content}" 1 "default_components")
expect_value("${content}" "foo" "default_components" 0)
expect_array("${content}" 2 "configurations")
expect_value("${content}" "release" "configurations" 0)
expect_value("${content}" "debug" "configurations" 1)

View File

@ -0,0 +1,11 @@
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo DESTINATION .)
export(
EXPORT foo
PACKAGE_INFO foo
VERSION 1.2.3
VERSION_SCHEMA simple
COMPAT_VERSION 1.2.0
DEFAULT_TARGETS foo
DEFAULT_CONFIGURATIONS release debug
)

View File

@ -0,0 +1,18 @@
include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake)
set(out_dir "${RunCMake_BINARY_DIR}/Minimal-build")
file(READ "${out_dir}/foo.cps" content)
expect_value("${content}" "foo" "name")
expect_value("${content}" "interface" "components" "foo" "type")
expect_missing("${content}" "version")
expect_missing("${content}" "configurations")
expect_missing("${content}" "default_targets")
expect_missing("${content}" "components" "foo" "compile_definitions")
expect_missing("${content}" "components" "foo" "compile_features")
expect_missing("${content}" "components" "foo" "compile_flags")
expect_missing("${content}" "components" "foo" "link_directories")
expect_missing("${content}" "components" "foo" "link_features")
expect_missing("${content}" "components" "foo" "link_flags")
expect_missing("${content}" "components" "foo" "link_libraries")
expect_missing("${content}" "components" "foo" "requires")

View File

@ -0,0 +1,3 @@
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo DESTINATION .)
export(EXPORT foo PACKAGE_INFO foo)

View File

@ -0,0 +1,21 @@
include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake)
set(out_dir "${RunCMake_BINARY_DIR}/MinimalVersion-build")
file(READ "${out_dir}/foo1.cps" content)
expect_value("${content}" "foo1" "name")
expect_value("${content}" "1.0" "version")
expect_missing("${content}" "compat_version")
expect_missing("${content}" "version_schema")
file(READ "${out_dir}/foo2.cps" content)
expect_value("${content}" "foo2" "name")
expect_value("${content}" "1.5" "version")
expect_value("${content}" "1.0" "compat_version")
expect_missing("${content}" "version_schema")
file(READ "${out_dir}/foo3.cps" content)
expect_value("${content}" "foo3" "name")
expect_value("${content}" "1.0" "version")
expect_missing("${content}" "compat_version")
expect_value("${content}" "simple" "version_schema")

View File

@ -0,0 +1,16 @@
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo DESTINATION .)
export(EXPORT foo
PACKAGE_INFO foo1
VERSION 1.0)
export(EXPORT foo
PACKAGE_INFO foo2
VERSION 1.5
COMPAT_VERSION 1.0)
export(EXPORT foo
PACKAGE_INFO foo3
VERSION 1.0
VERSION_SCHEMA simple)

View File

@ -0,0 +1,3 @@
CMake Error in CMakeLists.txt:
export called with target "canine" which requires target "mammal" that is
not in any export set.

View File

@ -0,0 +1,6 @@
add_library(mammal INTERFACE)
add_library(canine INTERFACE)
target_link_libraries(canine INTERFACE mammal)
install(TARGETS canine EXPORT dog DESTINATION .)
export(EXPORT dog PACKAGE_INFO dog)

View File

@ -0,0 +1,7 @@
CMake Error in CMakeLists.txt:
Target "test" references target "foo", which does not use the standard
namespace separator. This is not allowed.
.*
CMake Error in CMakeLists.txt:
Target "test" references target "bar_bar", which does not use the standard
namespace separator. This is not allowed.

View File

@ -0,0 +1,14 @@
add_library(foo INTERFACE)
add_library(bar INTERFACE)
add_library(test INTERFACE)
target_link_libraries(test INTERFACE foo bar)
install(TARGETS foo EXPORT foo DESTINATION .)
install(TARGETS bar EXPORT bar DESTINATION .)
export(EXPORT foo)
export(EXPORT bar NAMESPACE bar_)
install(TARGETS test EXPORT test DESTINATION .)
export(EXPORT test PACKAGE_INFO test)

View File

@ -0,0 +1,3 @@
CMake Error in CMakeLists.txt:
Target "foo" references imported target "bar" which does not come from any
known package.

View File

@ -0,0 +1,7 @@
add_library(bar INTERFACE IMPORTED)
add_library(foo INTERFACE)
target_link_libraries(foo INTERFACE bar)
install(TARGETS foo EXPORT foo DESTINATION .)
export(EXPORT foo PACKAGE_INFO foo)

View File

@ -0,0 +1,4 @@
CMake Error in CMakeLists.txt:
Target "foo" references target "wrong::lib", which comes from the "broken"
package, but does not belong to the package's canonical namespace. This is
not allowed.

View File

@ -0,0 +1,11 @@
find_package(
broken REQUIRED CONFIG
NO_DEFAULT_PATH
PATHS ${CMAKE_CURRENT_LIST_DIR}
)
add_library(foo INTERFACE)
target_link_libraries(foo INTERFACE wrong::lib)
install(TARGETS foo EXPORT foo DESTINATION .)
export(EXPORT foo PACKAGE_INFO foo)

View File

@ -0,0 +1,22 @@
include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake)
set(out_dir "${RunCMake_BINARY_DIR}/Requirements-build")
file(READ "${out_dir}/foo.cps" content)
expect_value("${content}" "foo" "name")
expect_value("${content}" "interface" "components" "libb" "type")
file(READ "${out_dir}/bar.cps" content)
expect_value("${content}" "bar" "name")
expect_array("${content}" 1 "requires" "foo" "components")
expect_value("${content}" "libb" "requires" "foo" "components" 0)
expect_array("${content}" 1 "requires" "test" "components")
expect_value("${content}" "liba" "requires" "test" "components" 0)
expect_value("${content}" "interface" "components" "libc" "type")
expect_value("${content}" "interface" "components" "libd" "type")
string(JSON component GET "${content}" "components" "libd")
expect_array("${component}" 3 "requires")
expect_value("${component}" "test:liba" "requires" 0)
expect_value("${component}" "foo:libb" "requires" 1)
expect_value("${component}" ":libc" "requires" 2)

View File

@ -0,0 +1,20 @@
find_package(
test REQUIRED CONFIG
NO_DEFAULT_PATH
PATHS ${CMAKE_CURRENT_LIST_DIR}
)
add_library(libb INTERFACE)
add_library(libc INTERFACE)
add_library(libd INTERFACE)
add_library(foo ALIAS libb)
add_library(bar ALIAS libc)
target_link_libraries(libd INTERFACE test::liba foo bar)
install(TARGETS libb EXPORT foo DESTINATION .)
export(EXPORT foo PACKAGE_INFO foo)
install(TARGETS libc libd EXPORT bar DESTINATION .)
export(EXPORT bar PACKAGE_INFO bar)

View File

@ -0,0 +1,37 @@
include(RunCMake)
# Test experimental gate
run_cmake(ExperimentalGate)
run_cmake(ExperimentalWarning)
# Enable experimental feature and suppress warnings
set(RunCMake_TEST_OPTIONS
-Wno-dev
"-DCMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO:STRING=b80be207-778e-46ba-8080-b23bba22639e"
)
# Test incorrect usage
run_cmake(BadArgs1)
run_cmake(BadArgs2)
run_cmake(BadArgs3)
run_cmake(BadArgs4)
run_cmake(BadName)
run_cmake(DuplicateOutput)
run_cmake(BadDefaultTarget)
run_cmake(ReferencesNonExportedTarget)
run_cmake(ReferencesWronglyExportedTarget)
run_cmake(ReferencesWronglyImportedTarget)
run_cmake(ReferencesWronglyNamespacedTarget)
run_cmake(DependsMultipleDifferentNamespace)
run_cmake(DependsMultipleDifferentSets)
# Test functionality
run_cmake(Appendix)
run_cmake(InterfaceProperties)
run_cmake(Metadata)
run_cmake(Minimal)
run_cmake(MinimalVersion)
run_cmake(LowerCaseFile)
run_cmake(Requirements)
run_cmake(TargetTypes)
run_cmake(DependsMultiple)

View File

@ -0,0 +1,11 @@
include(${CMAKE_CURRENT_LIST_DIR}/Assertions.cmake)
set(out_dir "${RunCMake_BINARY_DIR}/TargetTypes-build")
file(READ "${out_dir}/foo.cps" content)
expect_value("${content}" "foo" "name")
expect_value("${content}" "archive" "components" "foo-static" "type")
expect_value("${content}" "dylib" "components" "foo-shared" "type")
expect_value("${content}" "module" "components" "foo-module" "type")
expect_value("${content}" "interface" "components" "bar" "type")
expect_value("${content}" "executable" "components" "test" "type")

View File

@ -0,0 +1,20 @@
project(TargetTypes CXX)
add_library(foo-static STATIC foo.cxx)
add_library(foo-shared SHARED foo.cxx)
add_library(foo-module MODULE foo.cxx)
add_library(bar INTERFACE)
add_executable(test test.cxx)
install(
TARGETS
foo-static
foo-shared
foo-module
bar
test
EXPORT foo
DESTINATION .
)
export(EXPORT foo PACKAGE_INFO foo)

View File

@ -0,0 +1 @@
add_library(wrong::lib INTERFACE IMPORTED)

View File

@ -0,0 +1,3 @@
void foo()
{
}

View File

@ -0,0 +1 @@
add_library(test::liba INTERFACE IMPORTED)

View File

@ -0,0 +1,4 @@
int main()
{
return 0;
}

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,4 @@
CMake Error at BadName\.cmake:3 \(install\):
install PACKAGE_INFO given invalid package name "%foo"\.
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)

View File

@ -0,0 +1,3 @@
add_library(foo INTERFACE)
install(TARGETS foo EXPORT foo DESTINATION .)
install(PACKAGE_INFO "%foo" EXPORT foo)

View File

@ -16,6 +16,7 @@ run_cmake(BadArgs2)
run_cmake(BadArgs3)
run_cmake(BadArgs4)
run_cmake(BadArgs5)
run_cmake(BadName)
run_cmake(BadDefaultTarget)
run_cmake(ReferencesNonExportedTarget)
run_cmake(ReferencesWronglyExportedTarget)