diff options
23 files changed, 573 insertions, 0 deletions
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index c8a433d..fa1d297 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -240,6 +240,11 @@ Properties on Targets /prop_tgt/IMPORTED /prop_tgt/IMPORTED_COMMON_LANGUAGE_RUNTIME /prop_tgt/IMPORTED_CONFIGURATIONS + /prop_tgt/IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS + /prop_tgt/IMPORTED_CXX_MODULES_COMPILE_FEATURES + /prop_tgt/IMPORTED_CXX_MODULES_COMPILE_OPTIONS + /prop_tgt/IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES + /prop_tgt/IMPORTED_CXX_MODULES_LINK_LIBRARIES /prop_tgt/IMPORTED_GLOBAL /prop_tgt/IMPORTED_IMPLIB /prop_tgt/IMPORTED_IMPLIB_CONFIG diff --git a/Help/prop_tgt/IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS.rst b/Help/prop_tgt/IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS.rst new file mode 100644 index 0000000..88687b2 --- /dev/null +++ b/Help/prop_tgt/IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS.rst @@ -0,0 +1,14 @@ +IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS +---------------------------------------- + +.. versionadded:: 3.28 + +.. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + +Preprocessor definitions for compiling an ``IMPORTED`` target's C++ module +sources. + +CMake will automatically drop some definitions that are not supported +by the native build tool. diff --git a/Help/prop_tgt/IMPORTED_CXX_MODULES_COMPILE_FEATURES.rst b/Help/prop_tgt/IMPORTED_CXX_MODULES_COMPILE_FEATURES.rst new file mode 100644 index 0000000..c3eb7fb --- /dev/null +++ b/Help/prop_tgt/IMPORTED_CXX_MODULES_COMPILE_FEATURES.rst @@ -0,0 +1,13 @@ +IMPORTED_CXX_MODULES_COMPILE_FEATURES +------------------------------------- + +.. versionadded:: 3.28 + +.. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + +Compiler features enabled for this ``IMPORTED`` target's C++ modules. + +The value of this property is used by the generators to set the include +paths for the compiler. diff --git a/Help/prop_tgt/IMPORTED_CXX_MODULES_COMPILE_OPTIONS.rst b/Help/prop_tgt/IMPORTED_CXX_MODULES_COMPILE_OPTIONS.rst new file mode 100644 index 0000000..5c62c77 --- /dev/null +++ b/Help/prop_tgt/IMPORTED_CXX_MODULES_COMPILE_OPTIONS.rst @@ -0,0 +1,13 @@ +IMPORTED_CXX_MODULES_COMPILE_OPTIONS +------------------------------------ + +.. versionadded:: 3.28 + +.. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + +List of options to pass to the compiler for this ``IMPORTED`` target's C++ +modules. + +.. include:: ../command/OPTIONS_SHELL.txt diff --git a/Help/prop_tgt/IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES.rst b/Help/prop_tgt/IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES.rst new file mode 100644 index 0000000..08a993d --- /dev/null +++ b/Help/prop_tgt/IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES.rst @@ -0,0 +1,14 @@ +IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES +---------------------------------------- + +.. versionadded:: 3.28 + +.. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + +List of preprocessor include file search directories when compiling C++ +modules for ``IMPORTED`` targets. + +The value of this property is used by the generators to set the include +paths for the compiler. diff --git a/Help/prop_tgt/IMPORTED_CXX_MODULES_LINK_LIBRARIES.rst b/Help/prop_tgt/IMPORTED_CXX_MODULES_LINK_LIBRARIES.rst new file mode 100644 index 0000000..5111dc5 --- /dev/null +++ b/Help/prop_tgt/IMPORTED_CXX_MODULES_LINK_LIBRARIES.rst @@ -0,0 +1,11 @@ +IMPORTED_CXX_MODULES_LINK_LIBRARIES +----------------------------------- + +.. versionadded:: 3.28 + +.. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + +List of direct dependencies to use for usage requirements for C++ modules in +the target's C++ modules. diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index fd35786..69572f4 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -126,6 +126,15 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) properties); std::string errorMessage; + if (!this->PopulateCxxModuleExportProperties( + gte, properties, cmGeneratorExpression::BuildInterface, + errorMessage)) { + this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, errorMessage, + this->LG->GetMakefile()->GetBacktrace()); + return false; + } + if (!this->PopulateExportProperties(gte, properties, errorMessage)) { this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage( MessageType::FATAL_ERROR, errorMessage, diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 41234f4..5a12297 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -9,6 +9,7 @@ #include <utility> #include <cm/memory> +#include <cmext/string_view> #include "cmsys/FStream.hxx" @@ -1255,6 +1256,77 @@ void cmExportFileGenerator::GenerateImportedFileChecksCode( os << ")\n\n"; } +bool cmExportFileGenerator::PopulateCxxModuleExportProperties( + cmGeneratorTarget const* gte, ImportPropertyMap& properties, + cmGeneratorExpression::PreprocessContext ctx, std::string& errorMessage) +{ + if (!gte->HaveCxx20ModuleSources(&errorMessage)) { + return true; + } + + const cm::static_string_view exportedDirectModuleProperties[] = { + "CXX_EXTENSIONS"_s, + }; + for (auto const& propName : exportedDirectModuleProperties) { + auto const propNameStr = std::string(propName); + cmValue prop = gte->Target->GetComputedProperty( + propNameStr, *gte->Target->GetMakefile()); + if (!prop) { + prop = gte->Target->GetProperty(propNameStr); + } + if (prop) { + properties[propNameStr] = cmGeneratorExpression::Preprocess(*prop, ctx); + } + } + + const cm::static_string_view exportedModuleProperties[] = { + "INCLUDE_DIRECTORIES"_s, + "COMPILE_DEFINITIONS"_s, + "COMPILE_OPTIONS"_s, + "COMPILE_FEATURES"_s, + }; + for (auto const& propName : exportedModuleProperties) { + auto const propNameStr = std::string(propName); + cmValue prop = gte->Target->GetComputedProperty( + propNameStr, *gte->Target->GetMakefile()); + if (!prop) { + prop = gte->Target->GetProperty(propNameStr); + } + if (prop) { + auto const exportedPropName = + cmStrCat("IMPORTED_CXX_MODULES_", propName); + properties[exportedPropName] = + cmGeneratorExpression::Preprocess(*prop, ctx); + } + } + + const cm::static_string_view exportedLinkModuleProperties[] = { + "LINK_LIBRARIES"_s, + }; + for (auto const& propName : exportedLinkModuleProperties) { + auto const propNameStr = std::string(propName); + cmValue prop = gte->Target->GetComputedProperty( + propNameStr, *gte->Target->GetMakefile()); + if (!prop) { + prop = gte->Target->GetProperty(propNameStr); + } + if (prop) { + auto const exportedPropName = + cmStrCat("IMPORTED_CXX_MODULES_", propName); + auto value = cmGeneratorExpression::Preprocess(*prop, ctx); + this->ResolveTargetsInGeneratorExpressions( + value, gte, cmExportFileGenerator::ReplaceFreeTargets); + std::vector<std::string> wrappedValues; + for (auto& item : cmList{ value }) { + wrappedValues.push_back(cmStrCat("$<COMPILE_ONLY:", item, '>')); + } + properties[exportedPropName] = cmJoin(wrappedValues, ";"); + } + } + + return true; +} + bool cmExportFileGenerator::PopulateExportProperties( cmGeneratorTarget const* gte, ImportPropertyMap& properties, std::string& errorMessage) diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index fdda878..6fa19ee 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -175,6 +175,9 @@ protected: virtual void GenerateRequiredCMakeVersion(std::ostream& os, const char* versionString); + bool PopulateCxxModuleExportProperties( + cmGeneratorTarget const* gte, ImportPropertyMap& properties, + cmGeneratorExpression::PreprocessContext ctx, std::string& errorMessage); bool PopulateExportProperties(cmGeneratorTarget const* gte, ImportPropertyMap& properties, std::string& errorMessage); diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 6cf3a09..908bb31 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -126,6 +126,13 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) gt, cmGeneratorExpression::InstallInterface, properties); std::string errorMessage; + if (!this->PopulateCxxModuleExportProperties( + gt, properties, cmGeneratorExpression::InstallInterface, + errorMessage)) { + cmSystemTools::Error(errorMessage); + return false; + } + if (!this->PopulateExportProperties(gt, properties, errorMessage)) { cmSystemTools::Error(errorMessage); return false; diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake index 25670bd..d2fb11f 100644 --- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake +++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake @@ -187,6 +187,7 @@ endif () if ("export_bmi" IN_LIST CMake_TEST_MODULE_COMPILATION) run_cxx_module_test(export-interface-no-properties-build) run_cxx_module_test(export-interface-build) + run_cxx_module_test(export-usage-build) run_cxx_module_test(export-bmi-and-interface-build) endif () @@ -201,6 +202,7 @@ if ("install_bmi" IN_LIST CMake_TEST_MODULE_COMPILATION) if ("export_bmi" IN_LIST CMake_TEST_MODULE_COMPILATION) run_cxx_module_test(export-interface-no-properties-install) run_cxx_module_test(export-interface-install) + run_cxx_module_test(export-usage-install) run_cxx_module_test(export-bmi-and-interface-install) endif () endif () diff --git a/Tests/RunCMake/CXXModules/examples/export-usage-build-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-usage-build-stderr.txt new file mode 100644 index 0000000..78bdf2b --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-usage-build-stderr.txt @@ -0,0 +1,4 @@ +CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/export-usage-build/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-usage-build/CMakeLists.txt new file mode 100644 index 0000000..86a608b --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-usage-build/CMakeLists.txt @@ -0,0 +1,110 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_export_usage CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +add_library(export_usage STATIC) +target_sources(export_usage + PRIVATE + forward.cxx + PRIVATE + FILE_SET modules_private TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + private.cxx + PUBLIC + FILE_SET modules TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + importable.cxx) +target_compile_features(export_usage PUBLIC cxx_std_20) + +list(APPEND CMAKE_CXX_KNOWN_FEATURES + exported + buildiface + installiface + buildlocaliface) + +target_include_directories(export_usage + PRIVATE + "/usr/exported" + "$<BUILD_INTERFACE:/usr/buildiface>" + "$<INSTALL_INTERFACE:/usr/installiface>" + "$<BUILD_LOCAL_INTERFACE:/usr/buildlocaliface>") +target_compile_definitions(export_usage + PRIVATE + "exported" + "$<BUILD_INTERFACE:buildiface>" + "$<INSTALL_INTERFACE:installiface>" + "$<BUILD_LOCAL_INTERFACE:buildlocaliface>") +target_compile_features(export_usage + PRIVATE + "cxx_std_11" + "$<BUILD_INTERFACE:cxx_std_14>" + "$<INSTALL_INTERFACE:cxx_std_17>" + "$<BUILD_LOCAL_INTERFACE:cxx_std_20>") + +if (MSVC) + set(variable_flag "-constexpr:depth") +else () + set(variable_flag "-fconstexpr-depth=") +endif () + +target_compile_options(export_usage + PRIVATE + "${variable_flag}100" + "$<BUILD_INTERFACE:${variable_flag}200>" + "$<INSTALL_INTERFACE:${variable_flag}300>" + "$<BUILD_LOCAL_INTERFACE:${variable_flag}400>") + +add_library(export_used INTERFACE) +add_library(export_build INTERFACE) +add_library(export_install INTERFACE) +add_library(export_never INTERFACE) + +target_link_libraries(export_usage + PRIVATE + "export_used" + "$<BUILD_INTERFACE:export_build>" + "$<INSTALL_INTERFACE:export_install>" + "$<BUILD_LOCAL_INTERFACE:export_never>") + +install(TARGETS export_usage + EXPORT CXXModules + FILE_SET modules DESTINATION "lib/cxx/miu") +export(EXPORT CXXModules + NAMESPACE CXXModules:: + FILE "${CMAKE_CURRENT_BINARY_DIR}/export_usage-targets.cmake") +install(TARGETS export_used export_build export_install + EXPORT CXXModulesDeps) +export(EXPORT CXXModulesDeps + NAMESPACE CXXModules:: + FILE "${CMAKE_CURRENT_BINARY_DIR}/export_usage-dep-targets.cmake") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/export_usage-config.cmake" + "include(\"\${CMAKE_CURRENT_LIST_DIR}/export_usage-dep-targets.cmake\") +include(\"\${CMAKE_CURRENT_LIST_DIR}/export_usage-targets.cmake\") +set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1) +") + +set(generator + -G "${CMAKE_GENERATOR}") +if (CMAKE_GENERATOR_TOOLSET) + list(APPEND generator + -T "${CMAKE_GENERATOR_TOOLSET}") +endif () +if (CMAKE_GENERATOR_PLATFORM) + list(APPEND generator + -A "${CMAKE_GENERATOR_PLATFORM}") +endif () + +add_test(NAME export_usage_build + COMMAND + "${CMAKE_COMMAND}" + "-Dexpected_dir=${CMAKE_CURRENT_SOURCE_DIR}" + "-Dexport_interfaces_flag=${variable_flag}" + "-Dexport_usage_DIR=${CMAKE_CURRENT_BINARY_DIR}" + ${generator} + -S "${CMAKE_CURRENT_SOURCE_DIR}/test" + -B "${CMAKE_CURRENT_BINARY_DIR}/test") diff --git a/Tests/RunCMake/CXXModules/examples/export-usage-build/forward.cxx b/Tests/RunCMake/CXXModules/examples/export-usage-build/forward.cxx new file mode 100644 index 0000000..7f53271 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-usage-build/forward.cxx @@ -0,0 +1,6 @@ +import priv; + +int forwarding() +{ + return from_private(); +} diff --git a/Tests/RunCMake/CXXModules/examples/export-usage-build/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-usage-build/importable.cxx new file mode 100644 index 0000000..e0b1872 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-usage-build/importable.cxx @@ -0,0 +1,8 @@ +export module importable; + +int forwarding(); + +export int from_import() +{ + return forwarding(); +} diff --git a/Tests/RunCMake/CXXModules/examples/export-usage-build/private.cxx b/Tests/RunCMake/CXXModules/examples/export-usage-build/private.cxx new file mode 100644 index 0000000..c5b719a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-usage-build/private.cxx @@ -0,0 +1,6 @@ +export module priv; + +export int from_private() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/export-usage-build/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-usage-build/test/CMakeLists.txt new file mode 100644 index 0000000..88bda88 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-usage-build/test/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_library NONE) + +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e") + +find_package(export_usage REQUIRED) + +if (NOT TARGET CXXModules::export_usage) + message(FATAL_ERROR + "Missing imported target") +endif () + +if (NOT TARGET CXXModules::export_used) + message(FATAL_ERROR + "Missing imported target") +endif () + +if (NOT TARGET CXXModules::export_build) + message(FATAL_ERROR + "Missing imported target") +endif () + +if (NOT TARGET CXXModules::export_install) + message(FATAL_ERROR + "Missing imported target") +endif () + +if (TARGET CXXModules::export_never) + message(FATAL_ERROR + "Extra imported target") +endif () + +function (check_property expected property) + get_property(actual TARGET CXXModules::export_usage + PROPERTY "${property}") + if (NOT actual STREQUAL expected) + message(SEND_ERROR + "Mismatch for ${property}:\n expected: ${expected}\n actual: ${actual}") + endif () +endfunction () + +check_property("/usr/exported;/usr/buildiface" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES") +check_property("exported;buildiface" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS") +check_property("cxx_std_20;cxx_std_11;cxx_std_14" "IMPORTED_CXX_MODULES_COMPILE_FEATURES") +check_property("${export_interfaces_flag}100;${export_interfaces_flag}200" "IMPORTED_CXX_MODULES_COMPILE_OPTIONS") +check_property("$<COMPILE_ONLY:CXXModules::export_used>;$<COMPILE_ONLY:CXXModules::export_build>" "IMPORTED_CXX_MODULES_LINK_LIBRARIES") + +# Extract the export-dependent targets from the export file. +file(STRINGS "${export_usage_DIR}/export_usage-targets.cmake" usage_dependent_targets + REGEX "foreach._target ") +# Rudimentary argument splitting. +string(REPLACE " " ";" usage_dependent_targets "${usage_dependent_targets}") +# Keep only "target" names. +list(FILTER usage_dependent_targets INCLUDE REGEX "CXXModules::") +# Strip quotes. +string(REPLACE "\"" "" usage_dependent_targets "${usage_dependent_targets}") + +if (NOT "CXXModules::export_used" IN_LIST usage_dependent_targets) + message(SEND_ERROR + "The main export does not require the 'CXXModules::export_used' target") +endif () +if (NOT "CXXModules::export_build" IN_LIST usage_dependent_targets) + message(SEND_ERROR + "The main export does not require the 'CXXModules::export_build' target") +endif () +if ("CXXModules::export_install" IN_LIST usage_dependent_targets) + message(SEND_ERROR + "The main export requires the 'CXXModules::export_install' target") +endif () diff --git a/Tests/RunCMake/CXXModules/examples/export-usage-install-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-usage-install-stderr.txt new file mode 100644 index 0000000..78bdf2b --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-usage-install-stderr.txt @@ -0,0 +1,4 @@ +CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/export-usage-install/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-usage-install/CMakeLists.txt new file mode 100644 index 0000000..11f53b0 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-usage-install/CMakeLists.txt @@ -0,0 +1,114 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_export_usage CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +add_library(export_usage STATIC) +target_sources(export_usage + PRIVATE + forward.cxx + PRIVATE + FILE_SET modules_private TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + private.cxx + PUBLIC + FILE_SET modules TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + importable.cxx) +target_compile_features(export_usage PUBLIC cxx_std_20) + +list(APPEND CMAKE_CXX_KNOWN_FEATURES + exported + buildiface + installiface + buildlocaliface) + +target_include_directories(export_usage + PRIVATE + "/usr/exported" + "$<BUILD_INTERFACE:/usr/buildiface>" + "$<INSTALL_INTERFACE:/usr/installiface>" + "$<BUILD_LOCAL_INTERFACE:/usr/buildlocaliface>") +target_compile_definitions(export_usage + PRIVATE + "exported" + "$<BUILD_INTERFACE:buildiface>" + "$<INSTALL_INTERFACE:installiface>" + "$<BUILD_LOCAL_INTERFACE:buildlocaliface>") +target_compile_features(export_usage + PRIVATE + "cxx_std_11" + "$<BUILD_INTERFACE:cxx_std_14>" + "$<INSTALL_INTERFACE:cxx_std_17>" + "$<BUILD_LOCAL_INTERFACE:cxx_std_20>") + +if (MSVC) + set(variable_flag "-constexpr:depth") +else () + set(variable_flag "-fconstexpr-depth=") +endif () + +target_compile_options(export_usage + PRIVATE + "${variable_flag}100" + "$<BUILD_INTERFACE:${variable_flag}200>" + "$<INSTALL_INTERFACE:${variable_flag}300>" + "$<BUILD_LOCAL_INTERFACE:${variable_flag}400>") + +add_library(export_used INTERFACE) +add_library(export_build INTERFACE) +add_library(export_install INTERFACE) +add_library(export_never INTERFACE) + +target_link_libraries(export_usage + PRIVATE + "export_used" + "$<BUILD_INTERFACE:export_build>" + "$<INSTALL_INTERFACE:export_install>" + "$<BUILD_LOCAL_INTERFACE:export_never>") + +install(TARGETS export_usage + EXPORT CXXModules + FILE_SET modules DESTINATION "lib/cxx/miu") +install(EXPORT CXXModules + NAMESPACE CXXModules:: + DESTINATION "lib/cmake/export_usage" + FILE "export_usage-targets.cmake") +install(TARGETS export_used export_build export_install + EXPORT CXXModulesDeps) +install(EXPORT CXXModulesDeps + NAMESPACE CXXModules:: + DESTINATION "lib/cmake/export_usage" + FILE "export_usage-dep-targets.cmake") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/export_usage-config.cmake" + "include(\"\${CMAKE_CURRENT_LIST_DIR}/export_usage-dep-targets.cmake\") +include(\"\${CMAKE_CURRENT_LIST_DIR}/export_usage-targets.cmake\") +set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1) +") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/export_usage-config.cmake" + DESTINATION "lib/cmake/export_usage") + +set(generator + -G "${CMAKE_GENERATOR}") +if (CMAKE_GENERATOR_TOOLSET) + list(APPEND generator + -T "${CMAKE_GENERATOR_TOOLSET}") +endif () +if (CMAKE_GENERATOR_PLATFORM) + list(APPEND generator + -A "${CMAKE_GENERATOR_PLATFORM}") +endif () + +add_test(NAME export_usage_build + COMMAND + "${CMAKE_COMMAND}" + "-Dexpected_dir=${CMAKE_INSTALL_PREFIX}/lib/cxx/miu" + "-Dexport_interfaces_flag=${variable_flag}" + "-Dexport_usage_DIR=${CMAKE_INSTALL_PREFIX}/lib/cmake/export_usage" + ${generator} + -S "${CMAKE_CURRENT_SOURCE_DIR}/test" + -B "${CMAKE_CURRENT_BINARY_DIR}/test") diff --git a/Tests/RunCMake/CXXModules/examples/export-usage-install/forward.cxx b/Tests/RunCMake/CXXModules/examples/export-usage-install/forward.cxx new file mode 100644 index 0000000..7f53271 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-usage-install/forward.cxx @@ -0,0 +1,6 @@ +import priv; + +int forwarding() +{ + return from_private(); +} diff --git a/Tests/RunCMake/CXXModules/examples/export-usage-install/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-usage-install/importable.cxx new file mode 100644 index 0000000..e0b1872 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-usage-install/importable.cxx @@ -0,0 +1,8 @@ +export module importable; + +int forwarding(); + +export int from_import() +{ + return forwarding(); +} diff --git a/Tests/RunCMake/CXXModules/examples/export-usage-install/private.cxx b/Tests/RunCMake/CXXModules/examples/export-usage-install/private.cxx new file mode 100644 index 0000000..c5b719a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-usage-install/private.cxx @@ -0,0 +1,6 @@ +export module priv; + +export int from_private() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/export-usage-install/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-usage-install/test/CMakeLists.txt new file mode 100644 index 0000000..bdc2898 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-usage-install/test/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_library NONE) + +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e") + +find_package(export_usage REQUIRED) + +if (NOT TARGET CXXModules::export_usage) + message(FATAL_ERROR + "Missing imported target") +endif () + +if (NOT TARGET CXXModules::export_used) + message(FATAL_ERROR + "Missing imported target") +endif () + +if (NOT TARGET CXXModules::export_build) + message(FATAL_ERROR + "Missing imported target") +endif () + +if (NOT TARGET CXXModules::export_install) + message(FATAL_ERROR + "Missing imported target") +endif () + +if (TARGET CXXModules::export_never) + message(FATAL_ERROR + "Extra imported target") +endif () + +function (check_property expected property) + get_property(actual TARGET CXXModules::export_usage + PROPERTY "${property}") + if (NOT actual STREQUAL expected) + message(SEND_ERROR + "Mismatch for ${property}:\n expected: ${expected}\n actual : ${actual}") + endif () +endfunction () + +check_property("/usr/exported;/usr/installiface" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES") +check_property("exported;installiface" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS") +check_property("cxx_std_20;cxx_std_11;cxx_std_17" "IMPORTED_CXX_MODULES_COMPILE_FEATURES") +check_property("${export_interfaces_flag}100;${export_interfaces_flag}300" "IMPORTED_CXX_MODULES_COMPILE_OPTIONS") +check_property("$<COMPILE_ONLY:CXXModules::export_used>;$<COMPILE_ONLY:CXXModules::export_install>" "IMPORTED_CXX_MODULES_LINK_LIBRARIES") + +# Extract the export-dependent targets from the export file. +file(STRINGS "${export_usage_DIR}/export_usage-targets.cmake" usage_dependent_targets + REGEX "foreach._target ") +# Rudimentary argument splitting. +string(REPLACE " " ";" usage_dependent_targets "${usage_dependent_targets}") +# Keep only "target" names. +list(FILTER usage_dependent_targets INCLUDE REGEX "CXXModules::") +# Strip quotes. +string(REPLACE "\"" "" usage_dependent_targets "${usage_dependent_targets}") + +if (NOT "CXXModules::export_used" IN_LIST usage_dependent_targets) + message(SEND_ERROR + "The main export does not require the 'CXXModules::export_used' target") +endif () +if ("CXXModules::export_build" IN_LIST usage_dependent_targets) + message(SEND_ERROR + "The main export requires the 'CXXModules::export_build' target") +endif () +if (NOT "CXXModules::export_install" IN_LIST usage_dependent_targets) + message(SEND_ERROR + "The main export does not require the 'CXXModules::export_install' target") +endif () |