FILE_SET: install and export SOURCES file set type

This commit is contained in:
Marc Chevrier
2026-03-12 10:29:48 +01:00
parent 5c5b68f44e
commit c386aaebf8
21 changed files with 388 additions and 11 deletions

View File

@@ -245,7 +245,10 @@ Signatures
File sets are defined by the :command:`target_sources(FILE_SET)` command.
If the file set ``<set-name>`` exists and is ``PUBLIC`` or ``INTERFACE``,
any files in the set are installed under the destination (see below).
any files in the set of type ``HEADERS`` are installed under
the destination (see below). Other types do not have any default
destination, so ``DESTINATION`` option must be specified for each
``FILE_SET``.
The directory structure relative to the file set's base directories is
preserved. For example, a file added to the file set as
``/blah/include/myproj/here.h`` with a base directory ``/blah/include``
@@ -265,12 +268,13 @@ Signatures
``DESTINATION`` is omitted, a default destination will be taken from the
appropriate variable from :module:`GNUInstallDirs`, or set to a built-in
default value if that variable is not defined. The same is true for file
sets, and the public and private headers associated with the installed
targets through the :prop_tgt:`PUBLIC_HEADER` and :prop_tgt:`PRIVATE_HEADER`
target properties. A destination must always be provided for module libraries,
Apple bundles and frameworks. A destination can be omitted for interface and
object libraries, but they are handled differently (see the discussion of this
topic toward the end of this section).
sets of type ``HEADERS``, and the public and private headers associated with
the installed targets through the :prop_tgt:`PUBLIC_HEADER` and
:prop_tgt:`PRIVATE_HEADER` target properties. A destination must always be
provided for module libraries, Apple bundles and frameworks. A destination
can be omitted for interface and object libraries, but they are handled
differently (see the discussion of this topic toward the end of this
section).
For shared libraries on DLL platforms, if neither ``RUNTIME`` nor ``ARCHIVE``
destinations are specified, both the ``RUNTIME`` and ``ARCHIVE`` components are

View File

@@ -71,12 +71,17 @@ bool cmExportBuildCMakeConfigGenerator::GenerateMainFile(std::ostream& os)
return false;
}
ImportFileSetPropertyMap fsProperties;
if (!this->PopulateFileSetInterfaceProperties(gte, fsProperties)) {
return false;
}
this->PopulateInterfaceLinkLibrariesProperty(
gte, cmGeneratorExpression::BuildInterface, properties);
this->GenerateInterfaceProperties(gte, os, properties);
this->GenerateTargetFileSets(gte, os);
this->GenerateTargetFileSets(gte, os, fsProperties);
}
std::string cxx_modules_name;

View File

@@ -11,6 +11,8 @@
#include "cmExportSet.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorFileSet.h"
#include "cmGeneratorFileSets.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmList.h"
@@ -284,3 +286,24 @@ bool cmExportBuildFileGenerator::PopulateInterfaceProperties(
return this->PopulateInterfaceProperties(
target, {}, cmGeneratorExpression::BuildInterface, properties);
}
bool cmExportBuildFileGenerator::PopulateFileSetInterfaceProperties(
cmGeneratorTarget const* target, ImportFileSetPropertyMap& properties)
{
cmGeneratorFileSets const* const gfs = target->GetGeneratorFileSets();
bool result = true;
for (auto const& type : gfs->GetInterfaceFileSetTypes()) {
for (auto const* fileSet : gfs->GetInterfaceFileSets(type)) {
ImportPropertyMap& fsProperties = properties[fileSet->GetName()];
this->PopulateFileSetInterfaceProperty(
"INTERFACE_INCLUDE_DIRECTORIES", target, fileSet,
cmGeneratorExpression::BuildInterface, fsProperties);
result = result &&
this->PopulateFileSetInterfaceProperties(
target, fileSet, cmGeneratorExpression::InstallInterface,
fsProperties);
}
}
return result;
}

View File

