From f05dec34b28fc86b4e1e54a0fb0907a8528e56f8 Mon Sep 17 00:00:00 2001 From: Whisperity Date: Fri, 12 Oct 2018 18:43:13 +0200 Subject: [PATCH 1/2] add_cxx_module: Add command for 'C++ Modules TS' compilations Currently CMake is only taught for Clang (>= 4.0) on how to compile modules, but this is a first step. CMake will compile the module to a module-object and allow `target_link_libraries` (not yet implemented) to link this module to a binary which imports it. --- Help/command/add_cxx_module.rst | 87 +++++++++++++++++++++++ Help/manual/cmake-commands.7.rst | 1 + Modules/Compiler/Clang-CXX.cmake | 13 ++++ Source/CMakeLists.txt | 2 + Source/cmAddCxxModuleCommand.cxx | 114 +++++++++++++++++++++++++++++++ Source/cmAddCxxModuleCommand.h | 38 +++++++++++ Source/cmCommands.cxx | 3 + Source/cmDependsC.cxx | 2 +- 8 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 Help/command/add_cxx_module.rst create mode 100644 Source/cmAddCxxModuleCommand.cxx create mode 100644 Source/cmAddCxxModuleCommand.h diff --git a/Help/command/add_cxx_module.rst b/Help/command/add_cxx_module.rst new file mode 100644 index 0000000000..d71cec0fc2 --- /dev/null +++ b/Help/command/add_cxx_module.rst @@ -0,0 +1,87 @@ +add_cxx_module +-------------- + +Add the compilation of a C++ Modules TS module to the build and sets it up as +a target for linking other targets against it. + +.. warning:: `add_cxx_module` is an **experimental** feature! + +.. note:: Using `add_cxx_module` requires a C++ compiler (set at + ``CMAKE_CXX_COMPILER``) that contains an experimental implementation for + this feature. If your compiler can't compile modules, or CMake does not + know how to configure your current compiler, an error will be emitted and + generation will stop. + +Using C++ Modules TS have two steps: + + 1. The module must be compiled as a module using `add_cxx_module`. + 2. Binaries that import this module must be linked against the module. + +Creating module compilations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + add_cxx_module(modulename [source]) + +This command will define a target named ``modulename``, which is compiled using +``CMAKE_CXX_COMPILER``. If ``source`` is not specified, the source file +``modulename`` + ``CMAKE_CXX_MODULE_SOURCE_EXTENSION``, e.g. +``modulename.cppm``. + +C++ Module TS modules are fully-fledged translations which might have other +libraries they depend on. These libraries can and should be added to the +linked library list of **the module**. CMake will propagate this information +towards the binary, as explained in :command:`target_link_libraries`. + +.. code-block:: cmake + + add_cxx_module(my_math_module) + target_link_libraries(my_math_module PUBLIC m) + +Linking the module implementation to the binary +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +`add_cxx_module` sets up ``modulename`` as a target, which can be used as a +library in :command:`target_link_libraries`. + +:: + + target_link_libraries(binary [...] PRIVATE modulename) + +Example +^^^^^^^ + +In the following example, a module's implemented function is used in an +executable. + +.. code-block:: cpp + + // In e.g. mymodule.cppm: + #include + + export module mymodule; + export int foo() { return 2; } + export double my_sqrt(double d) { return sqrt(d); } + +.. code-block:: cpp + + // In main.cpp: + #include + import mymodule; + + int main() { + std::cout << foo() << std::endl; + return my_sqrt(25); + } + +The following configuration can be used to compile this project. + +.. code-block:: cmake + + project(Example) + add_cxx_module(mymodule) + target_link_libraries(mymodule m) + + add_executable(main main) + target_link_libraries(main PRIVATE mymodule) diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst index 0cc5fca83b..3591284aa1 100644 --- a/Help/manual/cmake-commands.7.rst +++ b/Help/manual/cmake-commands.7.rst @@ -74,6 +74,7 @@ These commands are available only in CMake projects. /command/add_compile_options /command/add_custom_command /command/add_custom_target + /command/add_cxx_module /command/add_definitions /command/add_dependencies /command/add_executable diff --git a/Modules/Compiler/Clang-CXX.cmake b/Modules/Compiler/Clang-CXX.cmake index e99011b3bc..1aaf585e10 100644 --- a/Modules/Compiler/Clang-CXX.cmake +++ b/Modules/Compiler/Clang-CXX.cmake @@ -107,3 +107,16 @@ else() _record_compiler_features(CXX "" CMAKE_CXX_COMPILE_FEATURES) endmacro() endif() + +if (${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL 4.0.0) + # Set up how compiling C++ Modules work with Clang. + set(CMAKE_CXX_MODULE_BINARY_DIR + "${CMAKE_BINARY_DIR}/clang-${CMAKE_CXX_COMPILER_VERSION}-${CMAKE_CXX_LIBRARY_ARCHITECTURE}-modules/") + + set(CMAKE_CXX_MODULE_BINARY_EXTENSION ".pcm") + + set(CMAKE_CXX_MODULE_FLAGS + -fmodules-ts -fprebuilt-module-path=${CMAKE_CXX_MODULE_BINARY_DIR}) + set(CMAKE_CXX_MODULE_FLAGS_COMPILE + ${CMAKE_CXX_MODULE_FLAGS} --precompile) +endif() diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 5e2758adfa..954bc2fe36 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -388,6 +388,8 @@ set(SRCS cmAddCustomCommandCommand.h cmAddCustomTargetCommand.cxx cmAddCustomTargetCommand.h + cmAddCxxModuleCommand.cxx + cmAddCxxModuleCommand.h cmAddDefinitionsCommand.cxx cmAddDefinitionsCommand.h cmAddDependenciesCommand.cxx diff --git a/Source/cmAddCxxModuleCommand.cxx b/Source/cmAddCxxModuleCommand.cxx new file mode 100644 index 0000000000..205ab0241e --- /dev/null +++ b/Source/cmAddCxxModuleCommand.cxx @@ -0,0 +1,114 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmAddCxxModuleCommand.h" + +#include "cmCustomCommand.h" +#include "cmGeneratorTarget.h" +#include "cmGlobalGenerator.h" +#include "cmLocalGenerator.h" +#include "cmMakefile.h" +#include "cmSourceFile.h" +#include "cmTarget.h" + +class cmExecutionStatus; + +// cmAddCxxModuleCommand +bool cmAddCxxModuleCommand::InitialPass(std::vector const& args, + cmExecutionStatus&) +{ + if (args.empty()) { + this->SetError("called with an incorrect number of arguments"); + return false; + } + + auto it = args.begin(); + std::string const& modulename = *it; + std::string sourcename = modulename + ".cppm"; + + ++it; + if (it != args.end()) { + // The command takes an extra argument which allows the user to specify + // that the module is to be built from a different source file. + sourcename = *it; + ++it; + } + + if (it != args.end()) { + this->SetError("called with an incorrect number of arguments"); + return false; + } + + const std::string& moduledir = + this->Makefile->GetSafeDefinition("CMAKE_CXX_MODULE_BINARY_DIR"); + const std::string& moduleflags = + this->Makefile->GetSafeDefinition("CMAKE_CXX_MODULE_FLAGS_COMPILE"); + if (moduledir.empty() || moduleflags.empty()) { + this->SetError("using C++ Modules TS requires a C++ compiler that " + "supports an experimental implementation of it"); + return false; + } + + cmTarget* trg = this->Makefile->AddLibrary( + modulename, cmStateEnums::OBJECT_LIBRARY, {}, true); + // Set the current target to be compiled as a module. + trg->InsertCompileOption(moduleflags, this->Makefile->GetBacktrace()); + + cmSourceFile* src = trg->AddSource(sourcename); + + // Force CMake to compile the full source path for the source. + src->GetFullPath(); + + // Create a dummy local generator that helps us fetch the output filename. + cmLocalGenerator* localgen = + this->Makefile->GetGlobalGenerator()->CreateLocalGenerator(this->Makefile); + cmGeneratorTarget generator_target(trg, localgen); + localgen->AddGeneratorTarget(&generator_target); + + const std::string& target_output_dir = cmSystemTools::CollapseCombinedPath( + this->Makefile->GetCurrentBinaryDirectory(), + localgen->GetTargetDirectory(&generator_target)); + + const std::string& full_output = cmSystemTools::CollapseCombinedPath( + target_output_dir, generator_target.GetObjectName(src)); + + const std::string& comment = + std::string("Copying module ") + modulename + " to build location"; + + const std::string& module_out_path = cmSystemTools::CollapseCombinedPath( + moduledir, + modulename + + this->Makefile->GetSafeDefinition("CMAKE_CXX_MODULE_BINARY_EXTENSION")); + + cmCustomCommandLines commands; + + cmCustomCommandLine make_folder; + cmCustomCommandLine copy_module_file; +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + make_folder.emplace_back("mkdir"); + make_folder.emplace_back(std::string("\"") + moduledir + "\""); + + copy_module_file.emplace_back("copy"); + copy_module_file.emplace_back(std::string("\"") + full_output + "\""); + copy_module_file.emplace_back(std::string("\"") + module_out_path + "\""); +#else /* Something unix-y */ + make_folder.emplace_back("mkdir"); + make_folder.emplace_back("-p"); + make_folder.emplace_back(std::string("\"") + moduledir + "\""); + + copy_module_file.emplace_back("cp"); + copy_module_file.emplace_back(std::string("\"") + full_output + "\""); + copy_module_file.emplace_back(std::string("\"") + module_out_path + "\""); +#endif + commands.push_back(make_folder); + commands.push_back(copy_module_file); + + cmCustomCommand copyOverCommand(this->Makefile, { module_out_path }, {}, + { full_output }, commands, comment.c_str(), + target_output_dir.c_str()); + + trg->AddPostBuildCommand(copyOverCommand); + this->Makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", + moduledir.c_str()); + + return true; +} diff --git a/Source/cmAddCxxModuleCommand.h b/Source/cmAddCxxModuleCommand.h new file mode 100644 index 0000000000..11e93b1752 --- /dev/null +++ b/Source/cmAddCxxModuleCommand.h @@ -0,0 +1,38 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmAddCxxModuleCommand_h +#define cmAddCxxModuleCommand_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include +#include + +#include "cmCommand.h" + +class cmExecutionStatus; + +/** \class cmAddCxxModuleCommand + * \brief Defines the add_cxx_module() command which compiles a C++ Modules TS + * module from a module source file. + * + * This command sets up the module as a target library that can and should be + * linked. + */ +class cmAddCxxModuleCommand : public cmCommand +{ +public: + /** + * This is a virtual constructor for the command. + */ + cmCommand* Clone() override { return new cmAddCxxModuleCommand; } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + bool InitialPass(std::vector const& args, + cmExecutionStatus& status) override; +}; + +#endif diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 873372f6d3..20b7934808 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -7,6 +7,7 @@ #include "cmAddCompileDefinitionsCommand.h" #include "cmAddCustomCommandCommand.h" #include "cmAddCustomTargetCommand.h" +#include "cmAddCxxModuleCommand.h" #include "cmAddDefinitionsCommand.h" #include "cmAddDependenciesCommand.h" #include "cmAddExecutableCommand.h" @@ -214,6 +215,7 @@ void GetProjectCommands(cmState* state) state->AddBuiltinCommand("add_custom_command", new cmAddCustomCommandCommand); state->AddBuiltinCommand("add_custom_target", new cmAddCustomTargetCommand); + state->AddBuiltinCommand("add_cxx_module", new cmAddCxxModuleCommand); state->AddBuiltinCommand("add_definitions", new cmAddDefinitionsCommand); state->AddBuiltinCommand("add_dependencies", new cmAddDependenciesCommand); state->AddBuiltinCommand("add_executable", new cmAddExecutableCommand); @@ -320,6 +322,7 @@ void GetProjectCommandsInScriptMode(cmState* state) CM_UNEXPECTED_PROJECT_COMMAND("add_compile_options"); CM_UNEXPECTED_PROJECT_COMMAND("add_custom_command"); CM_UNEXPECTED_PROJECT_COMMAND("add_custom_target"); + CM_UNEXPECTED_PROJECT_COMMAND("add_cxx_module"); CM_UNEXPECTED_PROJECT_COMMAND("add_definitions"); CM_UNEXPECTED_PROJECT_COMMAND("add_dependencies"); CM_UNEXPECTED_PROJECT_COMMAND("add_executable"); diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx index f7dd33b371..3e9639ac46 100644 --- a/Source/cmDependsC.cxx +++ b/Source/cmDependsC.cxx @@ -12,7 +12,7 @@ #include "cmSystemTools.h" #define INCLUDE_REGEX_LINE \ - "^[ \t]*[#%][ \t]*(include|import)[ \t]*[<\"]([^\">]+)([\">])" + "^[ \t]*[#%]?[ \t]*(include|import)[ \t]*[<\"]?([^\">;]+)([\">;]?)" #define INCLUDE_REGEX_LINE_MARKER "#IncludeRegexLine: " #define INCLUDE_REGEX_SCAN_MARKER "#IncludeRegexScan: " -- GitLab From 157b40045e998b188c2d12698e077efe856af364 Mon Sep 17 00:00:00 2001 From: Whisperity Date: Fri, 12 Oct 2018 16:59:43 +0200 Subject: [PATCH 2/2] target_link_libraries: Properly link modules created by add_cxx_module Setting one or more cxx_module to be linked to a binary turns on the C++ Modules TS feature for the binary. Object file compilations must (at least in Clang's case) see the module's object both at compilation and at linking time. This can be fine-tuned later for different compilers using the extra variables introduced in this commit. --- Modules/CMakeCXXInformation.cmake | 5 +++ Modules/Compiler/Clang-CXX.cmake | 13 ++++++-- Source/cmAddCxxModuleCommand.cxx | 6 +++- Source/cmGeneratorTarget.cxx | 8 +++-- Source/cmTargetLinkLibrariesCommand.cxx | 32 ++++++++++++++++++- Tests/CxxOnly/CMakeLists.txt | 21 ++++++++++-- Tests/CxxOnly/cxxonly.cxx | 13 ++++++++ ...CxxModule.cxx => testCxxModuleLibrary.cxx} | 0 Tests/CxxOnly/testCxxModuleTs.cppm | 9 ++++++ 9 files changed, 98 insertions(+), 9 deletions(-) rename Tests/CxxOnly/{testCxxModule.cxx => testCxxModuleLibrary.cxx} (100%) create mode 100644 Tests/CxxOnly/testCxxModuleTs.cppm diff --git a/Modules/CMakeCXXInformation.cmake b/Modules/CMakeCXXInformation.cmake index 2975874d84..979d693e66 100644 --- a/Modules/CMakeCXXInformation.cmake +++ b/Modules/CMakeCXXInformation.cmake @@ -264,6 +264,11 @@ if(NOT CMAKE_CXX_LINK_EXECUTABLE) " -o ") endif() +if(NOT CMAKE_CXX_MODULES_AVAILABLE) + # By default consider C++ Modules TS support unavailable. + set(CMAKE_CXX_MODULES_AVAILABLE 0) +endif() + mark_as_advanced( CMAKE_VERBOSE_MAKEFILE ) diff --git a/Modules/Compiler/Clang-CXX.cmake b/Modules/Compiler/Clang-CXX.cmake index 1aaf585e10..48302a23fe 100644 --- a/Modules/Compiler/Clang-CXX.cmake +++ b/Modules/Compiler/Clang-CXX.cmake @@ -109,14 +109,23 @@ else() endif() if (${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL 4.0.0) + set(CMAKE_CXX_MODULES_AVAILABLE 1) + # Set up how compiling C++ Modules work with Clang. + list(APPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS "cppm") + set(CMAKE_CXX_MODULE_BINARY_EXTENSION ".pcm") + set(CMAKE_CXX_MODULE_BINARY_DIR "${CMAKE_BINARY_DIR}/clang-${CMAKE_CXX_COMPILER_VERSION}-${CMAKE_CXX_LIBRARY_ARCHITECTURE}-modules/") - set(CMAKE_CXX_MODULE_BINARY_EXTENSION ".pcm") - set(CMAKE_CXX_MODULE_FLAGS -fmodules-ts -fprebuilt-module-path=${CMAKE_CXX_MODULE_BINARY_DIR}) set(CMAKE_CXX_MODULE_FLAGS_COMPILE ${CMAKE_CXX_MODULE_FLAGS} --precompile) + + set(CMAKE_CXX_MODULE_FLAGS_AT_DEPENDANTS_COMPILATION "TRUE") + set(CMAKE_CXX_MODULE_BINARY_APPEAR_AT_LINKING "TRUE") +else() + # Earlier Clang versions do not support the Modules TS. + set(CMAKE_CXX_MODULES_AVAILABLE 0) endif() diff --git a/Source/cmAddCxxModuleCommand.cxx b/Source/cmAddCxxModuleCommand.cxx index 205ab0241e..627e35dfdf 100644 --- a/Source/cmAddCxxModuleCommand.cxx +++ b/Source/cmAddCxxModuleCommand.cxx @@ -42,7 +42,8 @@ bool cmAddCxxModuleCommand::InitialPass(std::vector const& args, this->Makefile->GetSafeDefinition("CMAKE_CXX_MODULE_BINARY_DIR"); const std::string& moduleflags = this->Makefile->GetSafeDefinition("CMAKE_CXX_MODULE_FLAGS_COMPILE"); - if (moduledir.empty() || moduleflags.empty()) { + if (!this->Makefile->IsOn("CMAKE_CXX_MODULES_AVAILABLE") || + moduledir.empty() || moduleflags.empty()) { this->SetError("using C++ Modules TS requires a C++ compiler that " "supports an experimental implementation of it"); return false; @@ -52,6 +53,7 @@ bool cmAddCxxModuleCommand::InitialPass(std::vector const& args, modulename, cmStateEnums::OBJECT_LIBRARY, {}, true); // Set the current target to be compiled as a module. trg->InsertCompileOption(moduleflags, this->Makefile->GetBacktrace()); + trg->SetProperty("IS_CXX_MODULE", "TRUE"); cmSourceFile* src = trg->AddSource(sourcename); @@ -79,6 +81,8 @@ bool cmAddCxxModuleCommand::InitialPass(std::vector const& args, modulename + this->Makefile->GetSafeDefinition("CMAKE_CXX_MODULE_BINARY_EXTENSION")); + trg->SetProperty("CXX_MODULE_BINARY_PATH", module_out_path.c_str()); + cmCustomCommandLines commands; cmCustomCommandLine make_folder; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 80fb621e27..21b886d0af 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -573,11 +573,13 @@ const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file) const char* cmGeneratorTarget::GetCustomObjectExtension() const { static std::string extension; - const bool has_ptx_extension = - this->GetPropertyAsBool("CUDA_PTX_COMPILATION"); - if (has_ptx_extension) { + if (this->GetPropertyAsBool("CUDA_PTX_COMPILATION")) { extension = ".ptx"; return extension.c_str(); + } else if (this->GetPropertyAsBool("IS_CXX_MODULE")) { + extension = + this->Makefile->GetSafeDefinition("CMAKE_CXX_MODULE_BINARY_EXTENSION"); + return extension.c_str(); } return nullptr; } diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index ad33f98502..7efab43aa9 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -427,7 +427,37 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); } - this->Target->AddLinkLibrary(*this->Makefile, lib, libRef, llt); + if (tgt && tgt->GetPropertyAsBool("IS_CXX_MODULE")) { + if (this->Makefile->IsOn( + "CMAKE_CXX_MODULE_FLAGS_AT_DEPENDANTS_COMPILATION")) { + // For some compilers, the C++ Modules compilation flags must also + // appear when compiling the object files which have 'import' + // statements. + this->Target->InsertCompileOption( + this->Makefile->GetSafeDefinition("CMAKE_CXX_MODULE_FLAGS"), + this->Makefile->GetBacktrace()); + } + + if (this->Makefile->IsOn("CMAKE_CXX_MODULE_BINARY_APPEAR_AT_LINKING")) { + // And for some compilers, the module's output binary should appear + // as a linked library. + if (tgt->GetProperty("CXX_MODULE_BINARY_PATH") == nullptr) { + std::ostringstream buf; + buf << "Attempted to use CXX module " << tgt->GetName() + << " but the target did not have 'CXX_MODULE_BINARY_PATH' " + "properly " + "set up."; + this->Makefile->IssueMessage(cmake::INTERNAL_ERROR, buf.str()); + return false; + } + + llt = GENERAL_LibraryType; + this->Target->AddLinkLibrary( + *this->Makefile, tgt->GetProperty("CXX_MODULE_BINARY_PATH"), libRef, + llt); + } + } else + this->Target->AddLinkLibrary(*this->Makefile, lib, libRef, llt); } if (warnRemoteInterface) { diff --git a/Tests/CxxOnly/CMakeLists.txt b/Tests/CxxOnly/CMakeLists.txt index e62f3c797e..70ef092e74 100644 --- a/Tests/CxxOnly/CMakeLists.txt +++ b/Tests/CxxOnly/CMakeLists.txt @@ -5,9 +5,26 @@ set(CMAKE_DEBUG_POSTFIX "_test_debug_postfix") if(WIN32) set(EXTRA_SRCS test.CPP) endif() + +add_executable (CxxOnly cxxonly.cxx) + add_library(testcxx1.my STATIC libcxx1.cxx ${EXTRA_SRCS}) add_library(testcxx2 SHARED libcxx2.cxx) -add_executable (CxxOnly cxxonly.cxx) +add_library(testCxxModuleLibrary MODULE testCxxModuleLibrary.cxx) + target_link_libraries(CxxOnly testcxx1.my testcxx2) -add_library(testCxxModule MODULE testCxxModule.cxx) +if(NOT CMAKE_CXX_MODULES_AVAILABLE) + message(WARNING "Skipping test of C++ Modules TS features. To test, use a " + "compiler that supports it and one CMake knows how to call.") +else() + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang$") + add_cxx_module(testCxxModuleTs) + target_compile_definitions(CxxOnly PRIVATE _MODULES_TS) + target_link_libraries(CxxOnly PRIVATE testCxxModuleTs) + else() + message(WARNING "Skipping test of C++ Modules TS as the properly prepared " + "test file for compiler ${CMAKE_CXX_COMPILER_ID} is not " + "known.") + endif() +endif() diff --git a/Tests/CxxOnly/cxxonly.cxx b/Tests/CxxOnly/cxxonly.cxx index 0911a075aa..5f7ea16593 100644 --- a/Tests/CxxOnly/cxxonly.cxx +++ b/Tests/CxxOnly/cxxonly.cxx @@ -6,11 +6,16 @@ extern int testCPP; #include +#ifdef _MODULES_TS +import testCxxModuleTs; +#endif + int main() { #ifdef _MSC_VER testCPP = 1; #endif + if (LibCxx1Class::Method() != 2.0) { printf("Problem with libcxx1\n"); return 1; @@ -19,5 +24,13 @@ int main() printf("Problem with libcxx2\n"); return 1; } + +#ifdef _MODULES_TS + if (!CxxModuleTsClass::Test()) { + printf("Problem with module-ts test\n"); + return 1; + } +#endif + return 0; } diff --git a/Tests/CxxOnly/testCxxModule.cxx b/Tests/CxxOnly/testCxxModuleLibrary.cxx similarity index 100% rename from Tests/CxxOnly/testCxxModule.cxx rename to Tests/CxxOnly/testCxxModuleLibrary.cxx diff --git a/Tests/CxxOnly/testCxxModuleTs.cppm b/Tests/CxxOnly/testCxxModuleTs.cppm new file mode 100644 index 0000000000..a2dceb96c6 --- /dev/null +++ b/Tests/CxxOnly/testCxxModuleTs.cppm @@ -0,0 +1,9 @@ +export module testCxxModuleTs; + +// Implementation detail of the module. +float Method() { return 3.0; } + +export class CxxModuleTsClass { +public: + static bool Test() { return Method() == 3.0; } +}; -- GitLab