From 008c09d6db60f7c24781b47414ffa26edbd0e22d Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 17 Nov 2022 15:25:23 -0500 Subject: cmNinjaTargetGenerator: factor out determining the fileset of a source This information is now needed in more than one place, so factor the logic out and use it to build a cache. --- Source/cmNinjaTargetGenerator.cxx | 115 ++++++++++++++++++++++---------------- Source/cmNinjaTargetGenerator.h | 6 ++ 2 files changed, 74 insertions(+), 47 deletions(-) diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index fba0ff9..ce73c17 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -173,6 +173,64 @@ bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang, return lang == "Fortran" || this->NeedCxxModuleSupport(lang, config); } +void cmNinjaTargetGenerator::BuildFileSetInfoCache(std::string const& config) +{ + auto& per_config = this->Configs[config]; + + if (per_config.BuiltFileSetCache) { + return; + } + + auto const* tgt = this->GeneratorTarget->Target; + + for (auto const& name : tgt->GetAllFileSetNames()) { + auto const* file_set = tgt->GetFileSet(name); + if (!file_set) { + this->GetMakefile()->IssueMessage( + MessageType::INTERNAL_ERROR, + cmStrCat("Target \"", tgt->GetName(), + "\" is tracked to have file set \"", name, + "\", but it was not found.")); + continue; + } + + auto fileEntries = file_set->CompileFileEntries(); + auto directoryEntries = file_set->CompileDirectoryEntries(); + auto directories = file_set->EvaluateDirectoryEntries( + directoryEntries, this->LocalGenerator, config, this->GeneratorTarget); + + std::map> files; + for (auto const& entry : fileEntries) { + file_set->EvaluateFileEntry(directories, files, entry, + this->LocalGenerator, config, + this->GeneratorTarget); + } + + for (auto const& it : files) { + for (auto const& filename : it.second) { + per_config.FileSetCache[filename] = file_set; + } + } + } + + per_config.BuiltFileSetCache = true; +} + +cmFileSet const* cmNinjaTargetGenerator::GetFileSetForSource( + std::string const& config, cmSourceFile const* sf) +{ + this->BuildFileSetInfoCache(config); + + auto const& path = sf->GetFullPath(); + auto const& per_config = this->Configs[config]; + + auto const fsit = per_config.FileSetCache.find(path); + if (fsit == per_config.FileSetCache.end()) { + return nullptr; + } + return fsit->second; +} + std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget( const std::string& config) { @@ -256,54 +314,17 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( flags, genexInterpreter.Evaluate(pchOptions, COMPILE_OPTIONS)); } - auto const& path = source->GetFullPath(); - auto const* tgt = this->GeneratorTarget->Target; - - std::string file_set_type; - - for (auto const& name : tgt->GetAllFileSetNames()) { - auto const* file_set = tgt->GetFileSet(name); - if (!file_set) { + auto const* fs = this->GetFileSetForSource(config, source); + if (fs && + (fs->GetType() == "CXX_MODULES"_s || + fs->GetType() == "CXX_MODULE_HEADER_UNITS"_s)) { + if (source->GetLanguage() != "CXX"_s) { this->GetMakefile()->IssueMessage( - MessageType::INTERNAL_ERROR, - cmStrCat("Target \"", tgt->GetName(), - "\" is tracked to have file set \"", name, - "\", but it was not found.")); - continue; - } - - auto fileEntries = file_set->CompileFileEntries(); - auto directoryEntries = file_set->CompileDirectoryEntries(); - auto directories = file_set->EvaluateDirectoryEntries( - directoryEntries, this->LocalGenerator, config, this->GeneratorTarget); - - std::map> files; - for (auto const& entry : fileEntries) { - file_set->EvaluateFileEntry(directories, files, entry, - this->LocalGenerator, config, - this->GeneratorTarget); - } - - for (auto const& it : files) { - for (auto const& filename : it.second) { - if (filename == path) { - file_set_type = file_set->GetType(); - break; - } - } - } - - if (file_set_type == "CXX_MODULES"_s || - file_set_type == "CXX_MODULE_HEADER_UNITS"_s) { - if (source->GetLanguage() != "CXX"_s) { - this->GetMakefile()->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat( - "Target \"", tgt->GetName(), "\" contains the source\n ", path, - "\nin a file set of type \"", file_set_type, - R"(" but the source is not classified as a "CXX" source.)")); - continue; - } + MessageType::FATAL_ERROR, + cmStrCat("Target \"", this->GeneratorTarget->Target->GetName(), + "\" contains the source\n ", source->GetFullPath(), + "\nin a file set of type \"", fs->GetType(), + R"(" but the source is not classified as a "CXX" source.)")); } } diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index c43b650..bb75fb3 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -63,6 +63,10 @@ protected: cmMakefile* GetMakefile() const { return this->Makefile; } + void BuildFileSetInfoCache(std::string const& config); + cmFileSet const* GetFileSetForSource(std::string const& config, + cmSourceFile const* sf); + std::string LanguageCompilerRule(const std::string& lang, const std::string& config) const; std::string LanguagePreprocessAndScanRule(std::string const& lang, @@ -223,6 +227,8 @@ private: std::vector CustomCommands; cmNinjaDeps ExtraFiles; std::unique_ptr MacOSXContentGenerator; + bool BuiltFileSetCache = false; + std::map FileSetCache; }; std::map Configs; -- cgit v0.12 From a02d792c6e9bf9200ab652db6b6da415d80b578c Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 17 Nov 2022 13:50:24 -0500 Subject: cxxmodules: add properties to control scanning The `CXX_SCAN_FOR_MODULES` property may be used to control scanning for targets and for source files rather than assuming "C++20 always needs to be scanned". --- Help/manual/cmake-properties.7.rst | 2 + Help/manual/cmake-variables.7.rst | 1 + Help/prop_sf/CXX_SCAN_FOR_MODULES.rst | 19 ++++++++ Help/prop_tgt/CXX_SCAN_FOR_MODULES.rst | 22 +++++++++ Help/release/dev/cxx-scanning-properties.rst | 5 ++ Help/variable/CMAKE_CXX_SCAN_FOR_MODULES.rst | 10 ++++ Source/cmNinjaTargetGenerator.cxx | 56 ++++++++++++++++++---- Source/cmNinjaTargetGenerator.h | 13 ++++- Source/cmTarget.cxx | 1 + Tests/RunCMake/CXXModules/RunCMakeTest.cmake | 1 + .../CXXModules/examples/scan_properties-stderr.txt | 9 ++++ .../examples/scan_properties/CMakeLists.txt | 54 +++++++++++++++++++++ .../examples/scan_properties/always_scan.cxx | 10 ++++ .../CXXModules/examples/scan_properties/join.cxx | 17 +++++++ .../CXXModules/examples/scan_properties/main.cxx | 16 +++++++ .../CXXModules/examples/scan_properties/module.cxx | 10 ++++ .../examples/scan_properties/never_scan.cxx | 8 ++++ 17 files changed, 245 insertions(+), 9 deletions(-) create mode 100644 Help/prop_sf/CXX_SCAN_FOR_MODULES.rst create mode 100644 Help/prop_tgt/CXX_SCAN_FOR_MODULES.rst create mode 100644 Help/release/dev/cxx-scanning-properties.rst create mode 100644 Help/variable/CMAKE_CXX_SCAN_FOR_MODULES.rst create mode 100644 Tests/RunCMake/CXXModules/examples/scan_properties-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/examples/scan_properties/CMakeLists.txt create mode 100644 Tests/RunCMake/CXXModules/examples/scan_properties/always_scan.cxx create mode 100644 Tests/RunCMake/CXXModules/examples/scan_properties/join.cxx create mode 100644 Tests/RunCMake/CXXModules/examples/scan_properties/main.cxx create mode 100644 Tests/RunCMake/CXXModules/examples/scan_properties/module.cxx create mode 100644 Tests/RunCMake/CXXModules/examples/scan_properties/never_scan.cxx diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index b17be82..e9ee681 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -195,6 +195,7 @@ Properties on Targets /prop_tgt/CXX_MODULE_SET /prop_tgt/CXX_MODULE_SET_NAME /prop_tgt/CXX_MODULE_SETS + /prop_tgt/CXX_SCAN_FOR_MODULES /prop_tgt/CXX_STANDARD /prop_tgt/CXX_STANDARD_REQUIRED /prop_tgt/DEBUG_POSTFIX @@ -533,6 +534,7 @@ Properties on Source Files /prop_sf/COMPILE_DEFINITIONS /prop_sf/COMPILE_FLAGS /prop_sf/COMPILE_OPTIONS + /prop_sf/CXX_SCAN_FOR_MODULES /prop_sf/EXTERNAL_OBJECT /prop_sf/Fortran_FORMAT /prop_sf/Fortran_PREPROCESS diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index cd46615..d66bb2b 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -417,6 +417,7 @@ Variables that Control the Build /variable/CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS /variable/CMAKE_CUDA_RUNTIME_LIBRARY /variable/CMAKE_CUDA_SEPARABLE_COMPILATION + /variable/CMAKE_CXX_SCAN_FOR_MODULES /variable/CMAKE_DEBUG_POSTFIX /variable/CMAKE_DEFAULT_BUILD_TYPE /variable/CMAKE_DEFAULT_CONFIGS diff --git a/Help/prop_sf/CXX_SCAN_FOR_MODULES.rst b/Help/prop_sf/CXX_SCAN_FOR_MODULES.rst new file mode 100644 index 0000000..9d6c0a5 --- /dev/null +++ b/Help/prop_sf/CXX_SCAN_FOR_MODULES.rst @@ -0,0 +1,19 @@ +CXX_SCAN_FOR_MODULES +-------------------- + +.. versionadded:: 3.26 + +``CXX_SCAN_FOR_MODULES`` is a boolean specifying whether CMake will scan the +source for C++ module dependencies. See also the +:prop_tgt:`CXX_SCAN_FOR_MODULES` for target-wide settings. + +When this property is set ``ON``, CMake will scan the source at build time and +add module dependency information to the compile line as necessary. When this +property is set ``OFF``, CMake will not scan the source at build time. When +this property is unset, the :prop_tgt:`CXX_SCAN_FOR_MODULES` property is +consulted. + +Note that scanning is only performed if C++20 or higher is enabled for the +target and the source uses the ``CXX`` language. Scanning for modules in +sources belonging to file sets of type ``CXX_MODULES`` and +``CXX_MODULES_HEADER_UNITS`` is always performed. diff --git a/Help/prop_tgt/CXX_SCAN_FOR_MODULES.rst b/Help/prop_tgt/CXX_SCAN_FOR_MODULES.rst new file mode 100644 index 0000000..5e89ba2 --- /dev/null +++ b/Help/prop_tgt/CXX_SCAN_FOR_MODULES.rst @@ -0,0 +1,22 @@ +CXX_SCAN_FOR_MODULES +-------------------- + +.. versionadded:: 3.26 + +``CXX_SCAN_FOR_MODULES`` is a boolean specifying whether CMake will scan C++ +sources in the target for module dependencies. See also the +:prop_sf:`CXX_SCAN_FOR_MODULES` for per-source settings which, if set, +overrides the target-wide settings. + +This property is initialized by the value of the +:variable:`CMAKE_CXX_SCAN_FOR_MODULES` variable if it is set when a target is +created. + +When this property is set ``ON`` or unset, CMake will scan the target's +``CXX`` sources at build time and add module dependency information to the +compile line as necessary. When this property is set ``OFF``, CMake will not +scan the target's ``CXX`` sources at build time. + +Note that scanning is only performed if C++20 or higher is enabled for the +target. Scanning for modules in the target's sources belonging to file sets +of type ``CXX_MODULES`` and ``CXX_MODULES_HEADER_UNITS`` is always performed. diff --git a/Help/release/dev/cxx-scanning-properties.rst b/Help/release/dev/cxx-scanning-properties.rst new file mode 100644 index 0000000..b393728 --- /dev/null +++ b/Help/release/dev/cxx-scanning-properties.rst @@ -0,0 +1,5 @@ +cxx-scanning-properties +----------------------- + +* The :prop_tgt:`CXX_SCAN_FOR_MODULES` target and source file properties may + be used to enable or disable scanning for C++ module dependencies. diff --git a/Help/variable/CMAKE_CXX_SCAN_FOR_MODULES.rst b/Help/variable/CMAKE_CXX_SCAN_FOR_MODULES.rst new file mode 100644 index 0000000..0d6c636 --- /dev/null +++ b/Help/variable/CMAKE_CXX_SCAN_FOR_MODULES.rst @@ -0,0 +1,10 @@ +CMAKE_CXX_SCAN_FOR_MODULES +-------------------------- + +.. versionadded:: 3.26 + +Whether to scan C++ source files for module dependencies. + +This variable is used to initialize the :prop_tgt:`CXX_SCAN_FOR_MODULES` +property on all the targets. See that target property for additional +information. diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index ce73c17..d39e155 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -109,12 +109,13 @@ cmGlobalNinjaGenerator* cmNinjaTargetGenerator::GetGlobalGenerator() const } std::string cmNinjaTargetGenerator::LanguageCompilerRule( - const std::string& lang, const std::string& config) const + const std::string& lang, const std::string& config, + WithScanning withScanning) const { return cmStrCat( lang, "_COMPILER__", cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()), - '_', config); + withScanning == WithScanning::Yes ? "_scanned_" : "_unscanned_", config); } std::string cmNinjaTargetGenerator::LanguagePreprocessAndScanRule( @@ -231,6 +232,32 @@ cmFileSet const* cmNinjaTargetGenerator::GetFileSetForSource( return fsit->second; } +bool cmNinjaTargetGenerator::NeedDyndepForSource(std::string const& lang, + std::string const& config, + cmSourceFile const* sf) +{ + bool const needDyndep = this->NeedDyndep(lang, config); + if (!needDyndep) { + return false; + } + auto const* fs = this->GetFileSetForSource(config, sf); + if (fs && + (fs->GetType() == "CXX_MODULES"_s || + fs->GetType() == "CXX_MODULE_HEADER_UNITS"_s)) { + return true; + } + auto const sfProp = sf->GetProperty("CXX_SCAN_FOR_MODULES"); + if (sfProp.IsSet()) { + return sfProp.IsOn(); + } + auto const tgtProp = + this->GeneratorTarget->GetProperty("CXX_SCAN_FOR_MODULES"); + if (tgtProp.IsSet()) { + return tgtProp.IsOn(); + } + return true; +} + std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget( const std::string& config) { @@ -671,6 +698,19 @@ cmNinjaRule GetScanRule( void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, const std::string& config) { + // For some cases we scan to dynamically discover dependencies. + bool const needDyndep = this->NeedDyndep(lang, config); + + if (needDyndep) { + this->WriteCompileRule(lang, config, WithScanning::Yes); + } + this->WriteCompileRule(lang, config, WithScanning::No); +} + +void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, + const std::string& config, + WithScanning withScanning) +{ cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); vars.CMTargetType = @@ -690,7 +730,6 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, cmMakefile* mf = this->GetMakefile(); // For some cases we scan to dynamically discover dependencies. - bool const needDyndep = this->NeedDyndep(lang, config); bool const compilationPreprocesses = !this->NeedExplicitPreprocessing(lang); std::string flags = "$FLAGS"; @@ -728,7 +767,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, this->GetLocalGenerator()->ConvertToOutputFormat( cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); - if (needDyndep) { + if (withScanning == WithScanning::Yes) { const auto& scanDepType = this->GetMakefile()->GetSafeDefinition( cmStrCat("CMAKE_EXPERIMENTAL_", lang, "_SCANDEP_DEPFILE_FORMAT")); @@ -834,7 +873,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, this->GetGlobalGenerator()->AddRule(rule); } - cmNinjaRule rule(this->LanguageCompilerRule(lang, config)); + cmNinjaRule rule(this->LanguageCompilerRule(lang, config, withScanning)); // If using a response file, move defines, includes, and flags into it. if (!responseFlag.empty()) { rule.RspFile = "$RSP_FILE"; @@ -888,7 +927,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, } } - if (needDyndep && !modmapFormat.empty()) { + if (withScanning == WithScanning::Yes && !modmapFormat.empty()) { std::string modmapFlags = mf->GetRequiredDefinition( cmStrCat("CMAKE_EXPERIMENTAL_", lang, "_MODULE_MAP_FLAG")); cmSystemTools::ReplaceString(modmapFlags, "", @@ -1348,8 +1387,10 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( !(language == "RC" || (language == "CUDA" && !flag)); int const commandLineLengthLimit = ((lang_supports_response && this->ForceResponseFile())) ? -1 : 0; + bool const needDyndep = this->NeedDyndepForSource(language, config, source); - cmNinjaBuild objBuild(this->LanguageCompilerRule(language, config)); + cmNinjaBuild objBuild(this->LanguageCompilerRule( + language, config, needDyndep ? WithScanning::Yes : WithScanning::No)); cmNinjaVars& vars = objBuild.Variables; vars["FLAGS"] = this->ComputeFlagsForObject(source, language, config); vars["DEFINES"] = this->ComputeDefines(source, language, config); @@ -1458,7 +1499,6 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( } // For some cases we scan to dynamically discover dependencies. - bool const needDyndep = this->NeedDyndep(language, config); bool const compilationPreprocesses = !this->NeedExplicitPreprocessing(language); diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index bb75fb3..d09f04b 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -19,6 +19,7 @@ #include "cmOSXBundleGenerator.h" class cmCustomCommand; +class cmFileSet; class cmGeneratedFileStream; class cmGeneratorTarget; class cmLocalNinjaGenerator; @@ -67,8 +68,14 @@ protected: cmFileSet const* GetFileSetForSource(std::string const& config, cmSourceFile const* sf); + enum class WithScanning + { + No, + Yes, + }; std::string LanguageCompilerRule(const std::string& lang, - const std::string& config) const; + const std::string& config, + WithScanning withScanning) const; std::string LanguagePreprocessAndScanRule(std::string const& lang, const std::string& config) const; std::string LanguageScanRule(std::string const& lang, @@ -76,6 +83,8 @@ protected: std::string LanguageDyndepRule(std::string const& lang, const std::string& config) const; bool NeedDyndep(std::string const& lang, std::string const& config) const; + bool NeedDyndepForSource(std::string const& lang, std::string const& config, + cmSourceFile const* sf); bool NeedExplicitPreprocessing(std::string const& lang) const; bool CompileWithDefines(std::string const& lang) const; bool NeedCxxModuleSupport(std::string const& lang, @@ -154,6 +163,8 @@ protected: const std::string& config); void WriteCompileRule(const std::string& language, const std::string& config); + void WriteCompileRule(const std::string& language, const std::string& config, + WithScanning withScanning); void WriteObjectBuildStatements(const std::string& config, const std::string& fileConfig, bool firstForConfig); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 2955d7c..70a624d 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -526,6 +526,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("ANDROID_ANT_ADDITIONAL_OPTIONS"); initProp("BUILD_RPATH"); initProp("BUILD_RPATH_USE_ORIGIN"); + initProp("CXX_SCAN_FOR_MODULES"); initProp("INSTALL_NAME_DIR"); initProp("INSTALL_REMOVE_ENVIRONMENT_RPATH"); initPropValue("INSTALL_RPATH", ""); diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake index 921fabd..81a086a 100644 --- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake +++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake @@ -138,6 +138,7 @@ if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION) set(RunCMake_CXXModules_NO_TEST 1) run_cxx_module_test(circular) unset(RunCMake_CXXModules_NO_TEST) + run_cxx_module_test(scan_properties) endif () # Tests which use named modules in shared libraries. diff --git a/Tests/RunCMake/CXXModules/examples/scan_properties-stderr.txt b/Tests/RunCMake/CXXModules/examples/scan_properties-stderr.txt new file mode 100644 index 0000000..7d79bad --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/scan_properties-stderr.txt @@ -0,0 +1,9 @@ +CMake Warning \(dev\) at CMakeLists.txt:20 \(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. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/scan_properties/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/scan_properties/CMakeLists.txt new file mode 100644 index 0000000..551c55c --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/scan_properties/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required(VERSION 3.24) +project(scan_properties CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +# To detect that not-to-be scanned sources are not scanned, add a `-D` to the +# scan flags so that the files can detect whether scanning happened and error +# if not. +string(APPEND CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG + " -DCMAKE_SCANNED_THIS_SOURCE") +string(APPEND CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE + " -DCMAKE_SCANNED_THIS_SOURCE") + +set_property(SOURCE always_scan.cxx + PROPERTY CXX_SCAN_FOR_MODULES 1) +set_property(SOURCE never_scan.cxx + PROPERTY CXX_SCAN_FOR_MODULES 0) + +add_executable(scans_everything) +target_sources(scans_everything + PRIVATE + main.cxx + join.cxx + always_scan.cxx + never_scan.cxx + PRIVATE + FILE_SET CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + module.cxx) +target_compile_features(scans_everything PRIVATE cxx_std_20) +target_compile_definitions(scans_everything PRIVATE SCAN_AT_TARGET_LEVEL=1) + +set(CMAKE_CXX_SCAN_FOR_MODULES 0) + +add_executable(no_scan_everything) +target_sources(no_scan_everything + PRIVATE + main.cxx + join.cxx + always_scan.cxx + never_scan.cxx + PRIVATE + FILE_SET CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + module.cxx) +target_compile_features(no_scan_everything PRIVATE cxx_std_20) +target_compile_definitions(no_scan_everything PRIVATE SCAN_AT_TARGET_LEVEL=0) + +add_test(NAME scanned COMMAND scans_everything) +add_test(NAME unscanned COMMAND no_scan_everything) diff --git a/Tests/RunCMake/CXXModules/examples/scan_properties/always_scan.cxx b/Tests/RunCMake/CXXModules/examples/scan_properties/always_scan.cxx new file mode 100644 index 0000000..27087d7 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/scan_properties/always_scan.cxx @@ -0,0 +1,10 @@ +#ifndef CMAKE_SCANNED_THIS_SOURCE +# error "This file should have been scanned" +#endif + +import M; + +int scanned_file() +{ + return from_module(); +} diff --git a/Tests/RunCMake/CXXModules/examples/scan_properties/join.cxx b/Tests/RunCMake/CXXModules/examples/scan_properties/join.cxx new file mode 100644 index 0000000..8184a40 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/scan_properties/join.cxx @@ -0,0 +1,17 @@ +#if SCAN_AT_TARGET_LEVEL +# ifndef CMAKE_SCANNED_THIS_SOURCE +# error "This file should have been scanned" +# endif +#else +# ifdef CMAKE_SCANNED_THIS_SOURCE +# error "This file should not have been scanned" +# endif +#endif + +int scanned_file(); +int never_scan(); + +int join() +{ + return scanned_file() + never_scan(); +} diff --git a/Tests/RunCMake/CXXModules/examples/scan_properties/main.cxx b/Tests/RunCMake/CXXModules/examples/scan_properties/main.cxx new file mode 100644 index 0000000..81e93f4 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/scan_properties/main.cxx @@ -0,0 +1,16 @@ +#if SCAN_AT_TARGET_LEVEL +# ifndef CMAKE_SCANNED_THIS_SOURCE +# error "This file should have been scanned" +# endif +#else +# ifdef CMAKE_SCANNED_THIS_SOURCE +# error "This file should not have been scanned" +# endif +#endif + +int join(); + +int main(int argc, char** argv) +{ + return join(); +} diff --git a/Tests/RunCMake/CXXModules/examples/scan_properties/module.cxx b/Tests/RunCMake/CXXModules/examples/scan_properties/module.cxx new file mode 100644 index 0000000..ad1e04d --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/scan_properties/module.cxx @@ -0,0 +1,10 @@ +#ifndef CMAKE_SCANNED_THIS_SOURCE +# error "This file should have been scanned" +#endif + +export module M; + +export int from_module() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/scan_properties/never_scan.cxx b/Tests/RunCMake/CXXModules/examples/scan_properties/never_scan.cxx new file mode 100644 index 0000000..8374110 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/scan_properties/never_scan.cxx @@ -0,0 +1,8 @@ +#ifdef CMAKE_SCANNED_THIS_SOURCE +# error "This file should not have been scanned" +#endif + +int never_scan() +{ + return 0; +} -- cgit v0.12