@@ -114,6 +114,10 @@ protected:
bool PopulateInterfaceProperties(cmGeneratorTarget const* target,
ImportPropertyMap& properties);
using cmExportFileGenerator::PopulateFileSetInterfaceProperties;
bool PopulateFileSetInterfaceProperties(
cmGeneratorTarget const* target, ImportFileSetPropertyMap& properties);
struct TargetExportPrivate
{
TargetExportPrivate(cmGeneratorTarget* target,

View File

@@ -612,6 +612,8 @@ cm::optional<FileSetInformation> GetFileSetInformation(cm::string_view type)
fileSetsInformation{
{ cm::FileSetMetadata::HEADERS,
{ cm::FileSetMetadata::HEADERS, "3.23.0"_s } },
{ cm::FileSetMetadata::SOURCES,
{ cm::FileSetMetadata::SOURCES, "4.4.0"_s } },
{ cm::FileSetMetadata::CXX_MODULES,
{ cm::FileSetMetadata::CXX_MODULES, "3.28.0"_s } },
};
@@ -625,7 +627,8 @@ cm::optional<FileSetInformation> GetFileSetInformation(cm::string_view type)
}
void cmExportCMakeConfigGenerator::GenerateTargetFileSets(
cmGeneratorTarget* gte, std::ostream& os, cmTargetExport const* te)
cmGeneratorTarget* gte, std::ostream& os,
ImportFileSetPropertyMap const& properties, cmTargetExport const* te)
{
cmGeneratorFileSets const* gfs = gte->GetGeneratorFileSets();
auto const& types = gfs->GetInterfaceFileSetTypes();
@@ -648,9 +651,20 @@ void cmExportCMakeConfigGenerator::GenerateTargetFileSets(
<< this->GetFileSetDirectories(gte, fileSet, te) << "\n FILES "
<< this->GetFileSetFiles(gte, fileSet, te) << '\n';
}
os << " )\n";
for (auto const* fileSet : gfs->GetInterfaceFileSets(type)) {
auto fsProperties = properties.find(fileSet->GetName());
if (fsProperties != properties.end()) {
for (auto const& property : fsProperties->second) {
os << "\n set_property(FILE_SET "
<< cmScriptGenerator::Quote(fileSet->GetName()) << " TARGET "
<< targetName << "\n PROPERTY " << property.first << ' '
<< cmExportFileGeneratorEscape(property.second) << "\n )";
}
}
}
if (fsInfo) {
os << " )";
if (type == cm::FileSetMetadata::HEADERS) {
os << "\nelse()\n set_property(TARGET " << targetName
<< "\n APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES";
@@ -658,6 +672,10 @@ void cmExportCMakeConfigGenerator::GenerateTargetFileSets(
os << "\n " << this->GetFileSetDirectories(gte, fileSet, te);
}
os << "\n )";
} else if (type == cm::FileSetMetadata::SOURCES) {
os << "\nelse()\n message(FATAL_ERROR \"The target '" << targetName
<< "' cannot be imported because it relies on 'FILE_SET' of type "
"'SOURCES' which is not supported by this CMake version.\")";
} else if (type == cm::FileSetMetadata::CXX_MODULES) {
os << "\nelse()\n message(AUTHOR_WARNING \"The target '"
<< targetName

View File

@@ -44,6 +44,7 @@ public:
protected:
using ImportPropertyMap = std::map<std::string, std::string>;
using ImportFileSetPropertyMap = std::map<std::string, ImportPropertyMap>;
// Methods to implement export file code generation.
bool GenerateImportFile(std::ostream& os) override;
@@ -84,6 +85,7 @@ protected:
cmGeneratorTarget const* target, ImportPropertyMap& properties);
void GenerateTargetFileSets(cmGeneratorTarget* gte, std::ostream& os,
ImportFileSetPropertyMap const& properties,
cmTargetExport const* te = nullptr);
std::string GetCxxModuleFile(std::string const& name) const override;

View File

@@ -16,6 +16,7 @@
#include "cmComputeLinkInformation.h"
#include "cmFindPackageStack.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorFileSet.h"
#include "cmGeneratorTarget.h"
#include "cmLinkItem.h"
#include "cmList.h"
@@ -139,6 +140,20 @@ bool cmExportFileGenerator::PopulateInterfaceProperties(
return true;
}
bool cmExportFileGenerator::PopulateFileSetInterfaceProperties(
cmGeneratorTarget const* target, cmGeneratorFileSet const* fileSet,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties)
{
this->PopulateFileSetInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS",
target, fileSet, preprocessRule,
properties);
this->PopulateFileSetInterfaceProperty("INTERFACE_COMPILE_OPTIONS", target,
fileSet, preprocessRule, properties);
return true;
}
void cmExportFileGenerator::PopulateInterfaceProperty(
std::string const& propName, cmGeneratorTarget const* target,
ImportPropertyMap& properties) const
@@ -181,6 +196,29 @@ void cmExportFileGenerator::PopulateInterfaceProperty(
properties);
}
void cmExportFileGenerator::PopulateFileSetInterfaceProperty(
std::string const& propName, cmGeneratorTarget const* target,
cmGeneratorFileSet const* fileSet,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties)
{
cmValue input = fileSet->GetProperty(propName);
if (input) {
if (input->empty()) {
// Set to empty
properties[propName].clear();
return;
}
std::string prepro =
cmGeneratorExpression::Preprocess(*input, preprocessRule);
if (!prepro.empty()) {
this->ResolveTargetsInGeneratorExpressions(prepro, target);
properties[propName] = prepro;
}
}
}
bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty(
cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,

View File

@@ -18,6 +18,7 @@
class cmExportSet;
class cmGeneratorTarget;
class cmGeneratorFileSet;
class cmLocalGenerator;
/** \class cmExportFileGenerator
@@ -48,6 +49,7 @@ public:
protected:
using ImportPropertyMap = std::map<std::string, std::string>;
using ImportFileSetPropertyMap = std::map<std::string, ImportPropertyMap>;
// Collect properties with detailed information about targets beyond
// their location on disk.
@@ -112,6 +114,10 @@ protected:
cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext,
ImportPropertyMap& properties);
void PopulateFileSetInterfaceProperty(
std::string const& propName, cmGeneratorTarget const* target,
cmGeneratorFileSet const* fileSet,
cmGeneratorExpression::PreprocessContext, ImportPropertyMap& properties);
bool PopulateInterfaceLinkLibrariesProperty(
cmGeneratorTarget const* target, cmGeneratorExpression::PreprocessContext,
ImportPropertyMap& properties);
@@ -122,6 +128,11 @@ protected:
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties);
bool PopulateFileSetInterfaceProperties(
cmGeneratorTarget const* target, cmGeneratorFileSet const* fileSet,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties);
virtual void IssueMessage(MessageType type,
std::string const& message) const = 0;
virtual void IssueDiagnostic(cmDiagnosticCategory category,

View File

@@ -83,6 +83,11 @@ bool cmExportInstallCMakeConfigGenerator::GenerateMainFile(std::ostream& os)
return false;
}
ImportFileSetPropertyMap fsProperties;
if (!this->PopulateFileSetInterfaceProperties(te, fsProperties)) {
return false;
}
if (this->PopulateInterfaceLinkLibrariesProperty(
gt, cmGeneratorExpression::InstallInterface, properties) &&
!this->ExportOld) {
@@ -99,7 +104,7 @@ bool cmExportInstallCMakeConfigGenerator::GenerateMainFile(std::ostream& os)
this->GenerateInterfaceProperties(gt, os, properties);
this->GenerateTargetFileSets(gt, os, te);
this->GenerateTargetFileSets(gt, os, fsProperties, te);
}
this->LoadConfigFiles(os);

View File

@@ -12,6 +12,8 @@
#include "cmExportSet.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorFileSet.h"
#include "cmGeneratorFileSets.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmInstallTargetGenerator.h"
@@ -410,6 +412,27 @@ bool cmExportInstallFileGenerator::PopulateInterfaceProperties(
properties);
}
bool cmExportInstallFileGenerator::PopulateFileSetInterfaceProperties(
cmTargetExport const* targetExport, ImportFileSetPropertyMap& properties)
{
cmGeneratorTarget const* const gt = targetExport->Target;
cmGeneratorFileSets const* const gfs = gt->GetGeneratorFileSets();
bool result = true;
for (auto const& type : gfs->GetInterfaceFileSetTypes()) {
for (auto const* fileSet : gfs->GetInterfaceFileSets(type)) {
ImportPropertyMap& fsProperties = properties[fileSet->GetName()];
this->PopulateFileSetIncludeDirectoriesInterface(
gt, fileSet, cmGeneratorExpression::InstallInterface, fsProperties);
result = result &&
this->PopulateFileSetInterfaceProperties(
gt, fileSet, cmGeneratorExpression::InstallInterface, fsProperties);
}
}
return result;
}
namespace {
bool isSubDirectory(std::string const& a, std::string const& b)
{
@@ -620,6 +643,37 @@ void cmExportInstallFileGenerator::PopulateIncludeDirectoriesInterface(
}
}
void cmExportInstallFileGenerator::PopulateFileSetIncludeDirectoriesInterface(
cmGeneratorTarget const* target, cmGeneratorFileSet const* fileSet,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties)
{
assert(preprocessRule == cmGeneratorExpression::InstallInterface);
char const* const propName = "INTERFACE_INCLUDE_DIRECTORIES";
cmValue includes = fileSet->GetProperty(propName);
if (!includes) {
return;
}
if (includes && includes->empty()) {
// Set to empty
properties[propName].clear();
return;
}
std::string prepro = cmGeneratorExpression::Preprocess(
*includes, preprocessRule, this->GetImportPrefixWithSlash());
if (!prepro.empty()) {
this->ResolveTargetsInGeneratorExpressions(prepro, target);
if (!this->CheckInterfaceDirs(prepro, target, propName)) {
return;
}
properties[propName] = prepro;
}
}
void cmExportInstallFileGenerator::PopulateLinkDependsInterface(
cmGeneratorTarget const* gt,
cmGeneratorExpression::PreprocessContext preprocessRule,

View File

@@ -19,6 +19,7 @@
#include "cmStateTypes.h"
class cmGeneratorTarget;
class cmGeneratorFileSet;
class cmInstallTargetGenerator;
class cmTargetExport;
@@ -138,6 +139,10 @@ protected:
ImportPropertyMap& properties,
std::set<std::string>& importedLocations);
using cmExportFileGenerator::PopulateFileSetInterfaceProperties;
bool PopulateFileSetInterfaceProperties(
cmTargetExport const* targetExport, ImportFileSetPropertyMap& properties);
virtual bool CheckInterfaceDirs(std::string const& prepro,
cmGeneratorTarget const* target,
std::string const& prop) const;
@@ -179,4 +184,9 @@ private:
cmGeneratorTarget const* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties);
void PopulateFileSetIncludeDirectoriesInterface(
cmGeneratorTarget const* target, cmGeneratorFileSet const* fileSet,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap& properties);
};

View File

@@ -0,0 +1,40 @@
enable_language(C)
add_library(lib1 STATIC)
target_sources(lib1 PRIVATE lib1.c)
target_sources(lib1 PUBLIC FILE_SET a TYPE SOURCES FILES lib2.c)
set_property(FILE_SET a TARGET lib1 PROPERTY COMPILE_DEFINITIONS LIB1_A)
set_property(FILE_SET a TARGET lib1 PROPERTY COMPILE_OPTIONS -DOPT_LIB1_A)
set_property(FILE_SET a TARGET lib1 PROPERTY INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/subdir1>"
"$<INSTALL_INTERFACE:include/subdir1>")
set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_COMPILE_DEFINITIONS INTERFACE_LIB1_A)
set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_COMPILE_OPTIONS -DOPT_INTERFACE_LIB1_A)
set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/subdir2>"
"$<INSTALL_INTERFACE:include/subdir2>")
target_sources(lib1 PUBLIC FILE_SET SOURCES FILES lib5.c)
set_property(FILE_SET SOURCES TARGET lib1 PROPERTY INTERFACE_COMPILE_DEFINITIONS INTERFACE_LIB1_SRCS)
set_property(FILE_SET SOURCES TARGET lib1 PROPERTY INTERFACE_COMPILE_OPTIONS -DOPT_INTERFACE_LIB1_SRCS)
set_property(FILE_SET SOURCES TARGET lib1 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/srcs>"
"$<INSTALL_INTERFACE:include/srcs>")
add_executable(main main.c)
target_link_libraries(main PRIVATE lib1)
target_compile_definitions(main PRIVATE CONSUMER)
if(CMAKE_GENERATOR MATCHES "Xcode")
install(TARGETS lib1 EXPORT export FILE_SET a DESTINATION sources
FILE_SET SOURCES DESTINATION sources/srcs)
else()
install(TARGETS lib1 EXPORT export FILE_SET a DESTINATION sources
FILE_SET SOURCES DESTINATION sources/$<IF:$<CONFIG:Debug>,debug,release>)
endif()
install(FILES subdir1/h1.h subdir1/h3.h DESTINATION include/subdir1)
install(FILES subdir2/h2.h subdir2/h3.h DESTINATION include/subdir2)
install(EXPORT export FILE export.cmake NAMESPACE install:: DESTINATION lib/cmake)
export(EXPORT export FILE export.cmake NAMESPACE export::)

View File

@@ -0,0 +1,85 @@
enable_language(C)
get_property(multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
function(assert_target_prop_eq tgt prop value)
unset(actual_value)
get_property(actual_value TARGET ${tgt} PROPERTY ${prop})
if(NOT actual_value STREQUAL value)
message(SEND_ERROR "Expected value of target ${prop}:\n ${value}\nActual value:\n ${actual_value}")
endif()
endfunction()
function(assert_fileset_prop_eq tgt fs prop value)
unset(actual_value)
get_property(actual_value FILE_SET ${fs} TARGET ${tgt} PROPERTY ${prop})
if(NOT actual_value STREQUAL value)
message(SEND_ERROR "Expected value of file set ${prop}:\n ${value}\nActual value:\n ${actual_value}")
endif()
endfunction()
cmake_path(GET CMAKE_BINARY_DIR PARENT_PATH export_build_dir)
cmake_path(APPEND export_build_dir "FileSetExport-build")
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_EQUAL 4.3
AND NOT CMAKE_PATCH_VERSION VERSION_LESS 20000000)
# development version for future 4.4: Force version 4.4
set(CMAKE_VERSION_BACKUP "${CMAKE_VERSION}")
set(CMAKE_VERSION 4.4)
endif()
include("${export_build_dir}/export.cmake")
include("${export_build_dir}/install/lib/cmake/export.cmake")
if(CMAKE_VERSION VERSION_GREATER 4.3 AND CMAKE_VERSION VERSION_LESS 4.4
AND NOT CMake_VERSION_PATCH VERSION_LESS 20000000)
# development version for future 4.4: Force version 4.4
set(CMAKE_VERSION "${CMAKE_VERSION_BACKUP}")
endif()
assert_target_prop_eq(export::lib1 SOURCE_SETS "")
assert_target_prop_eq(export::lib1 INTERFACE_SOURCE_SETS "a;SOURCES")
assert_target_prop_eq(export::lib1 SOURCE_SET_a "${CMAKE_CURRENT_SOURCE_DIR}/lib2.c")
assert_target_prop_eq(export::lib1 SOURCE_SET "${CMAKE_CURRENT_SOURCE_DIR}/lib5.c")
assert_target_prop_eq(export::lib1 SOURCE_SET_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/lib5.c")
assert_fileset_prop_eq(export::lib1 a INTERFACE_COMPILE_DEFINITIONS "INTERFACE_LIB1_A")
assert_fileset_prop_eq(export::lib1 a INTERFACE_COMPILE_OPTIONS "-DOPT_INTERFACE_LIB1_A")
assert_fileset_prop_eq(export::lib1 a INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/subdir2")
assert_fileset_prop_eq(export::lib1 SOURCES INTERFACE_COMPILE_DEFINITIONS "INTERFACE_LIB1_SRCS")
assert_fileset_prop_eq(export::lib1 SOURCES INTERFACE_COMPILE_OPTIONS "-DOPT_INTERFACE_LIB1_SRCS")
assert_fileset_prop_eq(export::lib1 SOURCES INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/srcs")
assert_target_prop_eq(install::lib1 SOURCE_SETS "")
assert_target_prop_eq(install::lib1 INTERFACE_SOURCE_SETS "a;SOURCES")
assert_target_prop_eq(install::lib1 SOURCE_SET_a "${export_build_dir}/install/sources/lib2.c")
if(multi_config)
if(CMAKE_GENERATOR MATCHES "Xcode")
assert_target_prop_eq(install::lib1 SOURCE_SET "${export_build_dir}/install/sources/srcs/lib5.c")
assert_target_prop_eq(install::lib1 SOURCE_SET_SOURCES "${export_build_dir}/install/sources/srcs/lib5.c")
else()
assert_target_prop_eq(install::lib1 SOURCE_SET "$<$<CONFIG:Debug>:${export_build_dir}/install/sources/debug/lib5.c>;$<$<CONFIG:Release>:${export_build_dir}/install/sources/release/lib5.c>")
assert_target_prop_eq(install::lib1 SOURCE_SET_SOURCES "$<$<CONFIG:Debug>:${export_build_dir}/install/sources/debug/lib5.c>;$<$<CONFIG:Release>:${export_build_dir}/install/sources/release/lib5.c>")
endif()
else()
assert_target_prop_eq(install::lib1 SOURCE_SET "${export_build_dir}/install/sources/debug/lib5.c")
assert_target_prop_eq(install::lib1 SOURCE_SET_SOURCES "${export_build_dir}/install/sources/debug/lib5.c")
endif()
assert_fileset_prop_eq(install::lib1 a INTERFACE_COMPILE_DEFINITIONS "INTERFACE_LIB1_A")
assert_fileset_prop_eq(install::lib1 a INTERFACE_COMPILE_OPTIONS "-DOPT_INTERFACE_LIB1_A")
assert_fileset_prop_eq(install::lib1 a INTERFACE_INCLUDE_DIRECTORIES "${export_build_dir}/install/include/subdir2")
assert_fileset_prop_eq(install::lib1 SOURCES INTERFACE_COMPILE_DEFINITIONS "INTERFACE_LIB1_SRCS")
assert_fileset_prop_eq(install::lib1 SOURCES INTERFACE_COMPILE_OPTIONS "-DOPT_INTERFACE_LIB1_SRCS")
assert_fileset_prop_eq(install::lib1 SOURCES INTERFACE_INCLUDE_DIRECTORIES "${export_build_dir}/install/include/srcs")
add_executable(main_export main.c)
target_link_libraries(main_export PRIVATE export::lib1)
target_compile_definitions(main_export PRIVATE CONSUMER)
add_executable(main_install main.c)
target_link_libraries(main_install PRIVATE install::lib1)
target_compile_definitions(main_install PRIVATE CONSUMER)

View File

@@ -0,0 +1,5 @@
CMake Error at InstallMissingSetsInterface\.cmake:[0-9]+ \(install\):
install TARGETS target lib1 is exported but not all of its interface file
sets are installed
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)

View File

@@ -0,0 +1,5 @@
enable_language(C)
add_library(lib1 STATIC)
target_sources(lib1 INTERFACE FILE_SET a TYPE SOURCES BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES lib1.c)
install(TARGETS lib1 EXPORT a)

View File

@@ -0,0 +1,6 @@
CMake Error in CMakeLists\.txt:
File set "a" is listed in interface file sets of lib1 but has not been
exported
CMake Generate step failed\. Build files cannot be regenerated correctly\.

View File

@@ -0,0 +1,6 @@
enable_language(C)
add_library(lib1 STATIC)
install(TARGETS lib1 EXPORT a)
target_sources(lib1 INTERFACE FILE_SET a TYPE SOURCES BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES lib1.c)
install(EXPORT a DESTINATION lib/cmake/test)

View File

@@ -41,3 +41,53 @@ if ((RunCMake_GENERATOR MATCHES "Makefiles|Ninja|Xcode"
AND NOT CMAKE_C_COMPILER_ID STREQUAL "Intel")
run_and_check(FileSetProperties2 lib1 main)
endif()
function(run_export_import name)
if(ARGV1)
set(importname ${ARGV1})
else()
set(importname ${name})
endif()
if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
set(_config_options "-DCMAKE_CONFIGURATION_TYPES=Debug\\\\;Release")
else()
set(_config_options -DCMAKE_BUILD_TYPE=Debug)
endif()
set(RunCMake_TEST_NO_CLEAN 1)
set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${name}Export-build")
set(RunCMake_TEST_OPTIONS "--install-prefix=${RunCMake_TEST_BINARY_DIR}/install" ${_config_options})
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
run_cmake(${name}Export)
if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
run_cmake_command(${name}Export-build-Debug ${CMAKE_COMMAND} --build . --config Debug)
run_cmake_command(${name}Export-install-Debug ${CMAKE_COMMAND} --install . --config Debug)
run_cmake_command(${name}Export-build-Release ${CMAKE_COMMAND} --build . --config Release)
run_cmake_command(${name}Export-install-Release ${CMAKE_COMMAND} --install . --config Release)
else()
run_cmake_command(${name}Export-build ${CMAKE_COMMAND} --build . --config Debug)
run_cmake_command(${name}Export-install ${CMAKE_COMMAND} --install . --config Debug)
endif()
unset(RunCMake_TEST_OPTIONS)
set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${importname}Import-build")
unset(RunCMake_TEST_OPTIONS)
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
run_cmake(${importname}Import)
if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
run_cmake_command(${importname}Import-build-Debug ${CMAKE_COMMAND} --build . --config Debug)
run_cmake_command(${importname}Import-build-Release ${CMAKE_COMMAND} --build . --config Release)
else()
run_cmake_command(${importname}Import-build ${CMAKE_COMMAND} --build . --config Debug)
endif()
unset(RunCMake_TEST_BINARY_DIR)
unset(RunCMake_TEST_NO_CLEAN)
endfunction()
run_cmake(InstallMissingSetsInterface)
run_cmake(InstallMissingSetsInterfacePostInstall)
run_export_import(FileSet)

View File

@@ -0,0 +1,4 @@
void f5(void)
{
}