diff options
author | Ben Boeckel <ben.boeckel@kitware.com> | 2023-07-19 23:00:05 (GMT) |
---|---|---|
committer | Ben Boeckel <ben.boeckel@kitware.com> | 2023-07-31 15:59:47 (GMT) |
commit | b768d293c5c358dd734234cacab7c34e61c88c54 (patch) | |
tree | c509fe68fab1661f978acd7a07b0aa3132c0d20c | |
parent | 93993c7ad4f634451fb1c8f67f00d4d959d199ac (diff) | |
download | CMake-b768d293c5c358dd734234cacab7c34e61c88c54.zip CMake-b768d293c5c358dd734234cacab7c34e61c88c54.tar.gz CMake-b768d293c5c358dd734234cacab7c34e61c88c54.tar.bz2 |
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
11 files changed, 137 insertions, 21 deletions
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<Arguments>{ 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<Arguments>{ 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<cmTryCompileResult> cmCoreTryCompile::TryCompileCode( cmSystemTools::RemoveFile(ccFile); // Choose sources. - std::vector<std::string> sources; + std::vector<std::pair<std::string, Arguments::SourceType>> 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<cmTryCompileResult> 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<cmTryCompileResult> cmCoreTryCompile::TryCompileCode( // Detect languages to enable. cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); std::set<std::string> 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<cmTryCompileResult> 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 <map> #include <string> +#include <utility> #include <vector> #include <cm/optional> @@ -71,12 +72,17 @@ public: cm::optional<std::string> SourceDirectoryOrFile; cm::optional<std::string> ProjectName; cm::optional<std::string> TargetName; - cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> Sources; - cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> + cm::optional<ArgumentParser::NonEmpty< + std::vector<std::pair<std::string, SourceType>>>> + Sources; + cm::optional<ArgumentParser::NonEmpty< + std::vector<std::pair<std::string, SourceType>>>> SourceFromContent; - cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> + cm::optional<ArgumentParser::NonEmpty< + std::vector<std::pair<std::string, SourceType>>>> SourceFromVar; - cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> + cm::optional<ArgumentParser::NonEmpty< + std::vector<std::pair<std::string, SourceType>>>> SourceFromFile; ArgumentParser::MaybeEmpty<std::vector<std::string>> 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; +} |