diff options
99 files changed, 720 insertions, 416 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4c44b07..24e19c7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -196,6 +196,26 @@ t:debian10-makefiles-clang: variables: CMAKE_CI_JOB_NIGHTLY: "true" +t:fedora37-ninja-clang: + extends: + - .fedora37_ninja_clang + - .cmake_test_linux_release + - .linux_builder_tags_qt + - .run_dependent + - .needs_centos6_x86_64 + variables: + CMAKE_CI_JOB_NIGHTLY: "true" + +t:fedora37-makefiles-clang: + extends: + - .fedora37_makefiles_clang + - .cmake_test_linux_release + - .linux_builder_tags_qt + - .run_dependent + - .needs_centos6_x86_64 + variables: + CMAKE_CI_JOB_NIGHTLY: "true" + t:fedora37-makefiles: extends: - .fedora37_makefiles diff --git a/.gitlab/ci/configure_fedora37_common_clang.cmake b/.gitlab/ci/configure_fedora37_common_clang.cmake new file mode 100644 index 0000000..70c9df9 --- /dev/null +++ b/.gitlab/ci/configure_fedora37_common_clang.cmake @@ -0,0 +1,6 @@ +set(CMAKE_Fortran_COMPILER "/usr/bin/flang-new" CACHE FILEPATH "") +set(CMAKE_Fortran_COMPILER_ID "LLVMFlang" CACHE STRING "") +set(CMAKE_Fortran_COMPILER_SUPPORTS_F90 "1" CACHE BOOL "") +set(CMAKE_Fortran_FLAGS "-flang-experimental-exec" CACHE STRING "") + +include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/.gitlab/ci/configure_fedora37_makefiles_clang.cmake b/.gitlab/ci/configure_fedora37_makefiles_clang.cmake new file mode 100644 index 0000000..7b82a9a --- /dev/null +++ b/.gitlab/ci/configure_fedora37_makefiles_clang.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora37_common_clang.cmake") diff --git a/.gitlab/ci/configure_fedora37_ninja_clang.cmake b/.gitlab/ci/configure_fedora37_ninja_clang.cmake new file mode 100644 index 0000000..7b82a9a --- /dev/null +++ b/.gitlab/ci/configure_fedora37_ninja_clang.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora37_common_clang.cmake") diff --git a/.gitlab/ci/env_fedora37_common_clang.sh b/.gitlab/ci/env_fedora37_common_clang.sh new file mode 100644 index 0000000..b03b757 --- /dev/null +++ b/.gitlab/ci/env_fedora37_common_clang.sh @@ -0,0 +1,4 @@ +export CC=/usr/bin/clang-15 +export CXX=/usr/bin/clang++-15 +export FC=/usr/bin/flang-new +export FFLAGS=-flang-experimental-exec diff --git a/.gitlab/ci/env_fedora37_makefiles_clang.sh b/.gitlab/ci/env_fedora37_makefiles_clang.sh new file mode 100644 index 0000000..9ff1d84 --- /dev/null +++ b/.gitlab/ci/env_fedora37_makefiles_clang.sh @@ -0,0 +1 @@ +. .gitlab/ci/env_fedora37_common_clang.sh diff --git a/.gitlab/ci/env_fedora37_ninja_clang.sh b/.gitlab/ci/env_fedora37_ninja_clang.sh new file mode 100644 index 0000000..9ff1d84 --- /dev/null +++ b/.gitlab/ci/env_fedora37_ninja_clang.sh @@ -0,0 +1 @@ +. .gitlab/ci/env_fedora37_common_clang.sh diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 6a99f33..8fc6ae1 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -200,6 +200,19 @@ variables: CMAKE_CONFIGURATION: debian10_ninja_clang +.fedora37_makefiles_clang: + extends: .fedora37 + + variables: + CMAKE_CONFIGURATION: fedora37_makefiles_clang + CMAKE_GENERATOR: "Unix Makefiles" + +.fedora37_ninja_clang: + extends: .fedora37 + + variables: + CMAKE_CONFIGURATION: fedora37_ninja_clang + ### Sanitizers .fedora_memcheck: diff --git a/Help/manual/cmake-compile-features.7.rst b/Help/manual/cmake-compile-features.7.rst index 8073511..1e87ec6 100644 --- a/Help/manual/cmake-compile-features.7.rst +++ b/Help/manual/cmake-compile-features.7.rst @@ -282,3 +282,25 @@ versions specified for each: * ``Clang``: Clang compiler 5.0+. * ``NVIDIA``: NVIDIA nvcc compiler 7.5+. + +.. _`Language Standard Flags`: + +Language Standard Flags +======================= + +In order to satisfy requirements specified by the +:command:`target_compile_features` command or the +:variable:`CMAKE_<LANG>_STANDARD` variable, CMake may pass a +language standard flag to the compiler, such as ``-std=c++11``. + +For :ref:`Visual Studio Generators`, CMake cannot precisely control +the placement of the language standard flag on the compiler command line. +For :ref:`Ninja Generators`, :ref:`Makefile Generators`, and +:generator:`Xcode`, CMake places the language standard flag just after +the language-wide flags from :variable:`CMAKE_<LANG>_FLAGS` +and :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>`. + +.. versionchanged:: 3.26 + The language standard flag is placed before flags specified by other + abstractions such as the :command:`target_compile_options` command. + Prior to CMake 3.26, the language standard flag was placed after them. 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/release/dev/lang-std-flag-order.rst b/Help/release/dev/lang-std-flag-order.rst new file mode 100644 index 0000000..4ef4123 --- /dev/null +++ b/Help/release/dev/lang-std-flag-order.rst @@ -0,0 +1,7 @@ +lang-std-flag-order +------------------- + +* :ref:`Language Standard Flags`, such as ``-std=c++11``, when generated due + to :command:`target_compile_features` or :variable:`CMAKE_<LANG>_STANDARD`, + are now placed before flags added by :command:`target_compile_options`, + rather than after them. 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/CMakeVersion.cmake b/Source/CMakeVersion.cmake index ee7639f..f239c4c 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 25) -set(CMake_VERSION_PATCH 20221118) +set(CMake_VERSION_PATCH 20221121) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index 0579066..68e7ba3 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -451,7 +451,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, mountpoint_regex.find(attach_output.c_str()); std::string const temp_mount = mountpoint_regex.match(1); std::string const temp_mount_name = - temp_mount.substr(sizeof("/Volumes/") - 1); + temp_mount.substr(cmStrLen("/Volumes/")); // Remove dummy padding file so we have enough space on RW image ... std::ostringstream dummy_padding; diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index bd2b6af..c8e2cb8 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -669,8 +669,7 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression( while ((pos = input.find("$<TARGET_PROPERTY:", lastPos)) != std::string::npos) { - std::string::size_type nameStartPos = - pos + sizeof("$<TARGET_PROPERTY:") - 1; + std::string::size_type nameStartPos = pos + cmStrLen("$<TARGET_PROPERTY:"); std::string::size_type closePos = input.find('>', nameStartPos); std::string::size_type commaPos = input.find(',', nameStartPos); std::string::size_type nextOpenPos = input.find("$<", nameStartPos); @@ -696,7 +695,7 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression( pos = 0; lastPos = pos; while ((pos = input.find("$<TARGET_NAME:", lastPos)) != std::string::npos) { - std::string::size_type nameStartPos = pos + sizeof("$<TARGET_NAME:") - 1; + std::string::size_type nameStartPos = pos + cmStrLen("$<TARGET_NAME:"); std::string::size_type endPos = input.find('>', nameStartPos); if (endPos == std::string::npos) { errorString = "$<TARGET_NAME:...> expression incomplete"; @@ -721,7 +720,7 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression( lastPos = pos; while (errorString.empty() && (pos = input.find("$<LINK_ONLY:", lastPos)) != std::string::npos) { - std::string::size_type nameStartPos = pos + sizeof("$<LINK_ONLY:") - 1; + std::string::size_type nameStartPos = pos + cmStrLen("$<LINK_ONLY:"); std::string::size_type endPos = input.find('>', nameStartPos); if (endPos == std::string::npos) { errorString = "$<LINK_ONLY:...> expression incomplete"; diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index b605350..c5ae31b 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -406,7 +406,7 @@ void cmGeneratorExpression::ReplaceInstallPrefix( while ((pos = input.find("$<INSTALL_PREFIX>", lastPos)) != std::string::npos) { - std::string::size_type endPos = pos + sizeof("$<INSTALL_PREFIX>") - 1; + std::string::size_type endPos = pos + cmStrLen("$<INSTALL_PREFIX>"); input.replace(pos, endPos - pos, replacement); lastPos = endPos; } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 6065285..fae6d54 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -6718,7 +6718,7 @@ bool cmGeneratorTarget::IsLinkLookupScope(std::string const& n, cmLocalGenerator const*& lg) const { if (cmHasLiteralPrefix(n, CMAKE_DIRECTORY_ID_SEP)) { - cmDirectoryId const dirId = n.substr(sizeof(CMAKE_DIRECTORY_ID_SEP) - 1); + cmDirectoryId const dirId = n.substr(cmStrLen(CMAKE_DIRECTORY_ID_SEP)); if (dirId.String.empty()) { lg = this->LocalGenerator; return true; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 9745142..4d5371f 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1021,12 +1021,6 @@ void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, } } - std::string compReqFlag; - this->AddCompilerRequirementFlag(compReqFlag, target, lang, config); - if (!compReqFlag.empty()) { - flags.emplace_back(std::move(compReqFlag)); - } - // Add Warning as errors flags if (!this->GetCMakeInstance()->GetIgnoreWarningAsError()) { const cmValue wError = target->GetProperty("COMPILE_WARNING_AS_ERROR"); @@ -1932,6 +1926,30 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, this->AddConfigVariableFlags(flags, cmStrCat("CMAKE_", lang, "_FLAGS"), config); + // Add the language standard flag for compiling, and sometimes linking. + if (compileOrLink == cmBuildStep::Compile || + (compileOrLink == cmBuildStep::Link && + // Some toolchains require use of the language standard flag + // when linking in order to use the matching standard library. + // FIXME: If CMake gains an abstraction for standard library + // selection, this will have to be reconciled with it. + this->Makefile->IsOn( + cmStrCat("CMAKE_", lang, "_LINK_WITH_STANDARD_COMPILE_OPTION")))) { + cmStandardLevelResolver standardResolver(this->Makefile); + std::string const& optionFlagDef = + standardResolver.GetCompileOptionDef(target, lang, config); + if (!optionFlagDef.empty()) { + cmValue opt = + target->Target->GetMakefile()->GetDefinition(optionFlagDef); + if (opt) { + std::vector<std::string> optVec = cmExpandedList(*opt); + for (std::string const& i : optVec) { + this->AppendFlagEscape(flags, i); + } + } + } + } + std::string compiler = this->Makefile->GetSafeDefinition( cmStrCat("CMAKE_", lang, "_COMPILER_ID")); @@ -2076,15 +2094,6 @@ void cmLocalGenerator::AddLanguageFlagsForLinking( std::string& flags, cmGeneratorTarget const* target, const std::string& lang, const std::string& config) { - if (this->Makefile->IsOn("CMAKE_" + lang + - "_LINK_WITH_STANDARD_COMPILE_OPTION")) { - // This toolchain requires use of the language standard flag - // when linking in order to use the matching standard library. - // FIXME: If CMake gains an abstraction for standard library - // selection, this will have to be reconciled with it. - this->AddCompilerRequirementFlag(flags, target, lang, config); - } - this->AddLanguageFlags(flags, target, cmBuildStep::Link, lang, config); if (target->IsIPOEnabled(lang, config)) { @@ -2224,25 +2233,6 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags, } } -void cmLocalGenerator::AddCompilerRequirementFlag( - std::string& flags, cmGeneratorTarget const* target, const std::string& lang, - const std::string& config) -{ - cmStandardLevelResolver standardResolver(this->Makefile); - - std::string const& optionFlagDef = - standardResolver.GetCompileOptionDef(target, lang, config); - if (!optionFlagDef.empty()) { - cmValue opt = target->Target->GetMakefile()->GetDefinition(optionFlagDef); - if (opt) { - std::vector<std::string> optVec = cmExpandedList(*opt); - for (std::string const& i : optVec) { - this->AppendFlagEscape(flags, i); - } - } - } -} - static void AddVisibilityCompileOption(std::string& flags, cmGeneratorTarget const* target, cmLocalGenerator* lg, diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 765441c..20f23de 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -164,10 +164,6 @@ public: const std::string& lang); void AddConfigVariableFlags(std::string& flags, const std::string& var, const std::string& config); - void AddCompilerRequirementFlag(std::string& flags, - cmGeneratorTarget const* target, - const std::string& lang, - const std::string& config); void AddColorDiagnosticsFlags(std::string& flags, const std::string& lang); //! Append flags to a string. virtual void AppendFlags(std::string& flags, diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index fba0ff9..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( @@ -173,6 +174,90 @@ 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<std::string, std::vector<std::string>> 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; +} + +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) { @@ -256,54 +341,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<std::string, std::vector<std::string>> 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.)")); } } @@ -650,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 = @@ -669,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"; @@ -707,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")); @@ -813,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"; @@ -867,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, "<MODULE_MAP_FILE>", @@ -1327,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); @@ -1437,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 c43b650..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; @@ -63,8 +64,18 @@ protected: cmMakefile* GetMakefile() const { return this->Makefile; } + void BuildFileSetInfoCache(std::string const& config); + 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, @@ -72,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, @@ -150,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); @@ -223,6 +238,8 @@ private: std::vector<cmCustomCommand const*> CustomCommands; cmNinjaDeps ExtraFiles; std::unique_ptr<MacOSXContentGeneratorType> MacOSXContentGenerator; + bool BuiltFileSetCache = false; + std::map<std::string, cmFileSet const*> FileSetCache; }; std::map<std::string, ByConfig> Configs; 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/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 7e43bee..cd73551 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -3293,6 +3293,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( this->GeneratorTarget->GetLanguages(languages, configName); if (languages.count("C")) { std::string flagsC; + this->LocalGenerator->AddLanguageFlags( + flagsC, this->GeneratorTarget, cmBuildStep::Compile, "C", configName); this->LocalGenerator->AddCompileOptions(flagsC, this->GeneratorTarget, "C", configName); Options optC(this->LocalGenerator, Options::Compiler, diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt index bd2dd7e..16e631b 100644 --- a/Tests/CMakeTests/CMakeLists.txt +++ b/Tests/CMakeTests/CMakeLists.txt @@ -32,16 +32,6 @@ AddCMakeTest(ProcessorCount "-DKWSYS_TEST_EXE=$<TARGET_FILE:cmsysTestsCxx>") AddCMakeTest(PushCheckState "") AddCMakeTest(While "") -AddCMakeTest(FileDownload "") -set_tests_properties(CMake.FileDownload PROPERTIES - PASS_REGULAR_EXPRESSION "file already exists with expected MD5 sum" - FAIL_REGULAR_EXPRESSION "Unexpected status|incorrectly interpreted" - ) -AddCMakeTest(FileDownloadBadHash "") -set_property(TEST CMake.FileDownloadBadHash PROPERTY - WILL_FAIL TRUE - ) - AddCMakeTest(FileUpload "") set(EndStuff_PreArgs diff --git a/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in b/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in deleted file mode 100644 index 64b45ed..0000000 --- a/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in +++ /dev/null @@ -1,13 +0,0 @@ -if(NOT "@CMAKE_CURRENT_SOURCE_DIR@" MATCHES "^/") - set(slash /) -endif() -set(url "file://${slash}@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") -set(dir "@CMAKE_CURRENT_BINARY_DIR@/downloads") - -file(DOWNLOAD - ${url} - ${dir}/file3.png - TIMEOUT 2 - STATUS status - EXPECTED_HASH SHA1=5555555555555555555555555555555555555555 - ) diff --git a/Tests/CMakeTests/FileDownloadTest.cmake.in b/Tests/CMakeTests/FileDownloadTest.cmake.in deleted file mode 100644 index 255909d..0000000 --- a/Tests/CMakeTests/FileDownloadTest.cmake.in +++ /dev/null @@ -1,229 +0,0 @@ -# We do not contact any real URLs, but do try a bogus one. -# Remove any proxy configuration that may change behavior. -unset(ENV{http_proxy}) -unset(ENV{https_proxy}) - -set(timeout 4) - -if(NOT "@CMAKE_CURRENT_SOURCE_DIR@" MATCHES "^/") - set(slash /) -endif() -set(url "file://${slash}@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") -set(dir "@CMAKE_CURRENT_BINARY_DIR@/downloads") - -# Beware Windows asynchronous file/directory removal, rename and then -# remove the renamed dir so we can be certain the dir isn't there when -# we get to the file() commands below -if(EXISTS "${dir}") - file(RENAME ${dir} "${dir}_beingRemoved") - file(REMOVE_RECURSE "${dir}_beingRemoved") -endif() - -function(__reportIfWrongStatus statusPair expectedStatusCode) - list(GET statusPair 0 statusCode) - if(NOT statusCode EQUAL expectedStatusCode) - message(SEND_ERROR - "Unexpected status: ${statusCode}, expected: ${expectedStatusCode}") - endif() -endfunction() - -message(STATUS "FileDownload:1") -file(DOWNLOAD - ${url} - ${dir}/file1.png - TIMEOUT ${timeout} - STATUS status - ) -__reportIfWrongStatus("${status}" 0) - -message(STATUS "FileDownload:2") -file(DOWNLOAD - ${url} - ${dir}/file2.png - TIMEOUT ${timeout} - STATUS status - SHOW_PROGRESS - ) -__reportIfWrongStatus("${status}" 0) - -# Two calls in a row, exactly the same arguments. -# Since downloaded file should exist already for 2nd call, -# the 2nd call will short-circuit and return early... -# -if(EXISTS ${dir}/file3.png) - file(REMOVE ${dir}/file3.png) -endif() - -message(STATUS "FileDownload:3") -file(DOWNLOAD - ${url} - ${dir}/file3.png - TIMEOUT ${timeout} - STATUS status - EXPECTED_MD5 dbd330d52f4dbd60115d4191904ded92 - ) -__reportIfWrongStatus("${status}" 0) - -message(STATUS "FileDownload:4") -file(DOWNLOAD - ${url} - ${dir}/file3.png - TIMEOUT ${timeout} - STATUS status - EXPECTED_HASH SHA1=67eee17f79d9ac557284fc0b8ad19f25723fb578 - ) -__reportIfWrongStatus("${status}" 0) - -message(STATUS "FileDownload:5") -file(DOWNLOAD - ${url} - ${dir}/file3.png - TIMEOUT ${timeout} - STATUS status - EXPECTED_HASH SHA224=ba283726bbb602776818b463943189afd91836cb7ee5dd6e2c7b5ae4 - ) -__reportIfWrongStatus("${status}" 0) - -message(STATUS "FileDownload:6") -file(DOWNLOAD - ${url} - ${dir}/file3.png - TIMEOUT ${timeout} - STATUS status - EXPECTED_HASH SHA256=cf3334b1275071e1da6e8c396ccb72cf1b2388d8c937526f3af26230affb9423 - ) -__reportIfWrongStatus("${status}" 0) - -message(STATUS "FileDownload:7") -file(DOWNLOAD - ${url} - ${dir}/file3.png - TIMEOUT ${timeout} - STATUS status - EXPECTED_HASH SHA384=43a5d13978d97c660db44481aee0604cb4ff6ca0775cd5c2cd68cd8000e107e507c4caf6c228941231041e282ffb8950 - ) -__reportIfWrongStatus("${status}" 0) - -message(STATUS "FileDownload:8") -file(DOWNLOAD - ${url} - ${dir}/file3.png - TIMEOUT ${timeout} - STATUS status - EXPECTED_HASH SHA512=6984e0909a1018030ccaa418e3be1654223cdccff0fe6adc745f9aea7e377f178be53b9fc7d54a6f81c2b62ef9ddcd38ba1978fedf4c5e7139baaf355eefad5b - ) -__reportIfWrongStatus("${status}" 0) - -message(STATUS "FileDownload:9") -file(DOWNLOAD - ${url} - ${dir}/file3.png - TIMEOUT ${timeout} - STATUS status - EXPECTED_HASH MD5=dbd330d52f4dbd60115d4191904ded92 - ) -__reportIfWrongStatus("${status}" 0) - -message(STATUS "FileDownload:10") -file(DOWNLOAD - ${url} - ${dir}/file3.png - TIMEOUT ${timeout} - STATUS status - EXPECTED_MD5 dbd330d52f4dbd60115d4191904ded92 - ) -__reportIfWrongStatus("${status}" 0) -# Print status because we check its message too -message(STATUS "${status}") - -# do not use proxy for lookup of invalid site (DNS failure by proxy looks -# different than DNS failure without proxy) -set(ENV{no_proxy} "$ENV{no_proxy},badhostname.invalid") -message(STATUS "FileDownload:11") -file(DOWNLOAD - badhostname.invalid - ${dir}/file11.png - TIMEOUT 30 - STATUS status - ) -message(STATUS "${status}") -__reportIfWrongStatus("${status}" 6) # 6 corresponds to an unresolvable host name - -message(STATUS "FileDownload:12") -set(absFile "@CMAKE_CURRENT_BINARY_DIR@/file12.png") -if(EXISTS "${absFile}") - file(RENAME ${absFile} "${absFile}_beingRemoved") - file(REMOVE "${absFile}_beingRemoved") -endif() -file(DOWNLOAD - ${url} - file12.png - TIMEOUT ${timeout} - EXPECTED_MD5 dbd330d52f4dbd60115d4191904ded92 - STATUS status - ) -__reportIfWrongStatus("${status}" 0) -if(NOT EXISTS file12.png) - message(SEND_ERROR "file12.png not downloaded: ${status}") -endif() - -message(STATUS "FileDownload:13") -file(DOWNLOAD - ${url} - TIMEOUT ${timeout} - STATUS status - ) -__reportIfWrongStatus("${status}" 0) -if(EXISTS TIMEOUT) - file(REMOVE TIMEOUT) - message(SEND_ERROR "TIMEOUT argument was incorrectly interpreted as a filename") -endif() -message(STATUS "${status}") - -message(STATUS "FileDownload:14") -file(DOWNLOAD - ${url} - ${dir}/file14.bin - TIMEOUT ${timeout} - STATUS status - RANGE_START 0 - EXPECTED_MD5 dbd330d52f4dbd60115d4191904ded92 - ) -__reportIfWrongStatus("${status}" 0) - -message(STATUS "FileDownload:15") -file(DOWNLOAD - ${url} - ${dir}/file15.bin - TIMEOUT ${timeout} - STATUS status - RANGE_END 50 - EXPECTED_MD5 8592e5665b839b5d23825dc84c135b61 - ) -__reportIfWrongStatus("${status}" 0) - -message(STATUS "FileDownload:16") -file(DOWNLOAD - ${url} - ${dir}/file16.bin - TIMEOUT ${timeout} - STATUS status - RANGE_START 10 - RANGE_END 50 - EXPECTED_MD5 36cd52681e6c6c8fef85fcd9e86fc30d - ) -__reportIfWrongStatus("${status}" 0) - -message(STATUS "FileDownload:17") -file(DOWNLOAD - ${url} - ${dir}/file17.bin - TIMEOUT ${timeout} - STATUS status - RANGE_START 0 - RANGE_END 50 - RANGE_START 60 - RANGE_END 100 - EXPECTED_MD5 c5c9e74e82d493dd901eecccd659cebc - ) -__reportIfWrongStatus("${status}" 0) diff --git a/Tests/CMakeTests/FileDownloadInput.png b/Tests/CMakeTests/FileUploadInput.png Binary files differindex 9ab565a..9ab565a 100644 --- a/Tests/CMakeTests/FileDownloadInput.png +++ b/Tests/CMakeTests/FileUploadInput.png diff --git a/Tests/CMakeTests/FileUploadTest.cmake.in b/Tests/CMakeTests/FileUploadTest.cmake.in index 0e6f080..7725041 100644 --- a/Tests/CMakeTests/FileUploadTest.cmake.in +++ b/Tests/CMakeTests/FileUploadTest.cmake.in @@ -9,7 +9,7 @@ endif() file(MAKE_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/uploads") -set(filename "@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") +set(filename "@CMAKE_CURRENT_SOURCE_DIR@/FileUploadInput.png") if(NOT "@CMAKE_CURRENT_BINARY_DIR@" MATCHES "^/") set(slash /) endif() diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt index f3d3a73..17f4408 100644 --- a/Tests/CompileFeatures/CMakeLists.txt +++ b/Tests/CompileFeatures/CMakeLists.txt @@ -374,3 +374,16 @@ else() target_link_libraries(CompileFeaturesGenex3 PRIVATE std_11_iface) target_compile_definitions(CompileFeaturesGenex3 PRIVATE ${genex_test_defs} ALLOW_LATER_STANDARDS=1) endif() + +if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" + AND (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.30 + # The MSVC 14.29.30133 toolset supports C++20, + # but MSBuild puts the flags in the wrong order. + OR (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.29.30129 AND NOT CMAKE_GENERATOR MATCHES "Visual Studio") + ) + ) + add_library(msvc_permissive msvc_permissive.cxx) + target_compile_features(msvc_permissive PRIVATE cxx_std_20) + # The `-std:c++20` flag implies `-permissive-`. Test passing `-permissive` afterward. + target_compile_options(msvc_permissive PRIVATE -permissive) +endif() diff --git a/Tests/CompileFeatures/msvc_permissive.cxx b/Tests/CompileFeatures/msvc_permissive.cxx new file mode 100644 index 0000000..a8f2ff3 --- /dev/null +++ b/Tests/CompileFeatures/msvc_permissive.cxx @@ -0,0 +1,9 @@ +#if !defined(_MSVC_LANG) || _MSVC_LANG < 202002L +# error "This source must be compiled with MSVC as C++20 or later." +#endif +// Test a construct that is allowed by MSVC only with 'cl -permissive'. +enum class X +{ + Y = 1 +}; +int array[X::Y]; diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 1174d0d..0fe4919 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -466,6 +466,7 @@ add_RunCMake_test(ctest_fixtures) add_RunCMake_test(define_property) add_RunCMake_test(file -DCYGWIN=${CYGWIN} -DMSYS=${MSYS}) add_RunCMake_test(file-CHMOD -DMSYS=${MSYS}) +add_RunCMake_test(file-DOWNLOAD -DCMake_TEST_NO_NETWORK=${CMake_TEST_NO_NETWORK}) add_RunCMake_test(file-RPATH -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}) add_RunCMake_test(find_file) add_RunCMake_test(find_library -DCYGWIN=${CYGWIN} -DMSYS=${MSYS}) 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; +} diff --git a/Tests/RunCMake/file-DOWNLOAD/CMakeLists.txt b/Tests/RunCMake/file-DOWNLOAD/CMakeLists.txt new file mode 100644 index 0000000..9a66cde --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.13) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/file-DOWNLOAD/EXPECTED_HASH-stdout.txt b/Tests/RunCMake/file-DOWNLOAD/EXPECTED_HASH-stdout.txt new file mode 100644 index 0000000..bd1727a --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/EXPECTED_HASH-stdout.txt @@ -0,0 +1,8 @@ +-- status='0;"No error"' +-- status='0;"skipping download as file already exists with expected MD5 sum"' +-- status='0;"skipping download as file already exists with expected MD5 hash"' +-- status='0;"skipping download as file already exists with expected SHA1 hash"' +-- status='0;"skipping download as file already exists with expected SHA224 hash"' +-- status='0;"skipping download as file already exists with expected SHA256 hash"' +-- status='0;"skipping download as file already exists with expected SHA384 hash"' +-- status='0;"skipping download as file already exists with expected SHA512 hash"' diff --git a/Tests/RunCMake/file-DOWNLOAD/EXPECTED_HASH.cmake b/Tests/RunCMake/file-DOWNLOAD/EXPECTED_HASH.cmake new file mode 100644 index 0000000..dc7f8ff --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/EXPECTED_HASH.cmake @@ -0,0 +1,13 @@ +include(common.cmake) + +# Actually download the file and verify its hash. +file_download(EXPECTED_MD5 dbd330d52f4dbd60115d4191904ded92) + +# Verify that the local file already exists with expected hash. +file_download(EXPECTED_MD5 dbd330d52f4dbd60115d4191904ded92) +file_download(EXPECTED_HASH MD5=dbd330d52f4dbd60115d4191904ded92) +file_download(EXPECTED_HASH SHA1=67eee17f79d9ac557284fc0b8ad19f25723fb578) +file_download(EXPECTED_HASH SHA224=ba283726bbb602776818b463943189afd91836cb7ee5dd6e2c7b5ae4) +file_download(EXPECTED_HASH SHA256=cf3334b1275071e1da6e8c396ccb72cf1b2388d8c937526f3af26230affb9423) +file_download(EXPECTED_HASH SHA384=43a5d13978d97c660db44481aee0604cb4ff6ca0775cd5c2cd68cd8000e107e507c4caf6c228941231041e282ffb8950) +file_download(EXPECTED_HASH SHA512=6984e0909a1018030ccaa418e3be1654223cdccff0fe6adc745f9aea7e377f178be53b9fc7d54a6f81c2b62ef9ddcd38ba1978fedf4c5e7139baaf355eefad5b) diff --git a/Tests/RunCMake/file-DOWNLOAD/RunCMakeTest.cmake b/Tests/RunCMake/file-DOWNLOAD/RunCMakeTest.cmake new file mode 100644 index 0000000..565f440 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/RunCMakeTest.cmake @@ -0,0 +1,26 @@ +include(RunCMake) + +# We do not contact any real URLs, but do try a bogus one. +# Remove any proxy configuration that may change behavior. +unset(ENV{http_proxy}) +unset(ENV{https_proxy}) + +run_cmake(hash-mismatch) +run_cmake(unused-argument) +run_cmake(httpheader-not-set) +run_cmake(netrc-bad) +run_cmake(tls-cainfo-not-set) +run_cmake(tls-verify-not-set) +run_cmake(pass-not-set) +run_cmake(no-save-hash) + +run_cmake(basic) +run_cmake(EXPECTED_HASH) +run_cmake(file-without-path) +run_cmake(no-file) +run_cmake(range) +run_cmake(SHOW_PROGRESS) + +if(NOT CMake_TEST_NO_NETWORK) + run_cmake(bad-hostname) +endif() diff --git a/Tests/RunCMake/file-DOWNLOAD/SHOW_PROGRESS-stdout.txt b/Tests/RunCMake/file-DOWNLOAD/SHOW_PROGRESS-stdout.txt new file mode 100644 index 0000000..e0a4982 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/SHOW_PROGRESS-stdout.txt @@ -0,0 +1,2 @@ +-- \[download 100% complete\] +-- status='0;"No error"' diff --git a/Tests/RunCMake/file-DOWNLOAD/SHOW_PROGRESS.cmake b/Tests/RunCMake/file-DOWNLOAD/SHOW_PROGRESS.cmake new file mode 100644 index 0000000..ccabced --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/SHOW_PROGRESS.cmake @@ -0,0 +1,3 @@ +include(common.cmake) + +file_download(SHOW_PROGRESS) diff --git a/Tests/RunCMake/file-DOWNLOAD/bad-hostname-stdout.txt b/Tests/RunCMake/file-DOWNLOAD/bad-hostname-stdout.txt new file mode 100644 index 0000000..12278e0 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/bad-hostname-stdout.txt @@ -0,0 +1 @@ +-- status='6;"Couldn't resolve host name"' diff --git a/Tests/RunCMake/file-DOWNLOAD/bad-hostname.cmake b/Tests/RunCMake/file-DOWNLOAD/bad-hostname.cmake new file mode 100644 index 0000000..d3b7a28 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/bad-hostname.cmake @@ -0,0 +1,9 @@ +include(common.cmake) + +# Do not use any proxy for lookup of an invalid site. +# DNS failure by proxy looks different than DNS failure without proxy. +set(ENV{no_proxy} "$ENV{no_proxy},badhostname.invalid") + +set(url "badhostname.invalid") + +file_download() diff --git a/Tests/RunCMake/file-DOWNLOAD/basic-stdout.txt b/Tests/RunCMake/file-DOWNLOAD/basic-stdout.txt new file mode 100644 index 0000000..701e995 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/basic-stdout.txt @@ -0,0 +1 @@ +-- status='0;"No error"' diff --git a/Tests/RunCMake/file-DOWNLOAD/basic.cmake b/Tests/RunCMake/file-DOWNLOAD/basic.cmake new file mode 100644 index 0000000..1fd931c --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/basic.cmake @@ -0,0 +1,3 @@ +include(common.cmake) + +file_download() diff --git a/Tests/RunCMake/file-DOWNLOAD/common.cmake b/Tests/RunCMake/file-DOWNLOAD/common.cmake new file mode 100644 index 0000000..6aa2fe6 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/common.cmake @@ -0,0 +1,15 @@ +if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "^/") + set(slash /) +endif() +set(url "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/input.png") +set(file ${CMAKE_CURRENT_BINARY_DIR}/output.png) + +function(file_download) + file(DOWNLOAD "${url}" + ${file} # leave unquoted + TIMEOUT 30 + STATUS status + ${ARGN} + ) + message(STATUS "status='${status}'") +endfunction() diff --git a/Tests/RunCMake/file-DOWNLOAD/file-without-path-stdout.txt b/Tests/RunCMake/file-DOWNLOAD/file-without-path-stdout.txt new file mode 100644 index 0000000..701e995 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/file-without-path-stdout.txt @@ -0,0 +1 @@ +-- status='0;"No error"' diff --git a/Tests/RunCMake/file-DOWNLOAD/file-without-path.cmake b/Tests/RunCMake/file-DOWNLOAD/file-without-path.cmake new file mode 100644 index 0000000..a628423 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/file-without-path.cmake @@ -0,0 +1,10 @@ +include(common.cmake) + +set(file_orig "${file}") +cmake_path(GET file_orig FILENAME file) + +file_download() + +if(NOT EXISTS "${file_orig}") + message(FATAL_ERROR "file not downloaded to expected path:\n ${file_orig}") +endif() diff --git a/Tests/RunCMake/file/DOWNLOAD-tls-verify-not-set-result.txt b/Tests/RunCMake/file-DOWNLOAD/hash-mismatch-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/file/DOWNLOAD-tls-verify-not-set-result.txt +++ b/Tests/RunCMake/file-DOWNLOAD/hash-mismatch-result.txt diff --git a/Tests/RunCMake/file-DOWNLOAD/hash-mismatch-stderr.txt b/Tests/RunCMake/file-DOWNLOAD/hash-mismatch-stderr.txt new file mode 100644 index 0000000..6682794 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/hash-mismatch-stderr.txt @@ -0,0 +1,11 @@ +^CMake Error at hash-mismatch.cmake:[0-9]+ \(file\): + file DOWNLOAD HASH mismatch + + for file: \[.*/Tests/RunCMake/file-DOWNLOAD/hash-mismatch-build/output.png\] + expected hash: \[0123456789abcdef0123456789abcdef01234567\] + actual hash: \[67eee17f79d9ac557284fc0b8ad19f25723fb578\] + +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) ++ +status='1;HASH mismatch: expected: 0123456789abcdef0123456789abcdef01234567 actual: 67eee17f79d9ac557284fc0b8ad19f25723fb578'$ diff --git a/Tests/RunCMake/file-DOWNLOAD/hash-mismatch.cmake b/Tests/RunCMake/file-DOWNLOAD/hash-mismatch.cmake new file mode 100644 index 0000000..e3f91e3 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/hash-mismatch.cmake @@ -0,0 +1,8 @@ +include(common.cmake) + +file(DOWNLOAD ${url} ${file} + EXPECTED_HASH SHA1=0123456789abcdef0123456789abcdef01234567 + TIMEOUT 30 + STATUS status + ) +message("status='${status}'") diff --git a/Tests/RunCMake/file/DOWNLOAD-tls-cainfo-not-set-result.txt b/Tests/RunCMake/file-DOWNLOAD/httpheader-not-set-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/file/DOWNLOAD-tls-cainfo-not-set-result.txt +++ b/Tests/RunCMake/file-DOWNLOAD/httpheader-not-set-result.txt diff --git a/Tests/RunCMake/file/DOWNLOAD-httpheader-not-set-stderr.txt b/Tests/RunCMake/file-DOWNLOAD/httpheader-not-set-stderr.txt index 247923b..3ac5082 100644 --- a/Tests/RunCMake/file/DOWNLOAD-httpheader-not-set-stderr.txt +++ b/Tests/RunCMake/file-DOWNLOAD/httpheader-not-set-stderr.txt @@ -1,4 +1,4 @@ -^CMake Error at DOWNLOAD-httpheader-not-set.cmake:[0-9]+ \(file\): +^CMake Error at httpheader-not-set.cmake:[0-9]+ \(file\): file DOWNLOAD missing string for HTTPHEADER. Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/file/DOWNLOAD-httpheader-not-set.cmake b/Tests/RunCMake/file-DOWNLOAD/httpheader-not-set.cmake index 6efc958..6efc958 100644 --- a/Tests/RunCMake/file/DOWNLOAD-httpheader-not-set.cmake +++ b/Tests/RunCMake/file-DOWNLOAD/httpheader-not-set.cmake diff --git a/Tests/RunCMake/file-DOWNLOAD/input.png b/Tests/RunCMake/file-DOWNLOAD/input.png Binary files differnew file mode 100644 index 0000000..9ab565a --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/input.png diff --git a/Tests/RunCMake/file/DOWNLOAD-pass-not-set-result.txt b/Tests/RunCMake/file-DOWNLOAD/netrc-bad-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/file/DOWNLOAD-pass-not-set-result.txt +++ b/Tests/RunCMake/file-DOWNLOAD/netrc-bad-result.txt diff --git a/Tests/RunCMake/file/DOWNLOAD-netrc-bad-stderr.txt b/Tests/RunCMake/file-DOWNLOAD/netrc-bad-stderr.txt index 96ce62a..61d7c99 100644 --- a/Tests/RunCMake/file/DOWNLOAD-netrc-bad-stderr.txt +++ b/Tests/RunCMake/file-DOWNLOAD/netrc-bad-stderr.txt @@ -1,19 +1,19 @@ -^CMake Error at DOWNLOAD-netrc-bad\.cmake:[0-9]+ \(file\): +^CMake Error at netrc-bad\.cmake:[0-9]+ \(file\): file DOWNLOAD missing level value for NETRC\. Call Stack \(most recent call first\): CMakeLists\.txt:[0-9]+ \(include\) + -CMake Error at DOWNLOAD-netrc-bad\.cmake:[0-9]+ \(file\): +CMake Error at netrc-bad\.cmake:[0-9]+ \(file\): file DOWNLOAD missing file value for NETRC_FILE\. Call Stack \(most recent call first\): CMakeLists\.txt:[0-9]+ \(include\) + -CMake Error at DOWNLOAD-netrc-bad\.cmake:[0-9]+ \(file\): +CMake Error at netrc-bad\.cmake:[0-9]+ \(file\): file NETRC accepts OPTIONAL, IGNORED or REQUIRED but got: INVALID Call Stack \(most recent call first\): CMakeLists\.txt:[0-9]+ \(include\) + -CMake Error at DOWNLOAD-netrc-bad\.cmake:[0-9]+ \(file\): +CMake Error at netrc-bad\.cmake:[0-9]+ \(file\): file NETRC accepts OPTIONAL, IGNORED or REQUIRED but got: FALSE Call Stack \(most recent call first\): CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/file/DOWNLOAD-netrc-bad.cmake b/Tests/RunCMake/file-DOWNLOAD/netrc-bad.cmake index 6a62df9..c62238a 100644 --- a/Tests/RunCMake/file/DOWNLOAD-netrc-bad.cmake +++ b/Tests/RunCMake/file-DOWNLOAD/netrc-bad.cmake @@ -5,11 +5,11 @@ file(DOWNLOAD "" "" NETRC) file(DOWNLOAD "" "" NETRC_FILE) set(CMAKE_NETRC FALSE) file(DOWNLOAD - "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-netrc-bad.txt" + "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/netrc-bad.txt" "${CMAKE_CURRENT_BINARY_DIR}/netrc-bad.txt" NETRC INVALID ) file(DOWNLOAD - "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-netrc-bad.txt" + "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/netrc-bad.txt" "${CMAKE_CURRENT_BINARY_DIR}/netrc-bad.txt" ) diff --git a/Tests/RunCMake/file/DOWNLOAD-unused-argument.txt b/Tests/RunCMake/file-DOWNLOAD/netrc-bad.txt index e69de29..e69de29 100644 --- a/Tests/RunCMake/file/DOWNLOAD-unused-argument.txt +++ b/Tests/RunCMake/file-DOWNLOAD/netrc-bad.txt diff --git a/Tests/RunCMake/file-DOWNLOAD/no-file-arg.cmake b/Tests/RunCMake/file-DOWNLOAD/no-file-arg.cmake new file mode 100644 index 0000000..6520940 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/no-file-arg.cmake @@ -0,0 +1,11 @@ +include(common.cmake) + +set(file "") + +file_download() + +set(file "${CMAKE_CURRENT_BINARY_DIR}/input.png") + +if(NOT EXISTS "${file}") + message(FATAL_ERROR "file not downloaded to expected path:\n ${file}") +endif() diff --git a/Tests/RunCMake/file-DOWNLOAD/no-file-stdout.txt b/Tests/RunCMake/file-DOWNLOAD/no-file-stdout.txt new file mode 100644 index 0000000..701e995 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/no-file-stdout.txt @@ -0,0 +1 @@ +-- status='0;"No error"' diff --git a/Tests/RunCMake/file-DOWNLOAD/no-file.cmake b/Tests/RunCMake/file-DOWNLOAD/no-file.cmake new file mode 100644 index 0000000..dc234b2 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/no-file.cmake @@ -0,0 +1,11 @@ +include(common.cmake) + +# Test downloading without saving to a file. +set(file "") +file_download() + +foreach(name input.png output.png TIMEOUT) + if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/${name}") + message(FATAL_ERROR "file incorrectly saved to:\n ${CMAKE_CURRENT_BINARY_DIR}/${name}") + endif() +endforeach() diff --git a/Tests/RunCMake/file/DOWNLOAD-no-save-hash-result.txt b/Tests/RunCMake/file-DOWNLOAD/no-save-hash-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/file/DOWNLOAD-no-save-hash-result.txt +++ b/Tests/RunCMake/file-DOWNLOAD/no-save-hash-result.txt diff --git a/Tests/RunCMake/file/DOWNLOAD-no-save-hash-stderr.txt b/Tests/RunCMake/file-DOWNLOAD/no-save-hash-stderr.txt index b0f0d19..8f2f885 100644 --- a/Tests/RunCMake/file/DOWNLOAD-no-save-hash-stderr.txt +++ b/Tests/RunCMake/file-DOWNLOAD/no-save-hash-stderr.txt @@ -1,4 +1,5 @@ -^CMake Error at DOWNLOAD-no-save-hash\.cmake:[0-9]+ \(file\): +^CMake Error at common\.cmake:[0-9]+ \(file\): file DOWNLOAD cannot calculate hash if file is not saved\. Call Stack \(most recent call first\): + no-save-hash.cmake:[0-9]+ \(file_download\) CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/file-DOWNLOAD/no-save-hash.cmake b/Tests/RunCMake/file-DOWNLOAD/no-save-hash.cmake new file mode 100644 index 0000000..7fdc397 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/no-save-hash.cmake @@ -0,0 +1,5 @@ +include(common.cmake) + +# Test downloading without saving to a file. +set(file "") +file_download(EXPECTED_HASH MD5=55555555555555555555555555555555) diff --git a/Tests/RunCMake/file/DOWNLOAD-unused-argument-result.txt b/Tests/RunCMake/file-DOWNLOAD/no-save-hash.txt index e69de29..e69de29 100644 --- a/Tests/RunCMake/file/DOWNLOAD-unused-argument-result.txt +++ b/Tests/RunCMake/file-DOWNLOAD/no-save-hash.txt diff --git a/Tests/RunCMake/file/DOWNLOAD-netrc-bad-result.txt b/Tests/RunCMake/file-DOWNLOAD/pass-not-set-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/file/DOWNLOAD-netrc-bad-result.txt +++ b/Tests/RunCMake/file-DOWNLOAD/pass-not-set-result.txt diff --git a/Tests/RunCMake/file/DOWNLOAD-pass-not-set-stderr.txt b/Tests/RunCMake/file-DOWNLOAD/pass-not-set-stderr.txt index 2fa2731..23997c5 100644 --- a/Tests/RunCMake/file/DOWNLOAD-pass-not-set-stderr.txt +++ b/Tests/RunCMake/file-DOWNLOAD/pass-not-set-stderr.txt @@ -1,4 +1,4 @@ -^CMake Error at DOWNLOAD-pass-not-set.cmake:[0-9]+ \(file\): +^CMake Error at pass-not-set.cmake:[0-9]+ \(file\): file DOWNLOAD missing string for USERPWD. Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/file/DOWNLOAD-pass-not-set.cmake b/Tests/RunCMake/file-DOWNLOAD/pass-not-set.cmake index 61eff6d..61eff6d 100644 --- a/Tests/RunCMake/file/DOWNLOAD-pass-not-set.cmake +++ b/Tests/RunCMake/file-DOWNLOAD/pass-not-set.cmake diff --git a/Tests/RunCMake/file-DOWNLOAD/range-stdout.txt b/Tests/RunCMake/file-DOWNLOAD/range-stdout.txt new file mode 100644 index 0000000..e2ed7aa --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/range-stdout.txt @@ -0,0 +1,4 @@ +-- status='0;"No error"' +-- status='0;"No error"' +-- status='0;"No error"' +-- status='0;"No error"' diff --git a/Tests/RunCMake/file-DOWNLOAD/range.cmake b/Tests/RunCMake/file-DOWNLOAD/range.cmake new file mode 100644 index 0000000..f77bb28 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/range.cmake @@ -0,0 +1,15 @@ +include(common.cmake) + +set(file ${CMAKE_CURRENT_BINARY_DIR}/output1.png) +file_download(RANGE_START 0 EXPECTED_MD5 dbd330d52f4dbd60115d4191904ded92) + +set(file ${CMAKE_CURRENT_BINARY_DIR}/output2.png) +file_download(RANGE_END 50 EXPECTED_MD5 8592e5665b839b5d23825dc84c135b61) + +set(file ${CMAKE_CURRENT_BINARY_DIR}/output3.png) +file_download(RANGE_START 10 RANGE_END 50 EXPECTED_MD5 36cd52681e6c6c8fef85fcd9e86fc30d) + +set(file ${CMAKE_CURRENT_BINARY_DIR}/output4.png) +file_download(RANGE_START 0 RANGE_END 50 + RANGE_START 60 RANGE_END 100 + EXPECTED_MD5 c5c9e74e82d493dd901eecccd659cebc) diff --git a/Tests/RunCMake/file/DOWNLOAD-httpheader-not-set-result.txt b/Tests/RunCMake/file-DOWNLOAD/tls-cainfo-not-set-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/file/DOWNLOAD-httpheader-not-set-result.txt +++ b/Tests/RunCMake/file-DOWNLOAD/tls-cainfo-not-set-result.txt diff --git a/Tests/RunCMake/file/DOWNLOAD-tls-cainfo-not-set-stderr.txt b/Tests/RunCMake/file-DOWNLOAD/tls-cainfo-not-set-stderr.txt index 1552baa..d9fa7b7 100644 --- a/Tests/RunCMake/file/DOWNLOAD-tls-cainfo-not-set-stderr.txt +++ b/Tests/RunCMake/file-DOWNLOAD/tls-cainfo-not-set-stderr.txt @@ -1,4 +1,4 @@ -^CMake Error at DOWNLOAD-tls-cainfo-not-set.cmake:[0-9]+ \(file\): +^CMake Error at tls-cainfo-not-set.cmake:[0-9]+ \(file\): file DOWNLOAD missing file value for TLS_CAINFO. Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/file/DOWNLOAD-tls-cainfo-not-set.cmake b/Tests/RunCMake/file-DOWNLOAD/tls-cainfo-not-set.cmake index b476425..b476425 100644 --- a/Tests/RunCMake/file/DOWNLOAD-tls-cainfo-not-set.cmake +++ b/Tests/RunCMake/file-DOWNLOAD/tls-cainfo-not-set.cmake diff --git a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch-result.txt b/Tests/RunCMake/file-DOWNLOAD/tls-verify-not-set-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch-result.txt +++ b/Tests/RunCMake/file-DOWNLOAD/tls-verify-not-set-result.txt diff --git a/Tests/RunCMake/file/DOWNLOAD-tls-verify-not-set-stderr.txt b/Tests/RunCMake/file-DOWNLOAD/tls-verify-not-set-stderr.txt index 2f46c0c..c048ea9 100644 --- a/Tests/RunCMake/file/DOWNLOAD-tls-verify-not-set-stderr.txt +++ b/Tests/RunCMake/file-DOWNLOAD/tls-verify-not-set-stderr.txt @@ -1,4 +1,4 @@ -^CMake Error at DOWNLOAD-tls-verify-not-set.cmake:[0-9]+ \(file\): +^CMake Error at tls-verify-not-set.cmake:[0-9]+ \(file\): file DOWNLOAD missing bool value for TLS_VERIFY. Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/file/DOWNLOAD-tls-verify-not-set.cmake b/Tests/RunCMake/file-DOWNLOAD/tls-verify-not-set.cmake index 919368c..919368c 100644 --- a/Tests/RunCMake/file/DOWNLOAD-tls-verify-not-set.cmake +++ b/Tests/RunCMake/file-DOWNLOAD/tls-verify-not-set.cmake diff --git a/Tests/RunCMake/file/DOWNLOAD-no-save-hash.txt b/Tests/RunCMake/file-DOWNLOAD/unused-argument-result.txt index e69de29..e69de29 100644 --- a/Tests/RunCMake/file/DOWNLOAD-no-save-hash.txt +++ b/Tests/RunCMake/file-DOWNLOAD/unused-argument-result.txt diff --git a/Tests/RunCMake/file/DOWNLOAD-unused-argument-stderr.txt b/Tests/RunCMake/file-DOWNLOAD/unused-argument-stderr.txt index 82a78c9..f7cfc4f 100644 --- a/Tests/RunCMake/file/DOWNLOAD-unused-argument-stderr.txt +++ b/Tests/RunCMake/file-DOWNLOAD/unused-argument-stderr.txt @@ -1,5 +1,6 @@ -^CMake Warning \(dev\) at DOWNLOAD-unused-argument.cmake:[0-9]+ \(file\): +^CMake Warning \(dev\) at common.cmake:[0-9]+ \(file\): Unexpected argument: JUNK Call Stack \(most recent call first\): + unused-argument.cmake:[0-9]+ \(file_download\) CMakeLists.txt:[0-9]+ \(include\) This warning is for project developers. Use -Wno-dev to suppress it.$ diff --git a/Tests/RunCMake/file-DOWNLOAD/unused-argument.cmake b/Tests/RunCMake/file-DOWNLOAD/unused-argument.cmake new file mode 100644 index 0000000..6f7f597 --- /dev/null +++ b/Tests/RunCMake/file-DOWNLOAD/unused-argument.cmake @@ -0,0 +1,3 @@ +include(common.cmake) + +file_download(JUNK) diff --git a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch-stderr.txt b/Tests/RunCMake/file/DOWNLOAD-hash-mismatch-stderr.txt deleted file mode 100644 index 7a356c1..0000000 --- a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch-stderr.txt +++ /dev/null @@ -1,11 +0,0 @@ -^CMake Error at DOWNLOAD-hash-mismatch.cmake:[0-9]+ \(file\): - file DOWNLOAD HASH mismatch - - for file: \[.*/Tests/RunCMake/file/DOWNLOAD-hash-mismatch-build/hash-mismatch.txt\] - expected hash: \[0123456789abcdef0123456789abcdef01234567\] - actual hash: \[da39a3ee5e6b4b0d3255bfef95601890afd80709\] - -Call Stack \(most recent call first\): - CMakeLists.txt:[0-9]+ \(include\) -+ -status='1;HASH mismatch: expected: 0123456789abcdef0123456789abcdef01234567 actual: da39a3ee5e6b4b0d3255bfef95601890afd80709'$ diff --git a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake b/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake deleted file mode 100644 index a91b217..0000000 --- a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake +++ /dev/null @@ -1,10 +0,0 @@ -if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "^/") - set(slash /) -endif() -file(DOWNLOAD - "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-hash-mismatch.txt" - ${CMAKE_CURRENT_BINARY_DIR}/hash-mismatch.txt - EXPECTED_HASH SHA1=0123456789abcdef0123456789abcdef01234567 - STATUS status - ) -message("status='${status}'") diff --git a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.txt b/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.txt deleted file mode 100644 index e69de29..0000000 --- a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.txt +++ /dev/null diff --git a/Tests/RunCMake/file/DOWNLOAD-netrc-bad.txt b/Tests/RunCMake/file/DOWNLOAD-netrc-bad.txt deleted file mode 100644 index e69de29..0000000 --- a/Tests/RunCMake/file/DOWNLOAD-netrc-bad.txt +++ /dev/null diff --git a/Tests/RunCMake/file/DOWNLOAD-no-save-hash.cmake b/Tests/RunCMake/file/DOWNLOAD-no-save-hash.cmake deleted file mode 100644 index ce959a7..0000000 --- a/Tests/RunCMake/file/DOWNLOAD-no-save-hash.cmake +++ /dev/null @@ -1,8 +0,0 @@ -if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "^/") - set(slash /) -endif() -file(DOWNLOAD - "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-no-save-md5.txt" - EXPECTED_HASH MD5=55555555555555555555555555555555 - STATUS status - ) diff --git a/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake b/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake deleted file mode 100644 index 2fa5482..0000000 --- a/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake +++ /dev/null @@ -1,8 +0,0 @@ -if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "^/") - set(slash /) -endif() -file(DOWNLOAD - "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-unused-argument.txt" - "${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt" - JUNK - ) diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index 0c4c174..752f7a0 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -4,14 +4,6 @@ run_cmake(CREATE_LINK) run_cmake(CREATE_LINK-COPY_ON_ERROR) run_cmake(CREATE_LINK-noarg) run_cmake(CREATE_LINK-noexist) -run_cmake(DOWNLOAD-hash-mismatch) -run_cmake(DOWNLOAD-unused-argument) -run_cmake(DOWNLOAD-httpheader-not-set) -run_cmake(DOWNLOAD-netrc-bad) -run_cmake(DOWNLOAD-tls-cainfo-not-set) -run_cmake(DOWNLOAD-tls-verify-not-set) -run_cmake(DOWNLOAD-pass-not-set) -run_cmake(DOWNLOAD-no-save-hash) run_cmake(TOUCH) run_cmake(TOUCH-error-in-source-directory) run_cmake(TOUCH-error-missing-directory) diff --git a/Utilities/ClangTidyModule/Tests/cmake-use-cmstrlen-fixit.cxx b/Utilities/ClangTidyModule/Tests/cmake-use-cmstrlen-fixit.cxx index c93d557..cde0086 100644 --- a/Utilities/ClangTidyModule/Tests/cmake-use-cmstrlen-fixit.cxx +++ b/Utilities/ClangTidyModule/Tests/cmake-use-cmstrlen-fixit.cxx @@ -27,11 +27,16 @@ int main() (void)cmStrLen("Goodbye"); (void)cmStrLen("Hola"); (void)cmStrLen("Bonjour"); + (void)(cmStrLen("Hallo")); + (void)(4 + cmStrLen("Hallo")); + (void)(cmStrLen("Hallo")); + (void)(4 + cmStrLen("Hallo")); // No correction needed (void)ns2::strlen("Salve"); (void)cmStrLen("Konnichiwa"); (void)strlen(s0); + (void)(sizeof("Hallo") - 2); return 0; } diff --git a/Utilities/ClangTidyModule/Tests/cmake-use-cmstrlen-stdout.txt b/Utilities/ClangTidyModule/Tests/cmake-use-cmstrlen-stdout.txt index 6c52ad5..d18822a 100644 --- a/Utilities/ClangTidyModule/Tests/cmake-use-cmstrlen-stdout.txt +++ b/Utilities/ClangTidyModule/Tests/cmake-use-cmstrlen-stdout.txt @@ -18,3 +18,35 @@ cmake-use-cmstrlen.cxx:29:9: warning: use cmStrLen() for string literals [cmake- ^~~~~~~~~~~ cmStrLen cmake-use-cmstrlen.cxx:29:9: note: FIX-IT applied suggested code changes +cmake-use-cmstrlen.cxx:30:10: warning: use cmStrLen() for string literals [cmake-use-cmstrlen] + (void)(sizeof("Hallo") - 1); + ^~~~~~ ~~~ + cmStrLen +cmake-use-cmstrlen.cxx:30:10: note: FIX-IT applied suggested code changes +cmake-use-cmstrlen.cxx:30:26: note: FIX-IT applied suggested code changes + (void)(sizeof("Hallo") - 1); + ^ +cmake-use-cmstrlen.cxx:31:14: warning: use cmStrLen() for string literals [cmake-use-cmstrlen] + (void)(4 + sizeof("Hallo") - 1); + ^~~~~~ ~~~ + cmStrLen +cmake-use-cmstrlen.cxx:31:14: note: FIX-IT applied suggested code changes +cmake-use-cmstrlen.cxx:31:30: note: FIX-IT applied suggested code changes + (void)(4 + sizeof("Hallo") - 1); + ^ +cmake-use-cmstrlen.cxx:32:10: warning: use cmStrLen() for string literals [cmake-use-cmstrlen] + (void)(sizeof "Hallo" - 1); + ^~~~~~ ~~~ + cmStrLen( ) +cmake-use-cmstrlen.cxx:32:10: note: FIX-IT applied suggested code changes +cmake-use-cmstrlen.cxx:32:25: note: FIX-IT applied suggested code changes + (void)(sizeof "Hallo" - 1); + ^ +cmake-use-cmstrlen.cxx:33:14: warning: use cmStrLen() for string literals [cmake-use-cmstrlen] + (void)(4 + sizeof "Hallo" - 1); + ^~~~~~ ~~~ + cmStrLen( ) +cmake-use-cmstrlen.cxx:33:14: note: FIX-IT applied suggested code changes +cmake-use-cmstrlen.cxx:33:29: note: FIX-IT applied suggested code changes + (void)(4 + sizeof "Hallo" - 1); + ^ diff --git a/Utilities/ClangTidyModule/Tests/cmake-use-cmstrlen.cxx b/Utilities/ClangTidyModule/Tests/cmake-use-cmstrlen.cxx index f36262b..205bc9c 100644 --- a/Utilities/ClangTidyModule/Tests/cmake-use-cmstrlen.cxx +++ b/Utilities/ClangTidyModule/Tests/cmake-use-cmstrlen.cxx @@ -27,11 +27,16 @@ int main() (void)::strlen("Goodbye"); (void)std::strlen("Hola"); (void)ns1::strlen("Bonjour"); + (void)(sizeof("Hallo") - 1); + (void)(4 + sizeof("Hallo") - 1); + (void)(sizeof "Hallo" - 1); + (void)(4 + sizeof "Hallo" - 1); // No correction needed (void)ns2::strlen("Salve"); (void)cmStrLen("Konnichiwa"); (void)strlen(s0); + (void)(sizeof("Hallo") - 2); return 0; } diff --git a/Utilities/ClangTidyModule/UseCmstrlenCheck.cxx b/Utilities/ClangTidyModule/UseCmstrlenCheck.cxx index 590d260..d4bae1f 100644 --- a/Utilities/ClangTidyModule/UseCmstrlenCheck.cxx +++ b/Utilities/ClangTidyModule/UseCmstrlenCheck.cxx @@ -17,17 +17,61 @@ UseCmstrlenCheck::UseCmstrlenCheck(StringRef Name, ClangTidyContext* Context) void UseCmstrlenCheck::registerMatchers(MatchFinder* Finder) { Finder->addMatcher(callExpr(callee(functionDecl(hasName("::strlen"))), - callee(expr().bind("callee")), + callee(expr().bind("strlen")), hasArgument(0, stringLiteral())), this); + + auto IsSizeOfStringLiteral = + unaryExprOrTypeTraitExpr( + ofKind(UETT_SizeOf), + anyOf(has(parenExpr(has(stringLiteral())).bind("paren")), + has(stringLiteral()))) + .bind("sizeOf"); + Finder->addMatcher( + binaryOperator( + hasOperatorName("-"), + hasLHS(anyOf( + binaryOperator(hasOperatorName("+"), hasRHS(IsSizeOfStringLiteral)), + IsSizeOfStringLiteral)), + hasRHS(implicitCastExpr(has(integerLiteral(equals(1)).bind("literal"))))) + .bind("sizeOfMinus"), + this); } void UseCmstrlenCheck::check(const MatchFinder::MatchResult& Result) { - const Expr* Node = Result.Nodes.getNodeAs<Expr>("callee"); + const Expr* Strlen = Result.Nodes.getNodeAs<Expr>("strlen"); + const BinaryOperator* SizeOfMinus = + Result.Nodes.getNodeAs<BinaryOperator>("sizeOfMinus"); + + if (Strlen) { + this->diag(Strlen->getBeginLoc(), "use cmStrLen() for string literals") + << FixItHint::CreateReplacement(Strlen->getSourceRange(), "cmStrLen"); + } + + if (SizeOfMinus) { + const ParenExpr* Paren = Result.Nodes.getNodeAs<ParenExpr>("paren"); + const UnaryExprOrTypeTraitExpr* SizeOf = + Result.Nodes.getNodeAs<UnaryExprOrTypeTraitExpr>("sizeOf"); + const IntegerLiteral* Literal = + Result.Nodes.getNodeAs<IntegerLiteral>("literal"); - this->diag(Node->getBeginLoc(), "use cmStrLen() for string literals") - << FixItHint::CreateReplacement(Node->getSourceRange(), "cmStrLen"); + std::vector<FixItHint> FixIts; + if (Paren) { + FixIts.push_back( + FixItHint::CreateReplacement(SizeOf->getOperatorLoc(), "cmStrLen")); + FixIts.push_back(FixItHint::CreateRemoval( + SourceRange(SizeOfMinus->getOperatorLoc(), Literal->getLocation()))); + } else { + FixIts.push_back( + FixItHint::CreateReplacement(SizeOf->getOperatorLoc(), "cmStrLen(")); + FixIts.push_back(FixItHint::CreateReplacement( + SourceRange(SizeOfMinus->getOperatorLoc(), Literal->getLocation()), + ")")); + } + this->diag(SizeOf->getOperatorLoc(), "use cmStrLen() for string literals") + << FixIts; + } } } } |