From 04300579ddcb8d6bdd6e653b06b60bae378826dc Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 25 Jul 2023 09:26:54 -0400 Subject: Modules/Internal/FeatureTesting: mark feature testing as a special test --- Modules/Internal/FeatureTesting.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/Internal/FeatureTesting.cmake b/Modules/Internal/FeatureTesting.cmake index 1a8a27e..c2bd14f 100644 --- a/Modules/Internal/FeatureTesting.cmake +++ b/Modules/Internal/FeatureTesting.cmake @@ -37,6 +37,7 @@ macro(_record_compiler_features lang compile_flags feature_list) LINK_LIBRARIES "${compile_flags_for_link}" COPY_FILE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin" COPY_FILE_ERROR _copy_error + __CMAKE_INTERNAL FEATURE_TESTING ) if(NOT CMAKE_${lang}_FEATURE_TEST) set(_result 255) -- cgit v0.12 From 1a538ae07c5a859158e603c6075b352c5f5e294e Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 19 Jul 2023 16:40:52 -0400 Subject: cmExperimental: use an `enum` for whether to forward to try_compile --- Source/cmCoreTryCompile.cxx | 3 ++- Source/cmExperimental.cxx | 6 +++--- Source/cmExperimental.h | 8 +++++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index cddbb9b..74f0320 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -1077,7 +1077,8 @@ cm::optional cmCoreTryCompile::TryCompileCode( i++) { auto const& data = cmExperimental::DataForFeature( static_cast(i)); - if (data.ForwardThroughTryCompile) { + if (data.ForwardThroughTryCompile == + cmExperimental::TryCompileCondition::Always) { vars.insert(data.Variable); } } diff --git a/Source/cmExperimental.cxx b/Source/cmExperimental.cxx index 51c174e..fcd215c 100644 --- a/Source/cmExperimental.cxx +++ b/Source/cmExperimental.cxx @@ -24,14 +24,14 @@ cmExperimental::FeatureData LookupTable[] = { "CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API", "CMake's C++ module support is experimental. It is meant only for " "experimentation and feedback to CMake developers.", - false, // https://gitlab.kitware.com/cmake/cmake/-/issues/25097 - false }, + // https://gitlab.kitware.com/cmake/cmake/-/issues/25097 + cmExperimental::TryCompileCondition::Never, false }, // WindowsKernelModeDriver { "WindowsKernelModeDriver", "5c2d848d-4efa-4529-a768-efd57171bf68", "CMAKE_EXPERIMENTAL_WINDOWS_KERNEL_MODE_DRIVER", "CMake's Windows kernel-mode driver support is experimental. It is meant " "only for experimentation and feedback to CMake developers.", - true, false }, + cmExperimental::TryCompileCondition::Always, false }, }; static_assert(sizeof(LookupTable) / sizeof(LookupTable[0]) == static_cast(cmExperimental::Feature::Sentinel), diff --git a/Source/cmExperimental.h b/Source/cmExperimental.h index 3374ba8..fa1982e 100644 --- a/Source/cmExperimental.h +++ b/Source/cmExperimental.h @@ -20,13 +20,19 @@ public: Sentinel, }; + enum class TryCompileCondition + { + Always, + Never, + }; + struct FeatureData { std::string const Name; std::string const Uuid; std::string const Variable; std::string const Description; - bool const ForwardThroughTryCompile; + TryCompileCondition const ForwardThroughTryCompile; bool Warned; }; -- cgit v0.12 From f6cf4332562adcacf590d9939d6ab591f049cf59 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 19 Jul 2023 16:41:49 -0400 Subject: cmExperimental: only forward C++ module support to non-ABI checks ABI checks never use modules, so don't forward the experimental status through. --- Source/cmCoreTryCompile.cxx | 6 +++++- Source/cmExperimental.cxx | 3 +-- Source/cmExperimental.h | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 74f0320..7045aa7 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -1078,7 +1078,11 @@ cm::optional cmCoreTryCompile::TryCompileCode( auto const& data = cmExperimental::DataForFeature( static_cast(i)); if (data.ForwardThroughTryCompile == - cmExperimental::TryCompileCondition::Always) { + cmExperimental::TryCompileCondition::Always || + (data.ForwardThroughTryCompile == + cmExperimental::TryCompileCondition::SkipCompilerChecks && + arguments.CMakeInternal != "ABI"_s && + arguments.CMakeInternal != "FEATURE_TESTING"_s)) { vars.insert(data.Variable); } } diff --git a/Source/cmExperimental.cxx b/Source/cmExperimental.cxx index fcd215c..68bd964 100644 --- a/Source/cmExperimental.cxx +++ b/Source/cmExperimental.cxx @@ -24,8 +24,7 @@ cmExperimental::FeatureData LookupTable[] = { "CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API", "CMake's C++ module support is experimental. It is meant only for " "experimentation and feedback to CMake developers.", - // https://gitlab.kitware.com/cmake/cmake/-/issues/25097 - cmExperimental::TryCompileCondition::Never, false }, + cmExperimental::TryCompileCondition::SkipCompilerChecks, false }, // WindowsKernelModeDriver { "WindowsKernelModeDriver", "5c2d848d-4efa-4529-a768-efd57171bf68", "CMAKE_EXPERIMENTAL_WINDOWS_KERNEL_MODE_DRIVER", diff --git a/Source/cmExperimental.h b/Source/cmExperimental.h index fa1982e..0768146 100644 --- a/Source/cmExperimental.h +++ b/Source/cmExperimental.h @@ -23,6 +23,7 @@ public: enum class TryCompileCondition { Always, + SkipCompilerChecks, Never, }; -- cgit v0.12 From aad9033b5640b62ab47c0be926b8e05d66b735c0 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 19 Jul 2023 16:42:37 -0400 Subject: cmExperimental: support forwarding associated variables to `try_compile` Other variables may be needed to make experimental features actually work. List them with the experimental flag. --- Source/cmCoreTryCompile.cxx | 3 +++ Source/cmExperimental.cxx | 16 ++++++++++++---- Source/cmExperimental.h | 2 ++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 7045aa7..7773569 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -1084,6 +1084,9 @@ cm::optional cmCoreTryCompile::TryCompileCode( arguments.CMakeInternal != "ABI"_s && arguments.CMakeInternal != "FEATURE_TESTING"_s)) { vars.insert(data.Variable); + for (auto const& var : data.TryCompileVariables) { + vars.insert(var); + } } } diff --git a/Source/cmExperimental.cxx b/Source/cmExperimental.cxx index 68bd964..b971a26 100644 --- a/Source/cmExperimental.cxx +++ b/Source/cmExperimental.cxx @@ -20,17 +20,25 @@ namespace { */ cmExperimental::FeatureData LookupTable[] = { // CxxModuleCMakeApi - { "CxxModuleCMakeApi", "bf70d4b0-9fb7-465c-9803-34014e70d112", + { "CxxModuleCMakeApi", + "bf70d4b0-9fb7-465c-9803-34014e70d112", "CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API", "CMake's C++ module support is experimental. It is meant only for " "experimentation and feedback to CMake developers.", - cmExperimental::TryCompileCondition::SkipCompilerChecks, false }, + { "CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE", + "CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT", + "CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG" }, + cmExperimental::TryCompileCondition::SkipCompilerChecks, + false }, // WindowsKernelModeDriver - { "WindowsKernelModeDriver", "5c2d848d-4efa-4529-a768-efd57171bf68", + { "WindowsKernelModeDriver", + "5c2d848d-4efa-4529-a768-efd57171bf68", "CMAKE_EXPERIMENTAL_WINDOWS_KERNEL_MODE_DRIVER", "CMake's Windows kernel-mode driver support is experimental. It is meant " "only for experimentation and feedback to CMake developers.", - cmExperimental::TryCompileCondition::Always, false }, + {}, + cmExperimental::TryCompileCondition::Always, + false }, }; static_assert(sizeof(LookupTable) / sizeof(LookupTable[0]) == static_cast(cmExperimental::Feature::Sentinel), diff --git a/Source/cmExperimental.h b/Source/cmExperimental.h index 0768146..c958ab6 100644 --- a/Source/cmExperimental.h +++ b/Source/cmExperimental.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include +#include class cmMakefile; @@ -33,6 +34,7 @@ public: std::string const Uuid; std::string const Variable; std::string const Description; + std::vector const TryCompileVariables; TryCompileCondition const ForwardThroughTryCompile; bool Warned; }; -- cgit v0.12 From 07551f35de4e5d4aef40f1646f699785ab741128 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 19 Jul 2023 16:44:03 -0400 Subject: cmCoreTryCompile: use `target_sources` for `try_compile` targets In order to support using C++ module sources in `try_compile`, `target_sources` will be required. To prepare, always use the command. --- Source/cmCoreTryCompile.cxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 7773569..32f2e3b 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -837,17 +837,18 @@ cm::optional cmCoreTryCompile::TryCompileCode( fprintf(fout, "set(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"%s\")\n", this->BinaryDirectory.c_str()); /* Create the actual executable. */ - fprintf(fout, "add_executable(%s", targetName.c_str()); + fprintf(fout, "add_executable(%s)\n", targetName.c_str()); } else // if (targetType == cmStateEnums::STATIC_LIBRARY) { /* Put the static library at a known location (for COPY_FILE). */ fprintf(fout, "set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY \"%s\")\n", this->BinaryDirectory.c_str()); /* Create the actual static library. */ - fprintf(fout, "add_library(%s STATIC", targetName.c_str()); + fprintf(fout, "add_library(%s STATIC)\n", targetName.c_str()); } + fprintf(fout, "target_sources(%s PRIVATE\n", targetName.c_str()); for (std::string const& si : sources) { - fprintf(fout, " \"%s\"", si.c_str()); + fprintf(fout, " \"%s\"\n", si.c_str()); // Add dependencies on any non-temporary sources. if (!IsTemporary(si)) { -- cgit v0.12 From c9ca5f6326136d02c8d12b0a749076ff375dae4c Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 19 Jul 2023 18:55:59 -0400 Subject: cmCoreTryCompile: parse `SOURCES_TYPE` argument This will serve to add context for the source listing in order to properly mark sources as `FILE_SET TYPE CXX_MODULES` in the generated code. --- Help/command/try_compile.rst | 22 ++++++++++++++++++++++ Help/command/try_run.rst | 1 + Source/cmCoreTryCompile.cxx | 40 +++++++++++++++++++++++++++++++++++++++- Source/cmCoreTryCompile.h | 19 +++++++++++++++++++ 4 files changed, 81 insertions(+), 1 deletion(-) diff --git a/Help/command/try_compile.rst b/Help/command/try_compile.rst index 8abb6e0..fbc4221 100644 --- a/Help/command/try_compile.rst +++ b/Help/command/try_compile.rst @@ -65,6 +65,7 @@ Try Compiling Source Files .. code-block:: cmake try_compile( + [SOURCES_TYPE ] | SOURCE_FROM_CONTENT | SOURCE_FROM_VAR | @@ -244,6 +245,27 @@ The options are: ``SOURCE_FROM_VAR`` may be specified multiple times. +``SOURCES_TYPE `` + .. versionadded:: 3.28 + + Sources may be classified using the ``SOURCES_TYPE`` argument. Once + specified, all subsequent sources specified will be treated as that type + until another ``SOURCES_TYPE`` is given. Available types are: + + ``NORMAL`` + Sources are not added to any ``FILE_SET`` in the generated project. + + ``CXX_MODULE`` + Sources are added to a ``FILE_SET`` of type ``CXX_MODULES`` in the + generated project. + + .. note :: + + Experimental. Sources of type ``CXX_MODULE`` are gated by + ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + + The default type of sources is ``NORMAL``. + ``_STANDARD `` .. versionadded:: 3.8 diff --git a/Help/command/try_run.rst b/Help/command/try_run.rst index 3a4e203..d48ab3d 100644 --- a/Help/command/try_run.rst +++ b/Help/command/try_run.rst @@ -13,6 +13,7 @@ Try Compiling and Running Source Files .. code-block:: cmake try_run( + [SOURCES_TYPE ] | SOURCE_FROM_CONTENT | SOURCE_FROM_VAR | diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 32f2e3b..57a9180 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -167,6 +167,7 @@ auto const TryCompileBaseArgParser = auto const TryCompileBaseSourcesArgParser = cmArgumentParser{ TryCompileBaseArgParser } + .Bind("SOURCES_TYPE"_s, &Arguments::SetSourceType) .Bind("SOURCES"_s, &Arguments::Sources) .Bind("COMPILE_DEFINITIONS"_s, TryCompileCompileDefs, ArgumentParser::ExpectAtLeast{ 0 }) @@ -221,12 +222,44 @@ auto const TryRunOldArgParser = makeTryRunParser(TryCompileOldArgParser); std::string const TryCompileDefaultConfig = "DEBUG"; } +ArgumentParser::Continue cmCoreTryCompile::Arguments::SetSourceType( + cm::string_view sourceType) +{ + bool matched = false; + if (sourceType == "NORMAL"_s) { + this->SourceTypeContext = SourceType::Normal; + matched = true; + } else if (sourceType == "CXX_MODULE"_s) { + bool const supportCxxModuleSources = cmExperimental::HasSupportEnabled( + *this->Makefile, cmExperimental::Feature::CxxModuleCMakeApi); + if (supportCxxModuleSources) { + this->SourceTypeContext = SourceType::CxxModule; + matched = true; + } + } + + if (!matched && this->SourceTypeError.empty()) { + bool const supportCxxModuleSources = cmExperimental::HasSupportEnabled( + *this->Makefile, cmExperimental::Feature::CxxModuleCMakeApi); + auto const* message = "'SOURCE'"; + if (supportCxxModuleSources) { + message = "one of 'SOURCE' or 'CXX_MODULE'"; + } + // Only remember one error at a time; all other errors related to argument + // parsing are "indicate one error and return" anyways. + this->SourceTypeError = + cmStrCat("Invalid 'SOURCE_TYPE' '", sourceType, "'; must be ", message); + } + return ArgumentParser::Continue::Yes; +} + Arguments cmCoreTryCompile::ParseArgs( const cmRange::const_iterator>& args, const cmArgumentParser& parser, std::vector& unparsedArguments) { - auto arguments = parser.Parse(args, &unparsedArguments, 0); + Arguments arguments{ this->Makefile }; + parser.Parse(arguments, args, &unparsedArguments, 0); if (!arguments.MaybeReportError(*(this->Makefile)) && !unparsedArguments.empty()) { std::string m = "Unknown arguments:"; @@ -434,6 +467,11 @@ cm::optional cmCoreTryCompile::TryCompileCode( "SOURCE_FROM_FILE requires exactly two arguments"); return cm::nullopt; } + if (!arguments.SourceTypeError.empty()) { + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, + arguments.SourceTypeError); + return cm::nullopt; + } } else { // only valid for srcfile signatures if (!arguments.LangProps.empty()) { diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h index c185c68..7d5a4f8 100644 --- a/Source/cmCoreTryCompile.h +++ b/Source/cmCoreTryCompile.h @@ -9,6 +9,7 @@ #include #include +#include #include "cmArgumentParser.h" #include "cmArgumentParserTypes.h" @@ -51,6 +52,20 @@ public: struct Arguments : public ArgumentParser::ParseResult { + Arguments(cmMakefile const* mf) + : Makefile(mf) + { + } + + cmMakefile const* Makefile; + + enum class SourceType + { + Normal, + CxxModule, + Directory, + }; + cm::optional CompileResultVariable; cm::optional BinaryDirectory; cm::optional SourceDirectoryOrFile; @@ -79,6 +94,10 @@ public: bool NoCache = false; bool NoLog = false; + ArgumentParser::Continue SetSourceType(cm::string_view sourceType); + SourceType SourceTypeContext = SourceType::Normal; + std::string SourceTypeError; + // Argument for try_run only. // Keep in sync with warnings in cmCoreTryCompile::ParseArgs. cm::optional CompileOutputVariable; -- cgit v0.12 From 93993c7ad4f634451fb1c8f67f00d4d959d199ac Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 19 Jul 2023 16:44:59 -0400 Subject: cmArgumentParser: support storing a context value with parsing This allows for parsing of contextual keywords. For example: ``` some_command( ARG_WITH_CONTEXT foo CONTEXT bar ARG_WITH_CONTEXT quux) ``` will be able to store that `foo` happened without context (or, rather, its default value) and `quux` was provided in a `bar` context. --- Source/cmArgumentParser.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/Source/cmArgumentParser.h b/Source/cmArgumentParser.h index fdf54fb..b35d7f3 100644 --- a/Source/cmArgumentParser.h +++ b/Source/cmArgumentParser.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -176,6 +177,17 @@ public: void Bind(MaybeEmpty>& val); void Bind(NonEmpty>& val); void Bind(std::vector>& val); + template + void Bind(NonEmpty>>& val, + U const& context) + { + this->Bind( + [&val, &context](cm::string_view arg) -> Continue { + val.emplace_back(std::string(arg), context); + return Continue::Yes; + }, + ExpectAtLeast{ 1 }); + } // cm::optional<> records the presence the keyword to which it binds. template @@ -187,6 +199,15 @@ public: this->Bind(*optVal); } + template + void Bind(cm::optional& optVal, U const& context) + { + if (!optVal) { + optVal.emplace(); + } + this->Bind(*optVal, context); + } + template void Parse(Range const& args, std::size_t pos = 0) { @@ -232,6 +253,17 @@ public: return *this; } + template + cmArgumentParser& BindWithContext(cm::static_string_view name, + T Result::*member, U Result::*context) + { + this->Base::Bind(name, [member, context](Instance& instance) { + auto* result = static_cast(instance.Result); + instance.Bind(result->*member, result->*context); + }); + return *this; + } + cmArgumentParser& Bind(cm::static_string_view name, Continue (Result::*member)(cm::string_view), ExpectAtLeast expect = { 1 }) -- cgit v0.12 From b768d293c5c358dd734234cacab7c34e61c88c54 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 19 Jul 2023 19:00:05 -0400 Subject: cmCoreTryCompile: use the source type context for source files Also add a test to `RunCMake/CXXModules` to test `try_compile` with C++ modules. Fixes: #25097 --- Source/cmCoreTryCompile.cxx | 68 ++++++++++++++++------ Source/cmCoreTryCompile.h | 14 +++-- Tests/RunCMake/CXXModules/RunCMakeTest.cmake | 2 + .../CXXModules/examples/try-compile-stderr.txt | 4 ++ .../CXXModules/examples/try-compile/CMakeLists.txt | 19 ++++++ .../CXXModules/examples/try-compile/importable.cxx | 6 ++ .../examples/try-compile/use_importable.cxx | 6 ++ .../CXXModules/examples/try-run-stderr.txt | 4 ++ .../CXXModules/examples/try-run/CMakeLists.txt | 23 ++++++++ .../CXXModules/examples/try-run/importable.cxx | 6 ++ .../RunCMake/CXXModules/examples/try-run/main.cxx | 6 ++ 11 files changed, 137 insertions(+), 21 deletions(-) create mode 100644 Tests/RunCMake/CXXModules/examples/try-compile-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/examples/try-compile/CMakeLists.txt create mode 100644 Tests/RunCMake/CXXModules/examples/try-compile/importable.cxx create mode 100644 Tests/RunCMake/CXXModules/examples/try-compile/use_importable.cxx create mode 100644 Tests/RunCMake/CXXModules/examples/try-run-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/examples/try-run/CMakeLists.txt create mode 100644 Tests/RunCMake/CXXModules/examples/try-run/importable.cxx create mode 100644 Tests/RunCMake/CXXModules/examples/try-run/main.cxx diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 57a9180..03c71bf 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -168,7 +168,8 @@ auto const TryCompileBaseArgParser = auto const TryCompileBaseSourcesArgParser = cmArgumentParser{ TryCompileBaseArgParser } .Bind("SOURCES_TYPE"_s, &Arguments::SetSourceType) - .Bind("SOURCES"_s, &Arguments::Sources) + .BindWithContext("SOURCES"_s, &Arguments::Sources, + &Arguments::SourceTypeContext) .Bind("COMPILE_DEFINITIONS"_s, TryCompileCompileDefs, ArgumentParser::ExpectAtLeast{ 0 }) .Bind("LINK_LIBRARIES"_s, &Arguments::LinkLibraries) @@ -185,9 +186,12 @@ auto const TryCompileBaseSourcesArgParser = auto const TryCompileBaseNewSourcesArgParser = cmArgumentParser{ TryCompileBaseSourcesArgParser } - .Bind("SOURCE_FROM_CONTENT"_s, &Arguments::SourceFromContent) - .Bind("SOURCE_FROM_VAR"_s, &Arguments::SourceFromVar) - .Bind("SOURCE_FROM_FILE"_s, &Arguments::SourceFromFile) + .BindWithContext("SOURCE_FROM_CONTENT"_s, &Arguments::SourceFromContent, + &Arguments::SourceTypeContext) + .BindWithContext("SOURCE_FROM_VAR"_s, &Arguments::SourceFromVar, + &Arguments::SourceTypeContext) + .BindWithContext("SOURCE_FROM_FILE"_s, &Arguments::SourceFromFile, + &Arguments::SourceTypeContext) /* keep semicolon on own line */; auto const TryCompileBaseProjectArgParser = @@ -524,42 +528,45 @@ cm::optional cmCoreTryCompile::TryCompileCode( cmSystemTools::RemoveFile(ccFile); // Choose sources. - std::vector sources; + std::vector> sources; if (arguments.Sources) { sources = std::move(*arguments.Sources); } else if (arguments.SourceDirectoryOrFile) { - sources.emplace_back(*arguments.SourceDirectoryOrFile); + sources.emplace_back(*arguments.SourceDirectoryOrFile, + Arguments::SourceType::Directory); } if (arguments.SourceFromContent) { auto const k = arguments.SourceFromContent->size(); for (auto i = decltype(k){ 0 }; i < k; i += 2) { - const auto& name = (*arguments.SourceFromContent)[i + 0]; - const auto& content = (*arguments.SourceFromContent)[i + 1]; + const auto& name = (*arguments.SourceFromContent)[i + 0].first; + const auto& content = (*arguments.SourceFromContent)[i + 1].first; auto out = this->WriteSource(name, content, "SOURCE_FROM_CONTENT"); if (out.empty()) { return cm::nullopt; } - sources.emplace_back(std::move(out)); + sources.emplace_back(std::move(out), + (*arguments.SourceFromContent)[i + 0].second); } } if (arguments.SourceFromVar) { auto const k = arguments.SourceFromVar->size(); for (auto i = decltype(k){ 0 }; i < k; i += 2) { - const auto& name = (*arguments.SourceFromVar)[i + 0]; - const auto& var = (*arguments.SourceFromVar)[i + 1]; + const auto& name = (*arguments.SourceFromVar)[i + 0].first; + const auto& var = (*arguments.SourceFromVar)[i + 1].first; const auto& content = this->Makefile->GetDefinition(var); auto out = this->WriteSource(name, content, "SOURCE_FROM_VAR"); if (out.empty()) { return cm::nullopt; } - sources.emplace_back(std::move(out)); + sources.emplace_back(std::move(out), + (*arguments.SourceFromVar)[i + 0].second); } } if (arguments.SourceFromFile) { auto const k = arguments.SourceFromFile->size(); for (auto i = decltype(k){ 0 }; i < k; i += 2) { - const auto& dst = (*arguments.SourceFromFile)[i + 0]; - const auto& src = (*arguments.SourceFromFile)[i + 1]; + const auto& dst = (*arguments.SourceFromFile)[i + 0].first; + const auto& src = (*arguments.SourceFromFile)[i + 1].first; if (!cmSystemTools::GetFilenamePath(dst).empty()) { const auto& msg = @@ -577,7 +584,8 @@ cm::optional cmCoreTryCompile::TryCompileCode( return cm::nullopt; } - sources.emplace_back(std::move(dstPath)); + sources.emplace_back(std::move(dstPath), + (*arguments.SourceFromFile)[i + 0].second); } } // TODO: ensure sources is not empty @@ -585,7 +593,8 @@ cm::optional cmCoreTryCompile::TryCompileCode( // Detect languages to enable. cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); std::set testLangs; - for (std::string const& si : sources) { + for (auto const& source : sources) { + auto const& si = source.first; std::string ext = cmSystemTools::GetFilenameLastExtension(si); std::string lang = gg->GetLanguageFromExtension(ext.c_str()); if (!lang.empty()) { @@ -885,7 +894,32 @@ cm::optional cmCoreTryCompile::TryCompileCode( fprintf(fout, "add_library(%s STATIC)\n", targetName.c_str()); } fprintf(fout, "target_sources(%s PRIVATE\n", targetName.c_str()); - for (std::string const& si : sources) { + std::string file_set_name; + bool in_file_set = false; + for (auto const& source : sources) { + auto const& si = source.first; + switch (source.second) { + case Arguments::SourceType::Normal: { + if (in_file_set) { + fprintf(fout, " PRIVATE\n"); + in_file_set = false; + } + } break; + case Arguments::SourceType::CxxModule: { + if (!in_file_set) { + file_set_name += 'a'; + fprintf(fout, + " PRIVATE FILE_SET %s TYPE CXX_MODULES BASE_DIRS \"%s\" " + "FILES\n", + file_set_name.c_str(), + this->Makefile->GetCurrentSourceDirectory().c_str()); + in_file_set = true; + } + } break; + case Arguments::SourceType::Directory: + /* Handled elsewhere. */ + break; + } fprintf(fout, " \"%s\"\n", si.c_str()); // Add dependencies on any non-temporary sources. diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h index 7d5a4f8..3217a1b 100644 --- a/Source/cmCoreTryCompile.h +++ b/Source/cmCoreTryCompile.h @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -71,12 +72,17 @@ public: cm::optional SourceDirectoryOrFile; cm::optional ProjectName; cm::optional TargetName; - cm::optional>> Sources; - cm::optional>> + cm::optional>>> + Sources; + cm::optional>>> SourceFromContent; - cm::optional>> + cm::optional>>> SourceFromVar; - cm::optional>> + cm::optional>>> SourceFromFile; ArgumentParser::MaybeEmpty> CMakeFlags{ 1, "CMAKE_FLAGS" diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake index d324ec9..25670bd 100644 --- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake +++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake @@ -148,6 +148,8 @@ if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION) run_cxx_module_test(duplicate) set(RunCMake_CXXModules_NO_TEST 1) run_cxx_module_test(circular) + run_cxx_module_test(try-compile) + run_cxx_module_test(try-run) unset(RunCMake_CXXModules_NO_TEST) run_cxx_module_test(same-src-name) run_cxx_module_test(scan_properties) diff --git a/Tests/RunCMake/CXXModules/examples/try-compile-stderr.txt b/Tests/RunCMake/CXXModules/examples/try-compile-stderr.txt new file mode 100644 index 0000000..571bb9c --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/try-compile-stderr.txt @@ -0,0 +1,4 @@ +CMake Warning \(dev\) at CMakeLists.txt:[0-9]* \(try_compile\): + 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/try-compile/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/try-compile/CMakeLists.txt new file mode 100644 index 0000000..dee61f1 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/try-compile/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_try_compile CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") +try_compile(can_use_modules + SOURCES_TYPE CXX_MODULE + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/importable.cxx" + SOURCES_TYPE NORMAL + SOURCE_FROM_FILE + use_importable.cxx "${CMAKE_CURRENT_LIST_DIR}/use_importable.cxx" + CXX_STANDARD 20) + +if (NOT can_use_modules) + message(FATAL_ERROR + "`try_compile` could not compile sources using modules.") +endif () diff --git a/Tests/RunCMake/CXXModules/examples/try-compile/importable.cxx b/Tests/RunCMake/CXXModules/examples/try-compile/importable.cxx new file mode 100644 index 0000000..607680a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/try-compile/importable.cxx @@ -0,0 +1,6 @@ +export module importable; + +export int from_import() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/try-compile/use_importable.cxx b/Tests/RunCMake/CXXModules/examples/try-compile/use_importable.cxx new file mode 100644 index 0000000..8d6bab2 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/try-compile/use_importable.cxx @@ -0,0 +1,6 @@ +import importable; + +int foo() +{ + return from_import(); +} diff --git a/Tests/RunCMake/CXXModules/examples/try-run-stderr.txt b/Tests/RunCMake/CXXModules/examples/try-run-stderr.txt new file mode 100644 index 0000000..508db55 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/try-run-stderr.txt @@ -0,0 +1,4 @@ +CMake Warning \(dev\) at CMakeLists.txt:[0-9]* \(try_run\): + 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/try-run/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/try-run/CMakeLists.txt new file mode 100644 index 0000000..fb03571 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/try-run/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_try_run CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +try_run(can_run_modules_result can_compile_modules + SOURCES_TYPE CXX_MODULE + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/importable.cxx" + SOURCES_TYPE NORMAL + SOURCE_FROM_FILE + main.cxx "${CMAKE_CURRENT_LIST_DIR}/main.cxx" + CXX_STANDARD 20) + +if (NOT can_compile_modules) + message(FATAL_ERROR + "`try_run` could not compile sources using modules.") +endif () + +if (can_run_modules_result) + message(FATAL_ERROR + "`try_run` could not run sources using modules.") +endif () diff --git a/Tests/RunCMake/CXXModules/examples/try-run/importable.cxx b/Tests/RunCMake/CXXModules/examples/try-run/importable.cxx new file mode 100644 index 0000000..607680a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/try-run/importable.cxx @@ -0,0 +1,6 @@ +export module importable; + +export int from_import() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/try-run/main.cxx b/Tests/RunCMake/CXXModules/examples/try-run/main.cxx new file mode 100644 index 0000000..5c1bb42 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/try-run/main.cxx @@ -0,0 +1,6 @@ +import importable; + +int main(int argc, char* argv[]) +{ + return from_import() == 1; +} -- cgit v0.12 From deb1c3cbd577ba2ddbc0044794ec854847c99cf8 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sat, 29 Jul 2023 11:54:49 -0400 Subject: cmCoreTryCompile: forward module-related binutils variables --- Source/cmCoreTryCompile.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 03c71bf..2ec62d9 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -1098,6 +1098,7 @@ cm::optional cmCoreTryCompile::TryCompileCode( vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s); vars.emplace("CMAKE_WATCOM_RUNTIME_LIBRARY"_s); vars.emplace("CMAKE_MSVC_DEBUG_INFORMATION_FORMAT"_s); + vars.emplace("CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS"_s); if (cmValue varListStr = this->Makefile->GetDefinition( kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES)) { -- cgit v0.12 From be53c7585281e67ba06969e2f83aa487579d1daa Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 21 Jul 2023 11:20:06 -0400 Subject: cmExperimental: recycle the C++ modules API UUID `try_compile` and `try_run` now support C++ modules. --- Source/cmExperimental.cxx | 2 +- Tests/RunCMake/CXXModules/CMakeLists.txt | 2 +- Tests/RunCMake/CXXModules/examples/cxx-modules-rules.cmake | 2 +- .../examples/export-bmi-and-interface-build/test/CMakeLists.txt | 2 +- .../examples/export-bmi-and-interface-install/test/CMakeLists.txt | 2 +- .../CXXModules/examples/export-interface-build/test/CMakeLists.txt | 2 +- .../CXXModules/examples/export-interface-install/test/CMakeLists.txt | 2 +- .../examples/export-interface-no-properties-build/test/CMakeLists.txt | 2 +- .../examples/export-interface-no-properties-install/test/CMakeLists.txt | 2 +- Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental.cmake | 2 +- Tests/RunCMake/target_sources/FileSetWrongTypeExperimental.cmake | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Source/cmExperimental.cxx b/Source/cmExperimental.cxx index b971a26..dd8f16e 100644 --- a/Source/cmExperimental.cxx +++ b/Source/cmExperimental.cxx @@ -21,7 +21,7 @@ namespace { cmExperimental::FeatureData LookupTable[] = { // CxxModuleCMakeApi { "CxxModuleCMakeApi", - "bf70d4b0-9fb7-465c-9803-34014e70d112", + "a816ed09-43d1-40e5-bc8c-1a2824ee194e", "CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API", "CMake's C++ module support is experimental. It is meant only for " "experimentation and feedback to CMake developers.", diff --git a/Tests/RunCMake/CXXModules/CMakeLists.txt b/Tests/RunCMake/CXXModules/CMakeLists.txt index 640d67b..ecc66b6 100644 --- a/Tests/RunCMake/CXXModules/CMakeLists.txt +++ b/Tests/RunCMake/CXXModules/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.23) project(${RunCMake_TEST} NONE) -set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112") +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e") include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CXXModules/examples/cxx-modules-rules.cmake b/Tests/RunCMake/CXXModules/examples/cxx-modules-rules.cmake index c17b5a4..6238d37 100644 --- a/Tests/RunCMake/CXXModules/examples/cxx-modules-rules.cmake +++ b/Tests/RunCMake/CXXModules/examples/cxx-modules-rules.cmake @@ -1,4 +1,4 @@ -set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112") +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e") if (NOT EXISTS "${CMake_TEST_MODULE_COMPILATION_RULES}") message(FATAL_ERROR diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt index a3e55f6..4d7a85b 100644 --- a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt +++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.24) project(cxx_modules_library NONE) -set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112") +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e") find_package(export_bmi_and_interfaces REQUIRED) diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt index 0144b70..b96328f 100644 --- a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt +++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.24) project(cxx_modules_library NONE) -set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112") +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e") find_package(export_bmi_and_interfaces REQUIRED) diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt index bd2f2d4..74f16a6 100644 --- a/Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt +++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.24) project(cxx_modules_library NONE) -set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112") +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e") find_package(export_interfaces REQUIRED) diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt index 87451fe..a4c9225 100644 --- a/Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt +++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.24) project(cxx_modules_library NONE) -set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112") +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e") find_package(export_interfaces REQUIRED) diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/test/CMakeLists.txt index 5b6abc6..7f145ba2 100644 --- a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/test/CMakeLists.txt +++ b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-build/test/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.24) project(cxx_modules_library NONE) -set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112") +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e") find_package(export_interfaces_no_properties REQUIRED) diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/test/CMakeLists.txt index 5b6abc6..7f145ba2 100644 --- a/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/test/CMakeLists.txt +++ b/Tests/RunCMake/CXXModules/examples/export-interface-no-properties-install/test/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.24) project(cxx_modules_library NONE) -set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112") +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e") find_package(export_interfaces_no_properties REQUIRED) diff --git a/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental.cmake b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental.cmake index 84e1802..0826686 100644 --- a/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental.cmake +++ b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental.cmake @@ -1,6 +1,6 @@ enable_language(C) -set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112") +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e") add_library(lib1 STATIC empty.c) target_sources(lib1 PRIVATE FILE_SET UNKNOWN) diff --git a/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental.cmake b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental.cmake index 78e782d..7935178 100644 --- a/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental.cmake +++ b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental.cmake @@ -1,6 +1,6 @@ enable_language(C) -set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "bf70d4b0-9fb7-465c-9803-34014e70d112") +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "a816ed09-43d1-40e5-bc8c-1a2824ee194e") add_library(lib1 STATIC empty.c) target_sources(lib1 PRIVATE FILE_SET a TYPE UNKNOWN) -- cgit v0.12