summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.clang-tidy9
-rw-r--r--.gitlab-ci.yml84
-rw-r--r--.gitlab/ci/configure_fedora36_clang_analyzer.cmake1
-rw-r--r--.gitlab/ci/configure_fedora37_asan.cmake (renamed from .gitlab/ci/configure_fedora36_asan.cmake)2
-rw-r--r--.gitlab/ci/configure_fedora37_clang_analyzer.cmake1
-rw-r--r--.gitlab/ci/configure_fedora37_common.cmake (renamed from .gitlab/ci/configure_fedora36_common.cmake)0
-rw-r--r--.gitlab/ci/configure_fedora37_common_clang.cmake6
-rw-r--r--.gitlab/ci/configure_fedora37_extdeps.cmake (renamed from .gitlab/ci/configure_fedora36_extdeps.cmake)0
-rw-r--r--.gitlab/ci/configure_fedora37_makefiles.cmake (renamed from .gitlab/ci/configure_fedora36_makefiles.cmake)0
-rw-r--r--.gitlab/ci/configure_fedora37_makefiles_clang.cmake1
-rw-r--r--.gitlab/ci/configure_fedora37_ninja.cmake (renamed from .gitlab/ci/configure_fedora36_ninja.cmake)2
-rw-r--r--.gitlab/ci/configure_fedora37_ninja_clang.cmake1
-rw-r--r--.gitlab/ci/configure_fedora37_ninja_multi.cmake (renamed from .gitlab/ci/configure_fedora36_ninja_multi.cmake)0
-rw-r--r--.gitlab/ci/configure_fedora37_sphinx.cmake (renamed from .gitlab/ci/configure_fedora36_sphinx.cmake)0
-rw-r--r--.gitlab/ci/configure_fedora37_sphinx_package.cmake (renamed from .gitlab/ci/configure_fedora36_sphinx_package.cmake)0
-rw-r--r--.gitlab/ci/configure_fedora37_tidy.cmake (renamed from .gitlab/ci/configure_fedora36_tidy.cmake)2
-rw-r--r--.gitlab/ci/ctest_memcheck_fedora37_asan.lsan.supp (renamed from .gitlab/ci/ctest_memcheck_fedora36_asan.lsan.supp)0
-rw-r--r--.gitlab/ci/docker/fedora37/Dockerfile (renamed from .gitlab/ci/docker/fedora36/Dockerfile)8
-rwxr-xr-x.gitlab/ci/docker/fedora37/install_clang_tidy_headers.sh (renamed from .gitlab/ci/docker/fedora36/install_clang_tidy_headers.sh)0
-rwxr-xr-x.gitlab/ci/docker/fedora37/install_deps.sh (renamed from .gitlab/ci/docker/fedora36/install_deps.sh)3
-rwxr-xr-x.gitlab/ci/docker/fedora37/install_iwyu.sh (renamed from .gitlab/ci/docker/fedora36/install_iwyu.sh)0
-rwxr-xr-x.gitlab/ci/docker/fedora37/install_rvm.sh (renamed from .gitlab/ci/docker/fedora36/install_rvm.sh)0
-rw-r--r--.gitlab/ci/env_fedora37_asan.sh (renamed from .gitlab/ci/env_fedora36_asan.sh)0
-rw-r--r--.gitlab/ci/env_fedora37_clang_analyzer.sh (renamed from .gitlab/ci/env_fedora36_clang_analyzer.sh)0
-rw-r--r--.gitlab/ci/env_fedora37_common_clang.sh4
-rw-r--r--.gitlab/ci/env_fedora37_extdeps.sh (renamed from .gitlab/ci/env_fedora36_extdeps.sh)0
-rw-r--r--.gitlab/ci/env_fedora37_makefiles.cmake (renamed from .gitlab/ci/env_fedora36_makefiles.cmake)0
-rw-r--r--.gitlab/ci/env_fedora37_makefiles.sh (renamed from .gitlab/ci/env_fedora36_ninja_multi.sh)0
-rw-r--r--.gitlab/ci/env_fedora37_makefiles_clang.sh1
-rw-r--r--.gitlab/ci/env_fedora37_ninja.sh (renamed from .gitlab/ci/env_fedora36_ninja.sh)0
-rw-r--r--.gitlab/ci/env_fedora37_ninja_clang.sh1
-rw-r--r--.gitlab/ci/env_fedora37_ninja_multi.sh (renamed from .gitlab/ci/env_fedora36_makefiles.sh)0
-rw-r--r--.gitlab/ci/env_fedora37_tidy.sh (renamed from .gitlab/ci/env_fedora36_tidy.sh)0
-rw-r--r--.gitlab/os-linux.yml77
-rw-r--r--.gitlab/upload.yml4
-rw-r--r--Help/command/file.rst11
-rw-r--r--Help/manual/cmake-generator-expressions.7.rst14
-rw-r--r--Help/release/dev/build-local-interface-genex.rst5
-rw-r--r--Modules/CMakeDetermineFortranCompiler.cmake3
-rw-r--r--Modules/CMakeFortranCompiler.cmake.in2
-rw-r--r--Modules/ExternalData.cmake2
-rw-r--r--Modules/FindCUDAToolkit.cmake4
-rw-r--r--Source/CMakeLists.txt1
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CPack/cpack.cxx187
-rw-r--r--Source/CursesDialog/ccmake.cxx38
-rw-r--r--Source/QtDialog/CMakeSetup.cxx35
-rw-r--r--Source/cmCMakePresetsGraphInternal.h2
-rw-r--r--Source/cmCPluginAPI.h2
-rw-r--r--Source/cmDocumentation.cxx169
-rw-r--r--Source/cmDocumentation.h57
-rw-r--r--Source/cmDocumentationEntry.h29
-rw-r--r--Source/cmDocumentationFormatter.cxx234
-rw-r--r--Source/cmDocumentationFormatter.h56
-rw-r--r--Source/cmDocumentationSection.cxx28
-rw-r--r--Source/cmDocumentationSection.h22
-rw-r--r--Source/cmFileCommand.cxx8
-rw-r--r--Source/cmGeneratorExpression.cxx52
-rw-r--r--Source/cmGeneratorExpressionNode.cxx8
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.cxx7
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.h3
-rw-r--r--Source/cmGlobalGeneratorFactory.h23
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx10
-rw-r--r--Source/cmGlobalGhsMultiGenerator.h3
-rw-r--r--Source/cmGlobalJOMMakefileGenerator.cxx8
-rw-r--r--Source/cmGlobalJOMMakefileGenerator.h3
-rw-r--r--Source/cmGlobalMSYSMakefileGenerator.cxx8
-rw-r--r--Source/cmGlobalMSYSMakefileGenerator.h3
-rw-r--r--Source/cmGlobalMinGWMakefileGenerator.cxx8
-rw-r--r--Source/cmGlobalMinGWMakefileGenerator.h3
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.cxx16
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.h3
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx13
-rw-r--r--Source/cmGlobalNinjaGenerator.h5
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx8
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h3
-rw-r--r--Source/cmGlobalVisualStudio11Generator.cxx9
-rw-r--r--Source/cmGlobalVisualStudio12Generator.cxx9
-rw-r--r--Source/cmGlobalVisualStudio14Generator.cxx9
-rw-r--r--Source/cmGlobalVisualStudio9Generator.cxx9
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.cxx25
-rw-r--r--Source/cmGlobalWatcomWMakeGenerator.cxx8
-rw-r--r--Source/cmGlobalWatcomWMakeGenerator.h3
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx11
-rw-r--r--Source/cmGlobalXCodeGenerator.h4
-rw-r--r--Source/cmMessenger.cxx4
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx4
-rw-r--r--Source/cmSystemTools.cxx26
-rw-r--r--Source/cmSystemTools.h8
-rw-r--r--Source/cmVersionConfig.h.in2
-rw-r--r--Source/cmake.cxx292
-rw-r--r--Source/cmake.h35
-rw-r--r--Source/cmakemain.cxx34
-rw-r--r--Source/ctest.cxx30
-rw-r--r--Tests/CMakeTests/CMakeLists.txt10
-rw-r--r--Tests/CMakeTests/FileDownloadBadHashTest.cmake.in13
-rw-r--r--Tests/CMakeTests/FileDownloadTest.cmake.in229
-rw-r--r--Tests/CMakeTests/FileUploadInput.png (renamed from Tests/CMakeTests/FileDownloadInput.png)bin194 -> 194 bytes
-rw-r--r--Tests/CMakeTests/FileUploadTest.cmake.in2
-rw-r--r--Tests/RunCMake/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/ExportImport/BuildInstallInterfaceGenex-export.cmake14
-rw-r--r--Tests/RunCMake/ExportImport/BuildInstallInterfaceGenex-import.cmake9
-rw-r--r--Tests/RunCMake/ExportImport/RunCMakeTest.cmake25
-rw-r--r--Tests/RunCMake/ExportImport/buildlib.c8
-rw-r--r--Tests/RunCMake/ExportImport/installlib.c8
-rw-r--r--Tests/RunCMake/ExportImport/locallib.c8
-rw-r--r--Tests/RunCMake/GenEx-TARGET_PROPERTY/RunCMakeTest.cmake7
-rw-r--r--Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope-build-stdout.txt6
-rw-r--r--Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope.c12
-rw-r--r--Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope.cmake19
-rw-r--r--Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope1/CMakeLists.txt15
-rw-r--r--Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope2/CMakeLists.txt10
-rw-r--r--Tests/RunCMake/Swift/NoWorkToDo-nowork-stdout.txt1
-rw-r--r--Tests/RunCMake/Swift/NoWorkToDo.cmake2
-rw-r--r--Tests/RunCMake/Swift/RunCMakeTest.cmake10
-rw-r--r--Tests/RunCMake/Swift/hello.swift (renamed from Tests/RunCMake/file/DOWNLOAD-unused-argument.txt)0
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/EXPECTED_HASH-stdout.txt8
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/EXPECTED_HASH.cmake13
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/RunCMakeTest.cmake26
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/SHOW_PROGRESS-stdout.txt2
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/SHOW_PROGRESS.cmake3
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/bad-hostname-stdout.txt1
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/bad-hostname.cmake9
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/basic-stdout.txt1
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/basic.cmake3
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/common.cmake15
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/file-without-path-stdout.txt1
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/file-without-path.cmake10
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/hash-mismatch-result.txt (renamed from Tests/RunCMake/file/DOWNLOAD-tls-verify-not-set-result.txt)0
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/hash-mismatch-stderr.txt11
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/hash-mismatch.cmake8
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/httpheader-not-set-result.txt (renamed from Tests/RunCMake/file/DOWNLOAD-tls-cainfo-not-set-result.txt)0
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/httpheader-not-set-stderr.txt (renamed from Tests/RunCMake/file/DOWNLOAD-httpheader-not-set-stderr.txt)2
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/httpheader-not-set.cmake (renamed from Tests/RunCMake/file/DOWNLOAD-httpheader-not-set.cmake)0
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/input.pngbin0 -> 194 bytes
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/netrc-bad-result.txt (renamed from Tests/RunCMake/file/DOWNLOAD-pass-not-set-result.txt)0
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/netrc-bad-stderr.txt (renamed from Tests/RunCMake/file/DOWNLOAD-netrc-bad-stderr.txt)8
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/netrc-bad.cmake (renamed from Tests/RunCMake/file/DOWNLOAD-netrc-bad.cmake)4
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/netrc-bad.txt (renamed from Tests/RunCMake/file/DOWNLOAD-unused-argument-result.txt)0
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/no-file-arg.cmake11
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/no-file-stdout.txt1
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/no-file.cmake11
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/no-save-hash-result.txt (renamed from Tests/RunCMake/file/DOWNLOAD-no-save-hash-result.txt)0
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/no-save-hash-stderr.txt (renamed from Tests/RunCMake/file/DOWNLOAD-no-save-hash-stderr.txt)3
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/no-save-hash.cmake5
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/no-save-hash.txt (renamed from Tests/RunCMake/file/DOWNLOAD-no-save-hash.txt)0
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/pass-not-set-result.txt (renamed from Tests/RunCMake/file/DOWNLOAD-netrc-bad-result.txt)0
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/pass-not-set-stderr.txt (renamed from Tests/RunCMake/file/DOWNLOAD-pass-not-set-stderr.txt)2
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/pass-not-set.cmake (renamed from Tests/RunCMake/file/DOWNLOAD-pass-not-set.cmake)0
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/range-stdout.txt4
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/range.cmake15
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/tls-cainfo-not-set-result.txt (renamed from Tests/RunCMake/file/DOWNLOAD-httpheader-not-set-result.txt)0
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/tls-cainfo-not-set-stderr.txt (renamed from Tests/RunCMake/file/DOWNLOAD-tls-cainfo-not-set-stderr.txt)2
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/tls-cainfo-not-set.cmake (renamed from Tests/RunCMake/file/DOWNLOAD-tls-cainfo-not-set.cmake)0
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/tls-verify-not-set-result.txt (renamed from Tests/RunCMake/file/DOWNLOAD-hash-mismatch-result.txt)0
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/tls-verify-not-set-stderr.txt (renamed from Tests/RunCMake/file/DOWNLOAD-tls-verify-not-set-stderr.txt)2
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/tls-verify-not-set.cmake (renamed from Tests/RunCMake/file/DOWNLOAD-tls-verify-not-set.cmake)0
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/unused-argument-result.txt (renamed from Tests/RunCMake/file/DOWNLOAD-netrc-bad.txt)0
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/unused-argument-stderr.txt (renamed from Tests/RunCMake/file/DOWNLOAD-unused-argument-stderr.txt)3
-rw-r--r--Tests/RunCMake/file-DOWNLOAD/unused-argument.cmake3
-rw-r--r--Tests/RunCMake/file/COPY_FILE-file-INPUT_MAY_BE_RECENT.cmake10
-rw-r--r--Tests/RunCMake/file/DOWNLOAD-hash-mismatch-stderr.txt11
-rw-r--r--Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake10
-rw-r--r--Tests/RunCMake/file/DOWNLOAD-hash-mismatch.txt0
-rw-r--r--Tests/RunCMake/file/DOWNLOAD-no-save-hash.cmake8
-rw-r--r--Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake8
-rw-r--r--Tests/RunCMake/file/RunCMakeTest.cmake9
-rw-r--r--Utilities/ClangTidyModule/CMakeLists.txt2
-rw-r--r--Utilities/ClangTidyModule/Module.cxx2
-rw-r--r--Utilities/ClangTidyModule/Tests/CMakeLists.txt1
-rw-r--r--Utilities/ClangTidyModule/Tests/RunClangTidy.cmake54
-rw-r--r--Utilities/ClangTidyModule/Tests/cmake-use-pragma-once-stdout.txt25
-rw-r--r--Utilities/ClangTidyModule/Tests/cmake-use-pragma-once.cxx5
-rw-r--r--Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-both-fixit.h8
-rw-r--r--Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-both.h10
-rw-r--r--Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-include-guards-fixit.h6
-rw-r--r--Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-include-guards.h9
-rw-r--r--Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-neither-fixit.h5
-rw-r--r--Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-neither.h4
-rw-r--r--Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once.h6
-rw-r--r--Utilities/ClangTidyModule/UsePragmaOnceCheck.cxx325
-rw-r--r--Utilities/ClangTidyModule/UsePragmaOnceCheck.h60
183 files changed, 1771 insertions, 1233 deletions
diff --git a/.clang-tidy b/.clang-tidy
index 7ee8bf0..9ce5f42 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,24 +1,31 @@
---
Checks: "-*,\
bugprone-*,\
+-bugprone-assignment-in-if-condition,\
-bugprone-easily-swappable-parameters,\
-bugprone-implicit-widening-of-multiplication-result,\
-bugprone-macro-parentheses,\
-bugprone-misplaced-widening-cast,\
-bugprone-narrowing-conversions,\
-bugprone-too-small-loop-variable,\
+-bugprone-unchecked-optional-access,\
misc-*,\
+-misc-confusable-identifiers,\
+-misc-const-correctness,\
-misc-no-recursion,\
-misc-non-private-member-variables-in-classes,\
-misc-static-assert,\
modernize-*,\
-modernize-avoid-c-arrays,\
+-modernize-macro-to-enum,\
-modernize-return-braced-init-list,\
+-modernize-use-emplace,\
-modernize-use-nodiscard,\
-modernize-use-noexcept,\
-modernize-use-trailing-return-type,\
-modernize-use-transparent-functors,\
performance-*,\
+-performance-inefficient-vector-operation,\
readability-*,\
-readability-convert-member-functions-to-static,\
-readability-function-cognitive-complexity,\
@@ -28,9 +35,11 @@ readability-*,\
-readability-implicit-bool-conversion,\
-readability-inconsistent-declaration-parameter-name,\
-readability-magic-numbers,\
+-readability-make-member-function-const,\
-readability-named-parameter,\
-readability-redundant-declaration,\
-readability-redundant-member-init,\
+-readability-simplify-boolean-expr,\
-readability-suspicious-call-argument,\
-readability-uppercase-literal-suffix,\
cmake-*,\
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 707756e..24e19c7 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -57,7 +57,7 @@ p:source-package:
p:doc-package:
extends:
- - .fedora36_sphinx_package
+ - .fedora37_sphinx_package
- .cmake_prep_doc_linux
- .linux_builder_tags_qt
- .cmake_doc_artifacts
@@ -105,16 +105,16 @@ l:iwyu-debian10:
- .linux_builder_tags
- .run_automatically
-l:tidy-fedora36:
+l:tidy-fedora37:
extends:
- - .fedora36_tidy
+ - .fedora37_tidy
- .cmake_build_linux
- .linux_builder_tags_qt
- .run_automatically
-l:sphinx-fedora36:
+l:sphinx-fedora37:
extends:
- - .fedora36_sphinx
+ - .fedora37_sphinx
- .cmake_build_linux
- .linux_builder_tags_qt
- .run_automatically
@@ -122,9 +122,9 @@ l:sphinx-fedora36:
CMAKE_CI_JOB_CONTINUOUS: "true"
CMAKE_CI_JOB_HELP: "true"
-l:clang-analyzer-fedora36:
+l:clang-analyzer-fedora37:
extends:
- - .fedora36_clang_analyzer
+ - .fedora37_clang_analyzer
- .cmake_build_linux
- .linux_builder_tags_qt
- .run_automatically
@@ -181,7 +181,7 @@ t:debian10-ninja-clang:
- .debian10_ninja_clang
- .cmake_test_linux_release
- .linux_builder_tags_qt
- - .run_manually
+ - .run_dependent
- .needs_centos6_x86_64
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
@@ -191,22 +191,42 @@ t:debian10-makefiles-clang:
- .debian10_makefiles_clang
- .cmake_test_linux_release
- .linux_builder_tags_qt
- - .run_manually
+ - .run_dependent
+ - .needs_centos6_x86_64
+ 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:fedora36-makefiles:
+t:fedora37-makefiles:
extends:
- - .fedora36_makefiles
+ - .fedora37_makefiles
- .cmake_test_linux_release
- .linux_builder_tags_qt
- .run_dependent
- .needs_centos6_x86_64
-t:fedora36-makefiles-nospace:
+t:fedora37-makefiles-nospace:
extends:
- - .fedora36_makefiles
+ - .fedora37_makefiles
- .cmake_test_linux_release
- .linux_builder_tags_qt
- .cmake_junit_artifacts
@@ -214,7 +234,7 @@ t:fedora36-makefiles-nospace:
- .needs_centos6_x86_64
variables:
GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake-ci"
- CMAKE_CI_BUILD_NAME: fedora36_makefiles_nospace
+ CMAKE_CI_BUILD_NAME: fedora37_makefiles_nospace
CMAKE_CI_JOB_NIGHTLY: "true"
t:cuda9.2-nvidia:
@@ -295,9 +315,9 @@ t:linux-gcc-cxx-modules-ninja-multi:
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
-b:fedora36-ninja:
+b:fedora37-ninja:
extends:
- - .fedora36_ninja
+ - .fedora37_ninja
- .cmake_build_linux
- .cmake_build_artifacts
- .linux_builder_tags_qt
@@ -332,40 +352,40 @@ b:debian10-aarch64-extdeps:
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
-b:fedora36-extdeps:
+b:fedora37-extdeps:
extends:
- - .fedora36_extdeps
+ - .fedora37_extdeps
- .cmake_build_linux_standalone
- .linux_builder_tags
- .run_manually
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
-t:fedora36-ninja:
+t:fedora37-ninja:
extends:
- - .fedora36_ninja
+ - .fedora37_ninja
- .cmake_test_linux
- .linux_builder_tags_x11
- .cmake_test_artifacts
- .run_dependent
dependencies:
- - b:fedora36-ninja
+ - b:fedora37-ninja
needs:
- - b:fedora36-ninja
+ - b:fedora37-ninja
variables:
CMAKE_CI_JOB_CONTINUOUS: "true"
-t:fedora36-ninja-multi:
+t:fedora37-ninja-multi:
extends:
- - .fedora36_ninja_multi
+ - .fedora37_ninja_multi
- .cmake_test_linux_external
- .linux_builder_tags_qt
- .cmake_junit_artifacts
- .run_dependent
dependencies:
- - t:fedora36-ninja
+ - t:fedora37-ninja
needs:
- - t:fedora36-ninja
+ - t:fedora37-ninja
t:intel2016-makefiles:
extends:
@@ -704,9 +724,9 @@ u:linux-aarch64-package:
## Sanitizer builds
-b:fedora36-asan:
+b:fedora37-asan:
extends:
- - .fedora36_asan
+ - .fedora37_asan
- .cmake_build_linux
- .cmake_build_artifacts
- .linux_builder_tags_qt
@@ -714,16 +734,16 @@ b:fedora36-asan:
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
-t:fedora36-asan:
+t:fedora37-asan:
extends:
- - .fedora36_asan
+ - .fedora37_asan
- .cmake_memcheck_linux
- .linux_builder_tags_qt
- .run_dependent
dependencies:
- - b:fedora36-asan
+ - b:fedora37-asan
needs:
- - b:fedora36-asan
+ - b:fedora37-asan
variables:
CMAKE_CI_JOB_NIGHTLY: "true"
diff --git a/.gitlab/ci/configure_fedora36_clang_analyzer.cmake b/.gitlab/ci/configure_fedora36_clang_analyzer.cmake
deleted file mode 100644
index 456936b..0000000
--- a/.gitlab/ci/configure_fedora36_clang_analyzer.cmake
+++ /dev/null
@@ -1 +0,0 @@
-include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora36_common.cmake")
diff --git a/.gitlab/ci/configure_fedora36_asan.cmake b/.gitlab/ci/configure_fedora37_asan.cmake
index 51977d9..363e953 100644
--- a/.gitlab/ci/configure_fedora36_asan.cmake
+++ b/.gitlab/ci/configure_fedora37_asan.cmake
@@ -1,4 +1,4 @@
set(CMAKE_C_FLAGS "-fsanitize=address" CACHE STRING "")
set(CMAKE_CXX_FLAGS "-fsanitize=address" CACHE STRING "")
-include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora36_common.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora37_common.cmake")
diff --git a/.gitlab/ci/configure_fedora37_clang_analyzer.cmake b/.gitlab/ci/configure_fedora37_clang_analyzer.cmake
new file mode 100644
index 0000000..f4c4cdd
--- /dev/null
+++ b/.gitlab/ci/configure_fedora37_clang_analyzer.cmake
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora37_common.cmake")
diff --git a/.gitlab/ci/configure_fedora36_common.cmake b/.gitlab/ci/configure_fedora37_common.cmake
index 4484e26..4484e26 100644
--- a/.gitlab/ci/configure_fedora36_common.cmake
+++ b/.gitlab/ci/configure_fedora37_common.cmake
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_fedora36_extdeps.cmake b/.gitlab/ci/configure_fedora37_extdeps.cmake
index 8e545f5..8e545f5 100644
--- a/.gitlab/ci/configure_fedora36_extdeps.cmake
+++ b/.gitlab/ci/configure_fedora37_extdeps.cmake
diff --git a/.gitlab/ci/configure_fedora36_makefiles.cmake b/.gitlab/ci/configure_fedora37_makefiles.cmake
index 11d1a08..11d1a08 100644
--- a/.gitlab/ci/configure_fedora36_makefiles.cmake
+++ b/.gitlab/ci/configure_fedora37_makefiles.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_fedora36_ninja.cmake b/.gitlab/ci/configure_fedora37_ninja.cmake
index 45d9192..3defa5a 100644
--- a/.gitlab/ci/configure_fedora36_ninja.cmake
+++ b/.gitlab/ci/configure_fedora37_ninja.cmake
@@ -10,4 +10,4 @@ set(CMAKE_CXX_FLAGS_RELEASE "-O3" CACHE STRING "")
# Cover compilation with C++11 only and not higher standards.
set(CMAKE_CXX_STANDARD "11" CACHE STRING "")
-include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora36_common.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora37_common.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/configure_fedora36_ninja_multi.cmake b/.gitlab/ci/configure_fedora37_ninja_multi.cmake
index 94af721..94af721 100644
--- a/.gitlab/ci/configure_fedora36_ninja_multi.cmake
+++ b/.gitlab/ci/configure_fedora37_ninja_multi.cmake
diff --git a/.gitlab/ci/configure_fedora36_sphinx.cmake b/.gitlab/ci/configure_fedora37_sphinx.cmake
index 90d159b..90d159b 100644
--- a/.gitlab/ci/configure_fedora36_sphinx.cmake
+++ b/.gitlab/ci/configure_fedora37_sphinx.cmake
diff --git a/.gitlab/ci/configure_fedora36_sphinx_package.cmake b/.gitlab/ci/configure_fedora37_sphinx_package.cmake
index e839de8..e839de8 100644
--- a/.gitlab/ci/configure_fedora36_sphinx_package.cmake
+++ b/.gitlab/ci/configure_fedora37_sphinx_package.cmake
diff --git a/.gitlab/ci/configure_fedora36_tidy.cmake b/.gitlab/ci/configure_fedora37_tidy.cmake
index 2d0eeeb..f8eb9ab 100644
--- a/.gitlab/ci/configure_fedora36_tidy.cmake
+++ b/.gitlab/ci/configure_fedora37_tidy.cmake
@@ -2,4 +2,4 @@ set(CMake_RUN_CLANG_TIDY ON CACHE BOOL "")
set(CMake_USE_CLANG_TIDY_MODULE ON CACHE BOOL "")
set(CMake_CLANG_TIDY_MODULE "$ENV{CI_PROJECT_DIR}/Utilities/ClangTidyModule/build/libcmake-clang-tidy-module.so" CACHE FILEPATH "")
-include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora36_common.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/configure_fedora37_common.cmake")
diff --git a/.gitlab/ci/ctest_memcheck_fedora36_asan.lsan.supp b/.gitlab/ci/ctest_memcheck_fedora37_asan.lsan.supp
index 8ec1a03..8ec1a03 100644
--- a/.gitlab/ci/ctest_memcheck_fedora36_asan.lsan.supp
+++ b/.gitlab/ci/ctest_memcheck_fedora37_asan.lsan.supp
diff --git a/.gitlab/ci/docker/fedora36/Dockerfile b/.gitlab/ci/docker/fedora37/Dockerfile
index ea42561..13ef9aa 100644
--- a/.gitlab/ci/docker/fedora36/Dockerfile
+++ b/.gitlab/ci/docker/fedora37/Dockerfile
@@ -1,22 +1,22 @@
-FROM fedora:36 as rvm-build
+FROM fedora:37 as rvm-build
MAINTAINER Ben Boeckel <ben.boeckel@kitware.com>
COPY install_rvm.sh /root/install_rvm.sh
RUN sh /root/install_rvm.sh
-FROM fedora:36 AS clang-tidy-headers
+FROM fedora:37 AS clang-tidy-headers
MAINTAINER Kyle Edwards <kyle.edwards@kitware.com>
COPY install_clang_tidy_headers.sh /root/install_clang_tidy_headers.sh
RUN sh /root/install_clang_tidy_headers.sh
-FROM fedora:36 AS iwyu
+FROM fedora:37 AS iwyu
MAINTAINER Kyle Edwards <kyle.edwards@kitware.com>
COPY install_iwyu.sh /root/install_iwyu.sh
RUN sh /root/install_iwyu.sh
-FROM fedora:36
+FROM fedora:37
MAINTAINER Ben Boeckel <ben.boeckel@kitware.com>
COPY install_deps.sh /root/install_deps.sh
diff --git a/.gitlab/ci/docker/fedora36/install_clang_tidy_headers.sh b/.gitlab/ci/docker/fedora37/install_clang_tidy_headers.sh
index b9883f4..b9883f4 100755
--- a/.gitlab/ci/docker/fedora36/install_clang_tidy_headers.sh
+++ b/.gitlab/ci/docker/fedora37/install_clang_tidy_headers.sh
diff --git a/.gitlab/ci/docker/fedora36/install_deps.sh b/.gitlab/ci/docker/fedora37/install_deps.sh
index f117888..afb8560 100755
--- a/.gitlab/ci/docker/fedora36/install_deps.sh
+++ b/.gitlab/ci/docker/fedora37/install_deps.sh
@@ -11,8 +11,11 @@ dnf install --setopt=install_weak_deps=False -y \
# Install development tools.
dnf install --setopt=install_weak_deps=False -y \
+ clang \
clang-tools-extra \
compiler-rt \
+ flang \
+ flang-devel \
gcc-c++ \
git-core \
make
diff --git a/.gitlab/ci/docker/fedora36/install_iwyu.sh b/.gitlab/ci/docker/fedora37/install_iwyu.sh
index 714bcc0..714bcc0 100755
--- a/.gitlab/ci/docker/fedora36/install_iwyu.sh
+++ b/.gitlab/ci/docker/fedora37/install_iwyu.sh
diff --git a/.gitlab/ci/docker/fedora36/install_rvm.sh b/.gitlab/ci/docker/fedora37/install_rvm.sh
index 0011f87..0011f87 100755
--- a/.gitlab/ci/docker/fedora36/install_rvm.sh
+++ b/.gitlab/ci/docker/fedora37/install_rvm.sh
diff --git a/.gitlab/ci/env_fedora36_asan.sh b/.gitlab/ci/env_fedora37_asan.sh
index e976486..e976486 100644
--- a/.gitlab/ci/env_fedora36_asan.sh
+++ b/.gitlab/ci/env_fedora37_asan.sh
diff --git a/.gitlab/ci/env_fedora36_clang_analyzer.sh b/.gitlab/ci/env_fedora37_clang_analyzer.sh
index d732c0b..d732c0b 100644
--- a/.gitlab/ci/env_fedora36_clang_analyzer.sh
+++ b/.gitlab/ci/env_fedora37_clang_analyzer.sh
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_fedora36_extdeps.sh b/.gitlab/ci/env_fedora37_extdeps.sh
index 7076e18..7076e18 100644
--- a/.gitlab/ci/env_fedora36_extdeps.sh
+++ b/.gitlab/ci/env_fedora37_extdeps.sh
diff --git a/.gitlab/ci/env_fedora36_makefiles.cmake b/.gitlab/ci/env_fedora37_makefiles.cmake
index 2bcb6d0..2bcb6d0 100644
--- a/.gitlab/ci/env_fedora36_makefiles.cmake
+++ b/.gitlab/ci/env_fedora37_makefiles.cmake
diff --git a/.gitlab/ci/env_fedora36_ninja_multi.sh b/.gitlab/ci/env_fedora37_makefiles.sh
index 217ff30..217ff30 100644
--- a/.gitlab/ci/env_fedora36_ninja_multi.sh
+++ b/.gitlab/ci/env_fedora37_makefiles.sh
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_fedora36_ninja.sh b/.gitlab/ci/env_fedora37_ninja.sh
index 217ff30..217ff30 100644
--- a/.gitlab/ci/env_fedora36_ninja.sh
+++ b/.gitlab/ci/env_fedora37_ninja.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/ci/env_fedora36_makefiles.sh b/.gitlab/ci/env_fedora37_ninja_multi.sh
index 217ff30..217ff30 100644
--- a/.gitlab/ci/env_fedora36_makefiles.sh
+++ b/.gitlab/ci/env_fedora37_ninja_multi.sh
diff --git a/.gitlab/ci/env_fedora36_tidy.sh b/.gitlab/ci/env_fedora37_tidy.sh
index f9f08a3..f9f08a3 100644
--- a/.gitlab/ci/env_fedora36_tidy.sh
+++ b/.gitlab/ci/env_fedora37_tidy.sh
diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml
index 84950d2..8fc6ae1 100644
--- a/.gitlab/os-linux.yml
+++ b/.gitlab/os-linux.yml
@@ -5,7 +5,7 @@
### Release
.linux_prep_source:
- image: "fedora:36"
+ image: "fedora:37"
variables:
GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci"
@@ -68,8 +68,8 @@
### Fedora
-.fedora36:
- image: "kitware/cmake:ci-fedora36-x86_64-2022-10-04"
+.fedora37:
+ image: "kitware/cmake:ci-fedora37-x86_64-2022-11-16"
variables:
GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci/long file name for testing purposes"
@@ -77,37 +77,37 @@
#### Lint builds
-.fedora36_tidy:
- extends: .fedora36
+.fedora37_tidy:
+ extends: .fedora37
variables:
- CMAKE_CONFIGURATION: fedora36_tidy
+ CMAKE_CONFIGURATION: fedora37_tidy
CTEST_NO_WARNINGS_ALLOWED: 1
CMAKE_CI_NO_INSTALL: 1
-.fedora36_clang_analyzer:
- extends: .fedora36
+.fedora37_clang_analyzer:
+ extends: .fedora37
variables:
- CMAKE_CONFIGURATION: fedora36_clang_analyzer
+ CMAKE_CONFIGURATION: fedora37_clang_analyzer
CMAKE_CI_BUILD_TYPE: Debug
CTEST_NO_WARNINGS_ALLOWED: 1
CMAKE_CI_NO_INSTALL: 1
-.fedora36_sphinx:
- extends: .fedora36
+.fedora37_sphinx:
+ extends: .fedora37
variables:
- CMAKE_CONFIGURATION: fedora36_sphinx
+ CMAKE_CONFIGURATION: fedora37_sphinx
CTEST_NO_WARNINGS_ALLOWED: 1
CTEST_SOURCE_SUBDIRECTORY: "Utilities/Sphinx"
CMAKE_CI_NO_INSTALL: 1
-.fedora36_sphinx_package:
- extends: .fedora36
+.fedora37_sphinx_package:
+ extends: .fedora37
variables:
- CMAKE_CONFIGURATION: fedora36_sphinx_package
+ CMAKE_CONFIGURATION: fedora37_sphinx_package
CTEST_SOURCE_SUBDIRECTORY: "Utilities/Sphinx"
#### Build and test
@@ -153,35 +153,35 @@
CMAKE_CI_BUILD_TYPE: Release
CTEST_NO_WARNINGS_ALLOWED: 1
-.fedora36_extdeps:
- extends: .fedora36
+.fedora37_extdeps:
+ extends: .fedora37
variables:
- CMAKE_CONFIGURATION: fedora36_extdeps
+ CMAKE_CONFIGURATION: fedora37_extdeps
CMAKE_CI_BUILD_TYPE: Release
CTEST_NO_WARNINGS_ALLOWED: 1
-.fedora36_ninja:
- extends: .fedora36
+.fedora37_ninja:
+ extends: .fedora37
variables:
- CMAKE_CONFIGURATION: fedora36_ninja
+ CMAKE_CONFIGURATION: fedora37_ninja
CMAKE_CI_BUILD_TYPE: Release
CTEST_NO_WARNINGS_ALLOWED: 1
-.fedora36_ninja_multi:
- extends: .fedora36
+.fedora37_ninja_multi:
+ extends: .fedora37
variables:
- CMAKE_CONFIGURATION: fedora36_ninja_multi
+ CMAKE_CONFIGURATION: fedora37_ninja_multi
CTEST_NO_WARNINGS_ALLOWED: 1
CMAKE_GENERATOR: "Ninja Multi-Config"
-.fedora36_makefiles:
- extends: .fedora36
+.fedora37_makefiles:
+ extends: .fedora37
variables:
- CMAKE_CONFIGURATION: fedora36_makefiles
+ CMAKE_CONFIGURATION: fedora37_makefiles
CTEST_NO_WARNINGS_ALLOWED: 1
CMAKE_GENERATOR: "Unix Makefiles"
@@ -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:
@@ -213,13 +226,13 @@
CTEST_MEMORYCHECK_TYPE: AddressSanitizer
CTEST_MEMORYCHECK_SANITIZER_OPTIONS: ""
-.fedora36_asan:
+.fedora37_asan:
extends:
- - .fedora36
+ - .fedora37
- .fedora_asan_addon
variables:
- CMAKE_CONFIGURATION: fedora36_asan
+ CMAKE_CONFIGURATION: fedora37_asan
### Intel Compiler
@@ -437,7 +450,7 @@
.cmake_codespell_linux:
stage: build
- extends: .fedora36
+ extends: .fedora37
script:
- codespell
interruptible: true
@@ -580,7 +593,7 @@
.cmake_org_help:
stage: build
extends:
- - .fedora36
+ - .fedora37
- .linux_builder_tags
- .cmake_org_help_artifacts
script:
diff --git a/.gitlab/upload.yml b/.gitlab/upload.yml
index 38d40a9..27a6ab7 100644
--- a/.gitlab/upload.yml
+++ b/.gitlab/upload.yml
@@ -1,7 +1,7 @@
# Steps for uploading artifacts
.rsync_upload_package:
- image: "fedora:36"
+ image: "fedora:37"
stage: upload
tags:
- cmake
@@ -21,7 +21,7 @@
.rsync_upload_help:
stage: upload
- image: "fedora:36"
+ image: "fedora:37"
tags:
- cmake
- docker
diff --git a/Help/command/file.rst b/Help/command/file.rst
index 2348937..df895d0 100644
--- a/Help/command/file.rst
+++ b/Help/command/file.rst
@@ -750,7 +750,8 @@ The options are:
file(COPY_FILE <oldname> <newname>
[RESULT <result>]
- [ONLY_IF_DIFFERENT])
+ [ONLY_IF_DIFFERENT]
+ [INPUT_MAY_BE_RECENT])
.. versionadded:: 3.21
@@ -769,6 +770,14 @@ The options are:
contents are already the same as ``<oldname>`` (this avoids updating
``<newname>``'s timestamp).
+``INPUT_MAY_BE_RECENT``
+ .. versionadded:: 3.26
+
+ Tell CMake that the input file may have been recently created. This is
+ meaningful only on Windows, where files may be inaccessible for a short
+ time after they are created. With this option, if permission is denied,
+ CMake will retry reading the input a few times.
+
This sub-command has some similarities to :command:`configure_file` with the
``COPYONLY`` option. An important difference is that :command:`configure_file`
creates a dependency on the source file, so CMake will be re-run if it changes.
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index faa793f..a72eac1 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -1401,6 +1401,13 @@ In the following, the phrase "the ``tgt`` filename" means the name of the
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
+ .. versionchanged:: 3.26
+ When encountered during evaluation of :ref:`Target Usage Requirements`,
+ typically in an ``INTERFACE_*`` target property, lookup of the ``tgt``
+ name occurs in the directory of the target specifying the requirement,
+ rather than the directory of the consuming target for which the
+ expression is being evaluated.
+
.. genex:: $<TARGET_PROPERTY:prop>
Value of the property ``prop`` on the target for which the expression
@@ -1704,6 +1711,13 @@ Export And Install Expressions
when the target is used by another target in the same buildsystem. Expands to
the empty string otherwise.
+.. genex:: $<BUILD_LOCAL_INTERFACE:...>
+
+ .. versionadded:: 3.26
+
+ Content of ``...`` when the target is used by another target in the same
+ buildsystem. Expands to the empty string otherwise.
+
.. genex:: $<INSTALL_PREFIX>
Content of the install prefix when the target is exported via
diff --git a/Help/release/dev/build-local-interface-genex.rst b/Help/release/dev/build-local-interface-genex.rst
new file mode 100644
index 0000000..7fe702e
--- /dev/null
+++ b/Help/release/dev/build-local-interface-genex.rst
@@ -0,0 +1,5 @@
+build-local-interface-genex
+---------------------------
+
+* The :genex:`BUILD_LOCAL_INTERFACE` generator expression was added to
+ prevent usage requirements from being exported to dependent projects.
diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake
index 087c0f6..d169012 100644
--- a/Modules/CMakeDetermineFortranCompiler.cmake
+++ b/Modules/CMakeDetermineFortranCompiler.cmake
@@ -284,6 +284,9 @@ if(MSVC_Fortran_ARCHITECTURE_ID)
set(SET_MSVC_Fortran_ARCHITECTURE_ID
"set(MSVC_Fortran_ARCHITECTURE_ID ${MSVC_Fortran_ARCHITECTURE_ID})")
endif()
+if(CMAKE_Fortran_COMPILER_ID STREQUAL "NVHPC")
+ set(CMAKE_Fortran_VENDOR_SOURCE_FILE_EXTENSIONS ";cuf;CUF")
+endif()
# configure variables set in this file for fast reload later on
configure_file(${CMAKE_ROOT}/Modules/CMakeFortranCompiler.cmake.in
${CMAKE_PLATFORM_INFO_DIR}/CMakeFortranCompiler.cmake
diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in
index 97f891e..f52ad02 100644
--- a/Modules/CMakeFortranCompiler.cmake.in
+++ b/Modules/CMakeFortranCompiler.cmake.in
@@ -25,7 +25,7 @@ set(CMAKE_Fortran_COMPILER_ENV_VAR "FC")
set(CMAKE_Fortran_COMPILER_SUPPORTS_F90 @CMAKE_Fortran_COMPILER_SUPPORTS_F90@)
set(CMAKE_Fortran_COMPILER_ID_RUN 1)
-set(CMAKE_Fortran_SOURCE_FILE_EXTENSIONS f;F;fpp;FPP;f77;F77;f90;F90;for;For;FOR;f95;F95)
+set(CMAKE_Fortran_SOURCE_FILE_EXTENSIONS f;F;fpp;FPP;f77;F77;f90;F90;for;For;FOR;f95;F95@CMAKE_Fortran_VENDOR_SOURCE_FILE_EXTENSIONS@)
set(CMAKE_Fortran_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
set(CMAKE_Fortran_LINKER_PREFERENCE 20)
if(UNIX)
diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
index 189374b..6826c7b 100644
--- a/Modules/ExternalData.cmake
+++ b/Modules/ExternalData.cmake
@@ -945,7 +945,7 @@ function(_ExternalData_link_or_copy src dst)
file(CREATE_LINK "${tgt}" "${tmp}" RESULT result COPY_ON_ERROR SYMBOLIC)
else()
# Create a copy.
- file(COPY_FILE "${src}" "${tmp}" RESULT result)
+ file(COPY_FILE "${src}" "${tmp}" RESULT result INPUT_MAY_BE_RECENT)
endif()
if(result)
file(REMOVE "${tmp}")
diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake
index 365b72a..62e54c8 100644
--- a/Modules/FindCUDAToolkit.cmake
+++ b/Modules/FindCUDAToolkit.cmake
@@ -1060,7 +1060,9 @@ if(CUDAToolkit_FOUND)
if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 11.1.0)
if(NOT TARGET CUDA::nvptxcompiler_static)
_CUDAToolkit_find_and_add_import_lib(nvptxcompiler_static DEPS cuda_driver)
- target_link_libraries(CUDA::nvptxcompiler_static INTERFACE Threads::Threads)
+ if(TARGET CUDA::nvptxcompiler_static)
+ target_link_libraries(CUDA::nvptxcompiler_static INTERFACE Threads::Threads)
+ endif()
endif()
endif()
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index c268a92..c0709c6 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -196,7 +196,6 @@ add_library(
cmDependsCompiler.h
cmDocumentation.cxx
cmDocumentationFormatter.cxx
- cmDocumentationSection.cxx
cmDynamicLoader.cxx
cmDynamicLoader.h
cmELF.h
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 20d3508..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 20221117)
+set(CMake_VERSION_PATCH 20221121)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index f06946b..c228f07 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -5,10 +5,12 @@
#include <cstddef>
#include <functional>
#include <iostream>
+#include <iterator>
#include <map>
#include <memory>
#include <sstream>
#include <string>
+#include <type_traits>
#include <utility>
#include <vector>
@@ -25,7 +27,6 @@
#include "cmConsoleBuf.h"
#include "cmDocumentation.h"
#include "cmDocumentationEntry.h"
-#include "cmDocumentationFormatter.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmState.h"
@@ -36,19 +37,14 @@
#include "cmake.h"
namespace {
-const char* cmDocumentationName[][2] = {
- { nullptr, " cpack - Packaging driver provided by CMake." },
- { nullptr, nullptr }
+const cmDocumentationEntry cmDocumentationName = {
+ {},
+ " cpack - Packaging driver provided by CMake."
};
-const char* cmDocumentationUsage[][2] = {
- // clang-format off
- { nullptr, " cpack [options]" },
- { nullptr, nullptr }
- // clang-format on
-};
+const cmDocumentationEntry cmDocumentationUsage = { {}, " cpack [options]" };
-const char* cmDocumentationOptions[][2] = {
+const cmDocumentationEntry cmDocumentationOptions[14] = {
{ "-G <generators>", "Override/define CPACK_GENERATOR" },
{ "-C <Configuration>", "Specify the project configuration" },
{ "-D <var>=<value>", "Set a CPack variable." },
@@ -62,14 +58,30 @@ const char* cmDocumentationOptions[][2] = {
{ "-B <packageDirectory>", "Override/define CPACK_PACKAGE_DIRECTORY" },
{ "--vendor <vendorName>", "Override/define CPACK_PACKAGE_VENDOR" },
{ "--preset", "Read arguments from a package preset" },
- { "--list-presets", "List available package presets" },
- { nullptr, nullptr }
+ { "--list-presets", "List available package presets" }
};
void cpackProgressCallback(const std::string& message, float /*unused*/)
{
- std::cout << "-- " << message << std::endl;
+ std::cout << "-- " << message << '\n';
}
+
+std::vector<cmDocumentationEntry> makeGeneratorDocs(
+ const cmCPackGeneratorFactory& gf)
+{
+ const auto& generators = gf.GetGeneratorsList();
+
+ std::vector<cmDocumentationEntry> docs;
+ docs.reserve(generators.size());
+
+ std::transform(
+ generators.cbegin(), generators.cend(), std::back_inserter(docs),
+ [](const std::decay<decltype(generators)>::type::value_type& gen) {
+ return cmDocumentationEntry{ gen.first, gen.second };
+ });
+ return docs;
+}
+
} // namespace
// this is CPack.
@@ -101,8 +113,7 @@ int main(int argc, char const* const* argv)
if (cmSystemTools::GetCurrentWorkingDirectory().empty()) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "Current working directory cannot be established."
- << std::endl);
+ "Current working directory cannot be established.\n");
return 1;
}
@@ -129,14 +140,14 @@ int main(int argc, char const* const* argv)
auto const verboseLambda = [&log](const std::string&, cmake*,
cmMakefile*) -> bool {
log.SetVerbose(true);
- cmCPack_Log(&log, cmCPackLog::LOG_OUTPUT, "Enable Verbose" << std::endl);
+ cmCPack_Log(&log, cmCPackLog::LOG_OUTPUT, "Enable Verbose\n");
return true;
};
auto const debugLambda = [&log](const std::string&, cmake*,
cmMakefile*) -> bool {
log.SetDebug(true);
- cmCPack_Log(&log, cmCPackLog::LOG_OUTPUT, "Enable Debug" << std::endl);
+ cmCPack_Log(&log, cmCPackLog::LOG_OUTPUT, "Enable Debug\n");
return true;
};
@@ -194,26 +205,25 @@ int main(int argc, char const* const* argv)
CommandArgument::setToValue(preset) },
CommandArgument{ "--list-presets", CommandArgument::Values::Zero,
CommandArgument::setToTrue(listPresets) },
- CommandArgument{
- "-D", CommandArgument::Values::One,
- [&log, &definitions](const std::string& arg, cmake*,
- cmMakefile*) -> bool {
- std::string value = arg;
- size_t pos = value.find_first_of('=');
- if (pos == std::string::npos) {
- cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "Please specify CPack definitions as: KEY=VALUE"
- << std::endl);
- return false;
- }
- std::string key = value.substr(0, pos);
- value.erase(0, pos + 1);
- definitions[key] = value;
- cmCPack_Log(&log, cmCPackLog::LOG_DEBUG,
- "Set CPack variable: " << key << " to \"" << value << "\""
- << std::endl);
- return true;
- } },
+ CommandArgument{ "-D", CommandArgument::Values::One,
+ [&log, &definitions](const std::string& arg, cmake*,
+ cmMakefile*) -> bool {
+ std::string value = arg;
+ size_t pos = value.find_first_of('=');
+ if (pos == std::string::npos) {
+ cmCPack_Log(
+ &log, cmCPackLog::LOG_ERROR,
+ "Please specify CPack definitions as: KEY=VALUE\n");
+ return false;
+ }
+ std::string key = value.substr(0, pos);
+ value.erase(0, pos + 1);
+ definitions[key] = value;
+ cmCPack_Log(&log, cmCPackLog::LOG_DEBUG,
+ "Set CPack variable: " << key << " to \""
+ << value << "\"\n");
+ return true;
+ } },
};
cmake cminst(cmake::RoleScript, cmState::CPack);
@@ -262,8 +272,7 @@ int main(int argc, char const* const* argv)
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Could not read presets from "
<< workingDirectory << ": "
- << cmCMakePresetsGraph::ResultToString(result)
- << std::endl);
+ << cmCMakePresetsGraph::ResultToString(result) << '\n');
return 1;
}
@@ -276,7 +285,7 @@ int main(int argc, char const* const* argv)
if (presetPair == presetsGraph.PackagePresets.end()) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"No such package preset in " << workingDirectory << ": \""
- << preset << '"' << std::endl);
+ << preset << "\"\n");
presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
return 1;
}
@@ -284,8 +293,7 @@ int main(int argc, char const* const* argv)
if (presetPair->second.Unexpanded.Hidden) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Cannot use hidden package preset in "
- << workingDirectory << ": \"" << preset << '"'
- << std::endl);
+ << workingDirectory << ": \"" << preset << "\"\n");
presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
return 1;
}
@@ -294,7 +302,7 @@ int main(int argc, char const* const* argv)
if (!expandedPreset) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Could not evaluate package preset \""
- << preset << "\": Invalid macro expansion" << std::endl);
+ << preset << "\": Invalid macro expansion\n");
presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
return 1;
}
@@ -302,8 +310,7 @@ int main(int argc, char const* const* argv)
if (!expandedPreset->ConditionResult) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Cannot use disabled package preset in "
- << workingDirectory << ": \"" << preset << '"'
- << std::endl);
+ << workingDirectory << ": \"" << preset << "\"\n");
presetsGraph.PrintPackagePresetList(presetGeneratorsPresent);
return 1;
}
@@ -320,7 +327,7 @@ int main(int argc, char const* const* argv)
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"No such configure preset in "
<< workingDirectory << ": \""
- << expandedPreset->ConfigurePreset << '"' << std::endl);
+ << expandedPreset->ConfigurePreset << "\"\n");
presetsGraph.PrintConfigurePresetList();
return 1;
}
@@ -329,7 +336,7 @@ int main(int argc, char const* const* argv)
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Cannot use hidden configure preset in "
<< workingDirectory << ": \""
- << expandedPreset->ConfigurePreset << '"' << std::endl);
+ << expandedPreset->ConfigurePreset << "\"\n");
presetsGraph.PrintConfigurePresetList();
return 1;
}
@@ -339,7 +346,7 @@ int main(int argc, char const* const* argv)
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Could not evaluate configure preset \""
<< expandedPreset->ConfigurePreset
- << "\": Invalid macro expansion" << std::endl);
+ << "\": Invalid macro expansion\n");
return 1;
}
@@ -395,7 +402,7 @@ int main(int argc, char const* const* argv)
}
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
- "Read CPack config file: " << cpackConfigFile << std::endl);
+ "Read CPack config file: " << cpackConfigFile << '\n');
bool cpackConfigFileSpecified = true;
if (cpackConfigFile.empty()) {
@@ -423,7 +430,7 @@ int main(int argc, char const* const* argv)
globalMF.GetModulesFile("CMakeDetermineSystem.cmake");
if (!globalMF.ReadListFile(systemFile)) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "Error reading CMakeDetermineSystem.cmake" << std::endl);
+ "Error reading CMakeDetermineSystem.cmake\n");
return 1;
}
@@ -431,8 +438,7 @@ int main(int argc, char const* const* argv)
globalMF.GetModulesFile("CMakeSystemSpecificInformation.cmake");
if (!globalMF.ReadListFile(systemFile)) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "Error reading CMakeSystemSpecificInformation.cmake"
- << std::endl);
+ "Error reading CMakeSystemSpecificInformation.cmake\n");
return 1;
}
@@ -444,17 +450,17 @@ int main(int argc, char const* const* argv)
cpackConfigFile = cmSystemTools::CollapseFullPath(cpackConfigFile);
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
"Read CPack configuration file: " << cpackConfigFile
- << std::endl);
+ << '\n');
if (!globalMF.ReadListFile(cpackConfigFile)) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "Problem reading CPack config file: \""
- << cpackConfigFile << "\"" << std::endl);
+ "Problem reading CPack config file: \"" << cpackConfigFile
+ << "\"\n");
return 1;
}
} else if (cpackConfigFileSpecified) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Cannot find CPack config file: \"" << cpackConfigFile
- << "\"" << std::endl);
+ << "\"\n");
return 1;
}
@@ -503,17 +509,17 @@ int main(int argc, char const* const* argv)
cmValue genList = globalMF.GetDefinition("CPACK_GENERATOR");
if (!genList) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "CPack generator not specified" << std::endl);
+ "CPack generator not specified\n");
} else {
std::vector<std::string> generatorsVector = cmExpandedList(*genList);
for (std::string const& gen : generatorsVector) {
cmMakefile::ScopePushPop raii(&globalMF);
cmMakefile* mf = &globalMF;
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
- "Specified generator: " << gen << std::endl);
+ "Specified generator: " << gen << '\n');
if (!mf->GetDefinition("CPACK_PACKAGE_NAME")) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "CPack project name not specified" << std::endl);
+ "CPack project name not specified" << '\n');
parsed = false;
}
if (parsed &&
@@ -522,13 +528,11 @@ int main(int argc, char const* const* argv)
mf->GetDefinition("CPACK_PACKAGE_VERSION_MINOR") &&
mf->GetDefinition("CPACK_PACKAGE_VERSION_PATCH")))) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "CPack project version not specified"
- << std::endl
- << "Specify CPACK_PACKAGE_VERSION, or "
- "CPACK_PACKAGE_VERSION_MAJOR, "
- "CPACK_PACKAGE_VERSION_MINOR, and "
- "CPACK_PACKAGE_VERSION_PATCH."
- << std::endl);
+ "CPack project version not specified\n"
+ "Specify CPACK_PACKAGE_VERSION, or "
+ "CPACK_PACKAGE_VERSION_MAJOR, "
+ "CPACK_PACKAGE_VERSION_MINOR, and "
+ "CPACK_PACKAGE_VERSION_PATCH.\n");
parsed = false;
}
if (parsed) {
@@ -539,19 +543,12 @@ int main(int argc, char const* const* argv)
cpackGenerator->SetTraceExpand(cminst.GetTraceExpand());
} else {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "Could not create CPack generator: " << gen
- << std::endl);
+ "Could not create CPack generator: " << gen << '\n');
// Print out all the valid generators
cmDocumentation generatorDocs;
- std::vector<cmDocumentationEntry> v;
- for (auto const& g : generators.GetGeneratorsList()) {
- cmDocumentationEntry e;
- e.Name = g.first;
- e.Brief = g.second;
- v.push_back(std::move(e));
- }
- generatorDocs.SetSection("Generators", v);
- std::cerr << "\n";
+ generatorDocs.SetSection("Generators",
+ makeGeneratorDocs(generators));
+ std::cerr << '\n';
generatorDocs.PrintDocumentation(cmDocumentation::ListGenerators,
std::cerr);
parsed = false;
@@ -559,8 +556,7 @@ int main(int argc, char const* const* argv)
if (parsed && !cpackGenerator->Initialize(gen, mf)) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
- "Cannot initialize the generator " << gen
- << std::endl);
+ "Cannot initialize the generator " << gen << '\n');
parsed = false;
}
@@ -573,17 +569,16 @@ int main(int argc, char const* const* argv)
"Please specify build tree of the project that uses CMake "
"using CPACK_INSTALL_CMAKE_PROJECTS, specify "
"CPACK_INSTALL_COMMANDS, CPACK_INSTALL_SCRIPT, or "
- "CPACK_INSTALLED_DIRECTORIES."
- << std::endl);
+ "CPACK_INSTALLED_DIRECTORIES.\n");
parsed = false;
}
if (parsed) {
cmValue projName = mf->GetDefinition("CPACK_PACKAGE_NAME");
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
"Use generator: " << cpackGenerator->GetNameOfClass()
- << std::endl);
+ << '\n');
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
- "For project: " << *projName << std::endl);
+ "For project: " << *projName << '\n');
cmValue projVersion = mf->GetDefinition("CPACK_PACKAGE_VERSION");
if (!projVersion) {
@@ -594,7 +589,7 @@ int main(int argc, char const* const* argv)
cmValue projVersionPatch =
mf->GetDefinition("CPACK_PACKAGE_VERSION_PATCH");
std::ostringstream ostr;
- ostr << *projVersionMajor << "." << *projVersionMinor << "."
+ ostr << *projVersionMajor << "." << *projVersionMinor << '.'
<< *projVersionPatch;
mf->AddDefinition("CPACK_PACKAGE_VERSION", ostr.str());
}
@@ -603,7 +598,7 @@ int main(int argc, char const* const* argv)
if (!res) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Error when generating package: " << *projName
- << std::endl);
+ << '\n');
return 1;
}
}
@@ -618,27 +613,13 @@ int main(int argc, char const* const* argv)
*/
if (help) {
// Construct and print requested documentation.
-
doc.SetName("cpack");
doc.SetSection("Name", cmDocumentationName);
doc.SetSection("Usage", cmDocumentationUsage);
doc.PrependSection("Options", cmDocumentationOptions);
-
- std::vector<cmDocumentationEntry> v;
- for (auto const& g : generators.GetGeneratorsList()) {
- cmDocumentationEntry e;
- e.Name = g.first;
- e.Brief = g.second;
- v.push_back(std::move(e));
- }
- doc.SetSection("Generators", v);
-
- return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1;
- }
-
- if (cmSystemTools::GetErrorOccurredFlag()) {
- return 1;
+ doc.SetSection("Generators", makeGeneratorDocs(generators));
+ return !doc.PrintRequestedDocumentation(std::cout);
}
- return 0;
+ return int(cmSystemTools::GetErrorOccurredFlag());
}
diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx
index 70ed648..18c1a80 100644
--- a/Source/CursesDialog/ccmake.cxx
+++ b/Source/CursesDialog/ccmake.cxx
@@ -16,45 +16,38 @@
#include "cmCursesMainForm.h"
#include "cmCursesStandardIncludes.h"
#include "cmDocumentation.h"
-#include "cmDocumentationEntry.h" // IWYU pragma: keep
+#include "cmDocumentationEntry.h"
#include "cmMessageMetadata.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
-static const char* cmDocumentationName[][2] = {
- { nullptr, " ccmake - Curses Interface for CMake." },
- { nullptr, nullptr }
+namespace {
+const cmDocumentationEntry cmDocumentationName = {
+ {},
+ " ccmake - Curses Interface for CMake."
};
-static const char* cmDocumentationUsage[][2] = {
- { nullptr,
+const cmDocumentationEntry cmDocumentationUsage[2] = {
+ { {},
" ccmake <path-to-source>\n"
" ccmake <path-to-existing-build>" },
- { nullptr,
+ { {},
"Specify a source directory to (re-)generate a build system for "
"it in the current working directory. Specify an existing build "
"directory to re-generate its build system." },
- { nullptr, nullptr }
};
-static const char* cmDocumentationUsageNote[][2] = {
- { nullptr, "Run 'ccmake --help' for more information." },
- { nullptr, nullptr }
+const cmDocumentationEntry cmDocumentationUsageNote = {
+ {},
+ "Run 'ccmake --help' for more information."
};
-static const char* cmDocumentationOptions[][2] = {
- CMAKE_STANDARD_OPTIONS_TABLE,
- { nullptr, nullptr }
-};
-
-cmCursesForm* cmCursesForm::CurrentForm = nullptr;
-
#ifndef _WIN32
extern "C" {
-static void onsig(int /*unused*/)
+void onsig(int /*unused*/)
{
if (cmCursesForm::CurrentForm) {
cmCursesForm::CurrentForm->HandleResize();
@@ -63,6 +56,9 @@ static void onsig(int /*unused*/)
}
}
#endif // _WIN32
+} // anonymous namespace
+
+cmCursesForm* cmCursesForm::CurrentForm = nullptr;
int main(int argc, char const* const* argv)
{
@@ -89,8 +85,8 @@ int main(int argc, char const* const* argv)
doc.AppendSection("Usage", cmDocumentationUsageNote);
}
doc.AppendSection("Generators", generators);
- doc.PrependSection("Options", cmDocumentationOptions);
- return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1;
+ doc.PrependSection("Options", cmake::CMAKE_STANDARD_OPTIONS_TABLE);
+ return !doc.PrintRequestedDocumentation(std::cout);
}
bool debug = false;
diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
index 591b793..50e8e3a 100644
--- a/Source/QtDialog/CMakeSetup.cxx
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -22,26 +22,27 @@
#include "cmSystemTools.h" // IWYU pragma: keep
#include "cmake.h"
-static const char* cmDocumentationName[][2] = { { nullptr,
- " cmake-gui - CMake GUI." },
- { nullptr, nullptr } };
-
-static const char* cmDocumentationUsage[][2] = {
- { nullptr,
- " cmake-gui [options]\n"
- " cmake-gui [options] <path-to-source>\n"
- " cmake-gui [options] <path-to-existing-build>\n"
- " cmake-gui [options] -S <path-to-source> -B <path-to-build>\n"
- " cmake-gui [options] --browse-manual\n" },
- { nullptr, nullptr }
+namespace {
+const cmDocumentationEntry cmDocumentationName = {
+ {},
+ " cmake-gui - CMake GUI."
};
-static const char* cmDocumentationOptions[][2] = {
+const cmDocumentationEntry cmDocumentationUsage = {
+ {},
+ " cmake-gui [options]\n"
+ " cmake-gui [options] <path-to-source>\n"
+ " cmake-gui [options] <path-to-existing-build>\n"
+ " cmake-gui [options] -S <path-to-source> -B <path-to-build>\n"
+ " cmake-gui [options] --browse-manual"
+};
+
+const cmDocumentationEntry cmDocumentationOptions[3] = {
{ "-S <path-to-source>", "Explicitly specify a source directory." },
{ "-B <path-to-build>", "Explicitly specify a build directory." },
- { "--preset=<preset>", "Specify a configure preset." },
- { nullptr, nullptr }
+ { "--preset=<preset>", "Specify a configure preset." }
};
+} // anonymous namespace
#if defined(Q_OS_MAC)
static int cmOSXInstall(std::string dir);
@@ -91,7 +92,7 @@ int main(int argc, char** argv)
doc.AppendSection("Generators", generators);
doc.PrependSection("Options", cmDocumentationOptions);
- return (doc.PrintRequestedDocumentation(std::cout) ? 0 : 1);
+ return !doc.PrintRequestedDocumentation(std::cout);
}
#if defined(Q_OS_MAC)
@@ -252,6 +253,7 @@ int main(int argc, char** argv)
# include <unistd.h>
# include "cm_sys_stat.h"
+
static bool cmOSXInstall(std::string const& dir, std::string const& tool)
{
if (tool.empty()) {
@@ -277,6 +279,7 @@ static bool cmOSXInstall(std::string const& dir, std::string const& tool)
<< "': " << strerror(err) << "\n";
return false;
}
+
static int cmOSXInstall(std::string dir)
{
if (!cmHasLiteralSuffix(dir, "/")) {
diff --git a/Source/cmCMakePresetsGraphInternal.h b/Source/cmCMakePresetsGraphInternal.h
index 9e47a69..2726e92 100644
--- a/Source/cmCMakePresetsGraphInternal.h
+++ b/Source/cmCMakePresetsGraphInternal.h
@@ -1,5 +1,7 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
#include <memory>
#include <string>
#include <vector>
diff --git a/Source/cmCPluginAPI.h b/Source/cmCPluginAPI.h
index 19626f0..0d8a366 100644
--- a/Source/cmCPluginAPI.h
+++ b/Source/cmCPluginAPI.h
@@ -8,7 +8,7 @@
loosely into four groups 1) Utility 2) cmMakefile 3) cmSourceFile 4)
cmSystemTools. Within each grouping functions are listed alphabetically */
/*=========================================================================*/
-#ifndef cmCPluginAPI_h
+#ifndef cmCPluginAPI_h /* NOLINT(cmake-use-pragma-once) */
#define cmCPluginAPI_h
#define CMAKE_VERSION_MAJOR 2
diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx
index d466a12..77c5295 100644
--- a/Source/cmDocumentation.cxx
+++ b/Source/cmDocumentation.cxx
@@ -16,7 +16,8 @@
#include "cmSystemTools.h"
#include "cmVersion.h"
-static const char* cmDocumentationStandardOptions[][2] = {
+namespace {
+const cmDocumentationEntry cmDocumentationStandardOptions[20] = {
{ "-h,-H,--help,-help,-usage,/?", "Print usage information and exit." },
{ "--version,-version,/V [<file>]", "Print version number and exit." },
{ "--help-full [<file>]", "Print all help manuals and exit." },
@@ -42,22 +43,27 @@ static const char* cmDocumentationStandardOptions[][2] = {
{ "--help-variable var [<file>]", "Print help for one variable and exit." },
{ "--help-variable-list [<file>]",
"List variables with help available and exit." },
- { "--help-variables [<file>]", "Print cmake-variables manual and exit." },
- { nullptr, nullptr }
+ { "--help-variables [<file>]", "Print cmake-variables manual and exit." }
};
-static const char* cmDocumentationCPackGeneratorsHeader[][2] = {
- { nullptr, "The following generators are available on this platform:" },
- { nullptr, nullptr }
+const cmDocumentationEntry cmDocumentationCPackGeneratorsHeader = {
+ {},
+ "The following generators are available on this platform:"
};
-static const char* cmDocumentationCMakeGeneratorsHeader[][2] = {
- { nullptr,
- "The following generators are available on this platform (* marks "
- "default):" },
- { nullptr, nullptr }
+const cmDocumentationEntry cmDocumentationCMakeGeneratorsHeader = {
+ {},
+ "The following generators are available on this platform (* marks "
+ "default):"
};
+bool isOption(const char* arg)
+{
+ return ((arg[0] == '-') || (strcmp(arg, "/V") == 0) ||
+ (strcmp(arg, "/?") == 0));
+}
+} // anonymous namespace
+
cmDocumentation::cmDocumentation()
{
this->addCommonStandardDocSections();
@@ -148,14 +154,6 @@ bool cmDocumentation::PrintRequestedDocumentation(std::ostream& os)
return result;
}
-#define GET_OPT_ARGUMENT(target) \
- do { \
- if ((i + 1 < argc) && !this->IsOption(argv[i + 1])) { \
- (target) = argv[i + 1]; \
- i = i + 1; \
- }; \
- } while (false)
-
void cmDocumentation::WarnFormFromFilename(
cmDocumentation::RequestedHelpItem& request, bool& result)
{
@@ -217,6 +215,14 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv,
return true;
}
+ auto get_opt_argument = [=](const int nextIdx, std::string& target) -> bool {
+ if ((nextIdx < argc) && !isOption(argv[nextIdx])) {
+ target = argv[nextIdx];
+ return true;
+ }
+ return false;
+ };
+
// Search for supported help options.
bool result = false;
@@ -230,7 +236,7 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv,
(strcmp(argv[i], "/?") == 0) || (strcmp(argv[i], "-usage") == 0) ||
(strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "-H") == 0)) {
help.HelpType = cmDocumentation::Help;
- GET_OPT_ARGUMENT(help.Argument);
+ i += int(get_opt_argument(i + 1, help.Argument));
help.Argument = cmSystemTools::LowerCase(help.Argument);
// special case for single command
if (!help.Argument.empty()) {
@@ -239,25 +245,25 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv,
} else if (strcmp(argv[i], "--help-properties") == 0) {
help.HelpType = cmDocumentation::OneManual;
help.Argument = "cmake-properties.7";
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Filename));
this->WarnFormFromFilename(help, result);
} else if (strcmp(argv[i], "--help-policies") == 0) {
help.HelpType = cmDocumentation::OneManual;
help.Argument = "cmake-policies.7";
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Filename));
this->WarnFormFromFilename(help, result);
} else if (strcmp(argv[i], "--help-variables") == 0) {
help.HelpType = cmDocumentation::OneManual;
help.Argument = "cmake-variables.7";
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Filename));
this->WarnFormFromFilename(help, result);
} else if (strcmp(argv[i], "--help-modules") == 0) {
help.HelpType = cmDocumentation::OneManual;
help.Argument = "cmake-modules.7";
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Filename));
this->WarnFormFromFilename(help, result);
} else if (strcmp(argv[i], "--help-custom-modules") == 0) {
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Filename));
cmSystemTools::Message(
"Warning: --help-custom-modules no longer supported");
if (help.Filename.empty()) {
@@ -271,83 +277,79 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv,
} else if (strcmp(argv[i], "--help-commands") == 0) {
help.HelpType = cmDocumentation::OneManual;
help.Argument = "cmake-commands.7";
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Filename));
this->WarnFormFromFilename(help, result);
} else if (strcmp(argv[i], "--help-compatcommands") == 0) {
- GET_OPT_ARGUMENT(help.Filename);
cmSystemTools::Message(
"Warning: --help-compatcommands no longer supported");
return true;
} else if (strcmp(argv[i], "--help-full") == 0) {
help.HelpType = cmDocumentation::Full;
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Filename));
this->WarnFormFromFilename(help, result);
} else if (strcmp(argv[i], "--help-html") == 0) {
- GET_OPT_ARGUMENT(help.Filename);
cmSystemTools::Message("Warning: --help-html no longer supported");
return true;
} else if (strcmp(argv[i], "--help-man") == 0) {
- GET_OPT_ARGUMENT(help.Filename);
cmSystemTools::Message("Warning: --help-man no longer supported");
return true;
} else if (strcmp(argv[i], "--help-command") == 0) {
help.HelpType = cmDocumentation::OneCommand;
- GET_OPT_ARGUMENT(help.Argument);
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Argument));
+ i += int(get_opt_argument(i + 1, help.Filename));
help.Argument = cmSystemTools::LowerCase(help.Argument);
this->WarnFormFromFilename(help, result);
} else if (strcmp(argv[i], "--help-module") == 0) {
help.HelpType = cmDocumentation::OneModule;
- GET_OPT_ARGUMENT(help.Argument);
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Argument));
+ i += int(get_opt_argument(i + 1, help.Filename));
this->WarnFormFromFilename(help, result);
} else if (strcmp(argv[i], "--help-property") == 0) {
help.HelpType = cmDocumentation::OneProperty;
- GET_OPT_ARGUMENT(help.Argument);
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Argument));
+ i += int(get_opt_argument(i + 1, help.Filename));
this->WarnFormFromFilename(help, result);
} else if (strcmp(argv[i], "--help-policy") == 0) {
help.HelpType = cmDocumentation::OnePolicy;
- GET_OPT_ARGUMENT(help.Argument);
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Argument));
+ i += int(get_opt_argument(i + 1, help.Filename));
this->WarnFormFromFilename(help, result);
} else if (strcmp(argv[i], "--help-variable") == 0) {
help.HelpType = cmDocumentation::OneVariable;
- GET_OPT_ARGUMENT(help.Argument);
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Argument));
+ i += int(get_opt_argument(i + 1, help.Filename));
this->WarnFormFromFilename(help, result);
} else if (strcmp(argv[i], "--help-manual") == 0) {
help.HelpType = cmDocumentation::OneManual;
- GET_OPT_ARGUMENT(help.Argument);
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Argument));
+ i += int(get_opt_argument(i + 1, help.Filename));
this->WarnFormFromFilename(help, result);
} else if (strcmp(argv[i], "--help-command-list") == 0) {
help.HelpType = cmDocumentation::ListCommands;
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Filename));
} else if (strcmp(argv[i], "--help-module-list") == 0) {
help.HelpType = cmDocumentation::ListModules;
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Filename));
} else if (strcmp(argv[i], "--help-property-list") == 0) {
help.HelpType = cmDocumentation::ListProperties;
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Filename));
} else if (strcmp(argv[i], "--help-variable-list") == 0) {
help.HelpType = cmDocumentation::ListVariables;
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Filename));
} else if (strcmp(argv[i], "--help-policy-list") == 0) {
help.HelpType = cmDocumentation::ListPolicies;
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Filename));
} else if (strcmp(argv[i], "--help-manual-list") == 0) {
help.HelpType = cmDocumentation::ListManuals;
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Filename));
} else if (strcmp(argv[i], "--copyright") == 0) {
- GET_OPT_ARGUMENT(help.Filename);
cmSystemTools::Message("Warning: --copyright no longer supported");
return true;
} else if ((strcmp(argv[i], "--version") == 0) ||
(strcmp(argv[i], "-version") == 0) ||
(strcmp(argv[i], "/V") == 0)) {
help.HelpType = cmDocumentation::Version;
- GET_OPT_ARGUMENT(help.Filename);
+ i += int(get_opt_argument(i + 1, help.Filename));
}
if (help.HelpType != None) {
// This is a help option. See if there is a file name given.
@@ -369,56 +371,12 @@ void cmDocumentation::SetSection(const char* name,
this->SectionAtName(name) = std::move(section);
}
-void cmDocumentation::SetSection(const char* name,
- std::vector<cmDocumentationEntry>& docs)
-{
- cmDocumentationSection sec{ name };
- sec.Append(docs);
- this->SetSection(name, std::move(sec));
-}
-
-void cmDocumentation::SetSection(const char* name, const char* docs[][2])
-{
- cmDocumentationSection sec{ name };
- sec.Append(docs);
- this->SetSection(name, std::move(sec));
-}
-
-void cmDocumentation::SetSections(
- std::map<std::string, cmDocumentationSection> sections)
-{
- for (auto& s : sections) {
- this->SetSection(s.first.c_str(), std::move(s.second));
- }
-}
cmDocumentationSection& cmDocumentation::SectionAtName(const char* name)
{
return this->AllSections.emplace(name, cmDocumentationSection{ name })
.first->second;
}
-void cmDocumentation::PrependSection(const char* name, const char* docs[][2])
-{
- this->SectionAtName(name).Prepend(docs);
-}
-
-void cmDocumentation::PrependSection(const char* name,
- std::vector<cmDocumentationEntry>& docs)
-{
- this->SectionAtName(name).Prepend(docs);
-}
-
-void cmDocumentation::AppendSection(const char* name, const char* docs[][2])
-{
- this->SectionAtName(name).Append(docs);
-}
-
-void cmDocumentation::AppendSection(const char* name,
- std::vector<cmDocumentationEntry>& docs)
-{
- this->SectionAtName(name).Append(docs);
-}
-
void cmDocumentation::AppendSection(const char* name,
cmDocumentationEntry& docs)
{
@@ -465,7 +423,7 @@ void cmDocumentation::PrintNames(std::ostream& os, std::string const& pattern)
}
std::sort(names.begin(), names.end());
for (std::string const& n : names) {
- os << n << "\n";
+ os << n << '\n';
}
}
@@ -501,7 +459,7 @@ bool cmDocumentation::PrintHelpOneManual(std::ostream& os)
// Argument was not a manual. Complain.
os << "Argument \"" << this->CurrentArgument
<< "\" to --help-manual is not an available manual. "
- << "Use --help-manual-list to see all available manuals.\n";
+ "Use --help-manual-list to see all available manuals.\n";
return false;
}
@@ -520,7 +478,7 @@ bool cmDocumentation::PrintHelpOneCommand(std::ostream& os)
// Argument was not a command. Complain.
os << "Argument \"" << this->CurrentArgument
<< "\" to --help-command is not a CMake command. "
- << "Use --help-command-list to see all commands.\n";
+ "Use --help-command-list to see all commands.\n";
return false;
}
@@ -553,7 +511,7 @@ bool cmDocumentation::PrintHelpListModules(std::ostream& os)
}
std::sort(modules.begin(), modules.end());
for (std::string const& m : modules) {
- os << m << "\n";
+ os << m << '\n';
}
return true;
}
@@ -567,7 +525,7 @@ bool cmDocumentation::PrintHelpOneProperty(std::ostream& os)
// Argument was not a property. Complain.
os << "Argument \"" << this->CurrentArgument
<< "\" to --help-property is not a CMake property. "
- << "Use --help-property-list to see all properties.\n";
+ "Use --help-property-list to see all properties.\n";
return false;
}
@@ -601,7 +559,6 @@ bool cmDocumentation::PrintHelpListGenerators(std::ostream& os)
{
const auto si = this->AllSections.find("Generators");
if (si != this->AllSections.end()) {
- this->Formatter.SetIndent(" ");
this->Formatter.PrintSection(os, si->second);
}
return true;
@@ -616,7 +573,7 @@ bool cmDocumentation::PrintHelpOneVariable(std::ostream& os)
// Argument was not a variable. Complain.
os << "Argument \"" << this->CurrentArgument
<< "\" to --help-variable is not a defined variable. "
- << "Use --help-variable-list to see all defined variables.\n";
+ "Use --help-variable-list to see all defined variables.\n";
return false;
}
@@ -662,12 +619,6 @@ const char* cmDocumentation::GetNameString() const
return "CMake";
}
-bool cmDocumentation::IsOption(const char* arg) const
-{
- return ((arg[0] == '-') || (strcmp(arg, "/V") == 0) ||
- (strcmp(arg, "/?") == 0));
-}
-
bool cmDocumentation::PrintOldCustomModules(std::ostream& os)
{
// CheckOptions abuses the Argument field to give us the file name.
@@ -691,7 +642,7 @@ bool cmDocumentation::PrintOldCustomModules(std::ostream& os)
} else if ((ext.length() == 2) && (ext[1] >= '1') && (ext[1] <= '9')) {
/* clang-format off */
os <<
- ".TH " << name << " " << ext[1] << " \"" <<
+ ".TH " << name << ' ' << ext[1] << " \"" <<
cmSystemTools::GetCurrentDateTime("%B %d, %Y") <<
"\" \"cmake " << cmVersion::GetCMakeVersion() << "\"\n"
".SH NAME\n"
@@ -704,7 +655,7 @@ bool cmDocumentation::PrintOldCustomModules(std::ostream& os)
;
/* clang-format on */
} else {
- os << name << "\n\n" << summary << "\n" << detail;
+ os << name << "\n\n" << summary << '\n' << detail;
}
return true;
}
diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h
index 313be32..6930986 100644
--- a/Source/cmDocumentation.h
+++ b/Source/cmDocumentation.h
@@ -7,6 +7,7 @@
#include <iosfwd>
#include <map>
#include <string>
+#include <utility>
#include <vector>
#include "cmDocumentationFormatter.h"
@@ -15,9 +16,33 @@
struct cmDocumentationEntry;
/** Class to generate documentation. */
-class cmDocumentation : public cmDocumentationEnums
+class cmDocumentation
{
public:
+ /** Types of help provided. */
+ enum Type
+ {
+ None,
+ Version,
+ Usage,
+ Help,
+ Full,
+ ListManuals,
+ ListCommands,
+ ListModules,
+ ListProperties,
+ ListVariables,
+ ListPolicies,
+ ListGenerators,
+ OneManual,
+ OneCommand,
+ OneModule,
+ OneProperty,
+ OneVariable,
+ OnePolicy,
+ OldCustomModules
+ };
+
cmDocumentation();
/**
@@ -50,19 +75,26 @@ public:
/** Set a section of the documentation. Typical sections include Name,
Usage, Description, Options */
void SetSection(const char* sectionName, cmDocumentationSection section);
- void SetSection(const char* sectionName,
- std::vector<cmDocumentationEntry>& docs);
- void SetSection(const char* sectionName, const char* docs[][2]);
- void SetSections(std::map<std::string, cmDocumentationSection> sections);
+ template <typename Iterable>
+ void SetSection(const char* sectionName, const Iterable& docs)
+ {
+ cmDocumentationSection sec{ sectionName };
+ sec.Append(docs);
+ this->SetSection(sectionName, std::move(sec));
+ }
/** Add the documentation to the beginning/end of the section */
- void PrependSection(const char* sectionName, const char* docs[][2]);
- void PrependSection(const char* sectionName,
- std::vector<cmDocumentationEntry>& docs);
+ template <typename Iterable>
+ void PrependSection(const char* sectionName, const Iterable& docs)
+ {
+ this->SectionAtName(sectionName).Prepend(docs);
+ }
void PrependSection(const char* sectionName, cmDocumentationEntry& docs);
- void AppendSection(const char* sectionName, const char* docs[][2]);
- void AppendSection(const char* sectionName,
- std::vector<cmDocumentationEntry>& docs);
+ template <typename Iterable>
+ void AppendSection(const char* sectionName, const Iterable& docs)
+ {
+ this->SectionAtName(sectionName).Append(docs);
+ }
void AppendSection(const char* sectionName, cmDocumentationEntry& docs);
/** Add common (to all tools) documentation section(s) */
@@ -102,7 +134,6 @@ private:
bool PrintOldCustomModules(std::ostream& os);
const char* GetNameString() const;
- bool IsOption(const char* arg) const;
bool ShowGenerators;
@@ -114,7 +145,7 @@ private:
struct RequestedHelpItem
{
- cmDocumentationEnums::Type HelpType = None;
+ Type HelpType = None;
std::string Filename;
std::string Argument;
};
diff --git a/Source/cmDocumentationEntry.h b/Source/cmDocumentationEntry.h
index 89a2899..d971836 100644
--- a/Source/cmDocumentationEntry.h
+++ b/Source/cmDocumentationEntry.h
@@ -9,26 +9,15 @@
/** Standard documentation entry for cmDocumentation's formatting. */
struct cmDocumentationEntry
{
- std::string Name;
- std::string Brief;
- char CustomNamePrefix = ' ';
- cmDocumentationEntry() = default;
- cmDocumentationEntry(const char* doc[2])
- {
- if (doc[0]) {
- this->Name = doc[0];
- }
- if (doc[1]) {
- this->Brief = doc[1];
- }
- }
- cmDocumentationEntry(const char* n, const char* b)
+#if __cplusplus <= 201103L
+ cmDocumentationEntry(const std::string& name, const std::string& brief)
+ : Name{ name }
+ , Brief{ brief }
{
- if (n) {
- this->Name = n;
- }
- if (b) {
- this->Brief = b;
- }
}
+#endif
+
+ std::string Name = {};
+ std::string Brief = {};
+ char CustomNamePrefix = ' ';
};
diff --git a/Source/cmDocumentationFormatter.cxx b/Source/cmDocumentationFormatter.cxx
index 732637e..70ba1fc 100644
--- a/Source/cmDocumentationFormatter.cxx
+++ b/Source/cmDocumentationFormatter.cxx
@@ -2,7 +2,8 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDocumentationFormatter.h"
-#include <cstring>
+#include <algorithm>
+#include <cassert>
#include <iomanip>
#include <ostream>
#include <string>
@@ -11,178 +12,207 @@
#include "cmDocumentationEntry.h"
#include "cmDocumentationSection.h"
-cmDocumentationFormatter::cmDocumentationFormatter() = default;
-
-cmDocumentationFormatter::~cmDocumentationFormatter() = default;
+namespace {
+const char* skipSpaces(const char* ptr)
+{
+ assert(ptr);
+ for (; *ptr == ' '; ++ptr) {
+ ;
+ }
+ return ptr;
+}
+const char* skipToSpace(const char* ptr)
+{
+ assert(ptr);
+ for (; *ptr && (*ptr != '\n') && (*ptr != ' '); ++ptr) {
+ ;
+ }
+ return ptr;
+}
+}
void cmDocumentationFormatter::PrintFormatted(std::ostream& os,
- const char* text)
+ std::string const& text) const
{
- if (!text) {
+ if (text.empty()) {
return;
}
- const char* ptr = text;
- while (*ptr) {
- // Any ptrs starting in a space are treated as preformatted text.
- std::string preformatted;
- while (*ptr == ' ') {
- for (char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr) {
- preformatted.append(1, ch);
- }
- if (*ptr) {
- ++ptr;
- preformatted.append(1, '\n');
- }
- }
- if (!preformatted.empty()) {
- this->PrintPreformatted(os, preformatted.c_str());
+
+ struct Buffer
+ {
+ // clang-format off
+ using PrinterFn = void (cmDocumentationFormatter::*)(
+ std::ostream&, std::string const&
+ ) const;
+ // clang-format on
+ std::string collected;
+ const PrinterFn printer;
+ };
+ // const auto NORMAL_IDX = 0u;
+ const auto PREFORMATTED_IDX = 1u;
+ const auto HANDLERS_SIZE = 2u;
+ Buffer buffers[HANDLERS_SIZE] = {
+ { {}, &cmDocumentationFormatter::PrintParagraph },
+ { {}, &cmDocumentationFormatter::PrintPreformatted }
+ };
+
+ const auto padding = std::string(this->TextIndent, ' ');
+
+ for (std::size_t pos = 0u, eol = 0u; pos < text.size(); pos = eol) {
+ const auto current_idx = std::size_t(text[pos] == ' ');
+ // size_t(!bool(current_idx))
+ const auto other_idx = current_idx ^ 1u;
+
+ // Flush the other buffer if anything has been collected
+ if (!buffers[other_idx].collected.empty()) {
+ // NOTE Whatever the other index is, the current buffered
+ // string expected to be empty.
+ assert(buffers[current_idx].collected.empty());
+
+ (this->*buffers[other_idx].printer)(os, buffers[other_idx].collected);
+ buffers[other_idx].collected.clear();
}
- // Other ptrs are treated as paragraphs.
- std::string paragraph;
- for (char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr) {
- paragraph.append(1, ch);
+ // ATTENTION The previous implementation had called `PrintParagraph()`
+ // **for every processed (char by char) input line**.
+ // The method unconditionally append the `\n' character after the
+ // printed text. To keep the backward-compatible behavior it's needed to
+ // add the '\n' character to the previously collected line...
+ if (!buffers[current_idx].collected.empty() &&
+ current_idx != PREFORMATTED_IDX) {
+ buffers[current_idx].collected += '\n';
}
- if (*ptr) {
- ++ptr;
- paragraph.append(1, '\n');
+
+ // Lookup EOL
+ eol = text.find('\n', pos);
+ if (current_idx == PREFORMATTED_IDX) {
+ buffers[current_idx].collected.append(padding);
}
- if (!paragraph.empty()) {
- this->PrintParagraph(os, paragraph.c_str());
+ buffers[current_idx].collected.append(
+ text, pos, eol == std::string::npos ? eol : ++eol - pos);
+ }
+
+ for (auto& buf : buffers) {
+ if (!buf.collected.empty()) {
+ (this->*buf.printer)(os, buf.collected);
}
}
}
void cmDocumentationFormatter::PrintPreformatted(std::ostream& os,
- const char* text)
+ std::string const& text) const
{
- bool newline = true;
- for (const char* ptr = text; *ptr; ++ptr) {
- if (newline && *ptr != '\n') {
- os << this->TextIndent;
- newline = false;
- }
- os << *ptr;
- if (*ptr == '\n') {
- newline = true;
- }
- }
- os << "\n";
+ os << text << '\n';
}
void cmDocumentationFormatter::PrintParagraph(std::ostream& os,
- const char* text)
+ std::string const& text) const
{
- os << this->TextIndent;
+ if (this->TextIndent) {
+ os << std::string(this->TextIndent, ' ');
+ }
this->PrintColumn(os, text);
- os << "\n";
-}
-
-void cmDocumentationFormatter::SetIndent(const char* indent)
-{
- this->TextIndent = indent;
+ os << '\n';
}
-void cmDocumentationFormatter::PrintColumn(std::ostream& os, const char* text)
+void cmDocumentationFormatter::PrintColumn(std::ostream& os,
+ std::string const& text) const
{
// Print text arranged in an indented column of fixed width.
- const char* l = text;
- long column = 0;
bool newSentence = false;
bool firstLine = true;
- int width = this->TextWidth - static_cast<int>(strlen(this->TextIndent));
- // Loop until the end of the text.
- while (*l) {
- // Parse the next word.
- const char* r = l;
- while (*r && (*r != '\n') && (*r != ' ')) {
- ++r;
- }
+ assert(this->TextIndent < this->TextWidth);
+ const std::ptrdiff_t width = this->TextWidth - this->TextIndent;
+ std::ptrdiff_t column = 0;
+ // Loop until the end of the text.
+ for (const char *l = text.c_str(), *r = skipToSpace(text.c_str()); *l;
+ l = skipSpaces(r), r = skipToSpace(l)) {
// Does it fit on this line?
- if (r - l < (width - column - (newSentence ? 1 : 0))) {
+ if (r - l < width - column - std::ptrdiff_t(newSentence)) {
// Word fits on this line.
if (r > l) {
if (column) {
// Not first word on line. Separate from the previous word
// by a space, or two if this is a new sentence.
- if (newSentence) {
- os << " ";
- column += 2;
- } else {
- os << " ";
- column += 1;
- }
- } else {
+ os << &(" "[std::size_t(!newSentence)]);
+ column += 1u + std::ptrdiff_t(newSentence);
+ } else if (!firstLine && this->TextIndent) {
// First word on line. Print indentation unless this is the
// first line.
- os << (firstLine ? "" : this->TextIndent);
+ os << std::string(this->TextIndent, ' ');
}
// Print the word.
- os.write(l, static_cast<long>(r - l));
+ os.write(l, r - l);
newSentence = (*(r - 1) == '.');
}
if (*r == '\n') {
// Text provided a newline. Start a new line.
- os << "\n";
+ os << '\n';
++r;
column = 0;
firstLine = false;
} else {
// No provided newline. Continue this line.
- column += static_cast<long>(r - l);
+ column += r - l;
}
} else {
// Word does not fit on this line. Start a new line.
- os << "\n";
+ os << '\n';
firstLine = false;
if (r > l) {
- os << this->TextIndent;
- os.write(l, static_cast<long>(r - l));
- column = static_cast<long>(r - l);
+ os << std::string(this->TextIndent, ' ');
+ os.write(l, r - l);
+ column = r - l;
newSentence = (*(r - 1) == '.');
} else {
column = 0;
}
}
-
// Move to beginning of next word. Skip over whitespace.
- l = r;
- while (*l == ' ') {
- ++l;
- }
}
}
void cmDocumentationFormatter::PrintSection(
std::ostream& os, cmDocumentationSection const& section)
{
- os << section.GetName() << "\n";
+ const std::size_t PREFIX_SIZE =
+ sizeof(cmDocumentationEntry::CustomNamePrefix) + 1u;
+ // length of the "= " literal (see below)
+ const std::size_t SUFFIX_SIZE = 2u;
+ // legacy magic number ;-)
+ const std::size_t NAME_SIZE = 29u;
+
+ const std::size_t PADDING_SIZE = PREFIX_SIZE + SUFFIX_SIZE;
+ const std::size_t TITLE_SIZE = NAME_SIZE + PADDING_SIZE;
+
+ const auto savedIndent = this->TextIndent;
- const std::vector<cmDocumentationEntry>& entries = section.GetEntries();
- for (cmDocumentationEntry const& entry : entries) {
+ os << section.GetName() << '\n';
+
+ for (cmDocumentationEntry const& entry : section.GetEntries()) {
if (!entry.Name.empty()) {
- os << std::setw(2) << std::left << entry.CustomNamePrefix << entry.Name;
- this->TextIndent = " ";
- int align = static_cast<int>(strlen(this->TextIndent)) - 4;
- for (int i = static_cast<int>(entry.Name.size()); i < align; ++i) {
- os << " ";
- }
- if (entry.Name.size() > strlen(this->TextIndent) - 4) {
- os << "\n";
- os.write(this->TextIndent, strlen(this->TextIndent) - 2);
+ this->TextIndent = TITLE_SIZE;
+ os << std::setw(PREFIX_SIZE) << std::left << entry.CustomNamePrefix
+ << std::setw(int(std::max(NAME_SIZE, entry.Name.size())))
+ << entry.Name;
+ if (entry.Name.size() > NAME_SIZE) {
+ os << '\n' << std::setw(int(this->TextIndent - PREFIX_SIZE)) << ' ';
}
os << "= ";
- this->PrintColumn(os, entry.Brief.c_str());
- os << "\n";
+ this->PrintColumn(os, entry.Brief);
+ os << '\n';
} else {
- os << "\n";
- this->TextIndent = "";
- this->PrintFormatted(os, entry.Brief.c_str());
+ os << '\n';
+ this->TextIndent = 0u;
+ this->PrintFormatted(os, entry.Brief);
}
}
- os << "\n";
+
+ os << '\n';
+
+ this->TextIndent = savedIndent;
}
diff --git a/Source/cmDocumentationFormatter.h b/Source/cmDocumentationFormatter.h
index cb3038a..e269f6a 100644
--- a/Source/cmDocumentationFormatter.h
+++ b/Source/cmDocumentationFormatter.h
@@ -5,40 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
-
-/** This is just a helper class to make it build with MSVC 6.0.
-Actually the enums and internal classes could directly go into
-cmDocumentation, but then MSVC6 complains in RequestedHelpItem that
-cmDocumentation is an undefined type and so it doesn't know the enums.
-Moving the enums to a class which is then already completely parsed helps
-against this. */
-class cmDocumentationEnums
-{
-public:
- /** Types of help provided. */
- enum Type
- {
- None,
- Version,
- Usage,
- Help,
- Full,
- ListManuals,
- ListCommands,
- ListModules,
- ListProperties,
- ListVariables,
- ListPolicies,
- ListGenerators,
- OneManual,
- OneCommand,
- OneModule,
- OneProperty,
- OneVariable,
- OnePolicy,
- OldCustomModules
- };
-};
+#include <string>
class cmDocumentationSection;
@@ -46,18 +13,15 @@ class cmDocumentationSection;
class cmDocumentationFormatter
{
public:
- cmDocumentationFormatter();
- virtual ~cmDocumentationFormatter();
- void PrintFormatted(std::ostream& os, const char* text);
-
- virtual void PrintSection(std::ostream& os,
- cmDocumentationSection const& section);
- virtual void PrintPreformatted(std::ostream& os, const char* text);
- virtual void PrintParagraph(std::ostream& os, const char* text);
- void PrintColumn(std::ostream& os, const char* text);
- void SetIndent(const char* indent);
+ void SetIndent(std::size_t indent) { this->TextIndent = indent; }
+ void PrintFormatted(std::ostream& os, std::string const& text) const;
+ void PrintSection(std::ostream& os, cmDocumentationSection const& section);
private:
- int TextWidth = 77;
- const char* TextIndent = "";
+ void PrintPreformatted(std::ostream& os, std::string const&) const;
+ void PrintParagraph(std::ostream& os, std::string const&) const;
+ void PrintColumn(std::ostream& os, std::string const&) const;
+
+ std::size_t TextWidth = 77u;
+ std::size_t TextIndent = 0u;
};
diff --git a/Source/cmDocumentationSection.cxx b/Source/cmDocumentationSection.cxx
deleted file mode 100644
index 439da1b..0000000
--- a/Source/cmDocumentationSection.cxx
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmDocumentationSection.h"
-
-void cmDocumentationSection::Append(const char* data[][2])
-{
- int i = 0;
- while (data[i][1]) {
- this->Entries.emplace_back(data[i][0], data[i][1]);
- data += 1;
- }
-}
-
-void cmDocumentationSection::Prepend(const char* data[][2])
-{
- std::vector<cmDocumentationEntry> tmp;
- int i = 0;
- while (data[i][1]) {
- tmp.emplace_back(data[i][0], data[i][1]);
- data += 1;
- }
- this->Entries.insert(this->Entries.begin(), tmp.begin(), tmp.end());
-}
-
-void cmDocumentationSection::Append(const char* n, const char* b)
-{
- this->Entries.emplace_back(n, b);
-}
diff --git a/Source/cmDocumentationSection.h b/Source/cmDocumentationSection.h
index 276e520..b5e24fe 100644
--- a/Source/cmDocumentationSection.h
+++ b/Source/cmDocumentationSection.h
@@ -4,11 +4,10 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <iterator>
#include <string>
#include <vector>
-#include <cmext/algorithm>
-
#include "cmDocumentationEntry.h"
// Low-level interface for custom documents:
@@ -45,21 +44,20 @@ public:
{
this->Entries.push_back(entry);
}
- void Append(const std::vector<cmDocumentationEntry>& entries)
+
+ template <typename Iterable>
+ void Append(const Iterable& entries)
{
- cm::append(this->Entries, entries);
+ this->Entries.insert(std::end(this->Entries), std::begin(entries),
+ std::end(entries));
}
- /** Append an entry to this section using NULL terminated chars */
- void Append(const char* [][2]);
- void Append(const char* n, const char* b);
-
/** prepend some documentation to this section */
- void Prepend(const char* [][2]);
- void Prepend(const std::vector<cmDocumentationEntry>& entries)
+ template <typename Iterable>
+ void Prepend(const Iterable& entries)
{
- this->Entries.insert(this->Entries.begin(), entries.begin(),
- entries.end());
+ this->Entries.insert(std::begin(this->Entries), std::begin(entries),
+ std::end(entries));
}
private:
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 85f528d..cdd0408 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -1408,12 +1408,14 @@ bool HandleCopyFile(std::vector<std::string> const& args,
struct Arguments
{
+ bool InputMayBeRecent = false;
bool OnlyIfDifferent = false;
std::string Result;
};
static auto const parser =
cmArgumentParser<Arguments>{}
+ .Bind("INPUT_MAY_BE_RECENT"_s, &Arguments::InputMayBeRecent)
.Bind("ONLY_IF_DIFFERENT"_s, &Arguments::OnlyIfDifferent)
.Bind("RESULT"_s, &Arguments::Result);
@@ -1456,9 +1458,13 @@ bool HandleCopyFile(std::vector<std::string> const& args,
} else {
when = cmSystemTools::CopyWhen::Always;
}
+ cmSystemTools::CopyInputRecent const inputRecent = arguments.InputMayBeRecent
+ ? cmSystemTools::CopyInputRecent::Yes
+ : cmSystemTools::CopyInputRecent::No;
std::string err;
- if (cmSystemTools::CopySingleFile(oldname, newname, when, &err) ==
+ if (cmSystemTools::CopySingleFile(oldname, newname, when, inputRecent,
+ &err) ==
cmSystemTools::CopyResult::Success) {
if (!arguments.Result.empty()) {
status.GetMakefile().AddDefinition(arguments.Result, "0");
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 21ace89..b605350 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGeneratorExpression.h"
+#include <algorithm>
#include <cassert>
#include <memory>
#include <utility>
@@ -226,23 +227,33 @@ static std::string stripExportInterface(
while (true) {
std::string::size_type bPos = input.find("$<BUILD_INTERFACE:", lastPos);
std::string::size_type iPos = input.find("$<INSTALL_INTERFACE:", lastPos);
+ std::string::size_type lPos =
+ input.find("$<BUILD_LOCAL_INTERFACE:", lastPos);
- if (bPos == std::string::npos && iPos == std::string::npos) {
+ pos = std::min({ bPos, iPos, lPos });
+ if (pos == std::string::npos) {
break;
}
- if (bPos == std::string::npos) {
- pos = iPos;
- } else if (iPos == std::string::npos) {
- pos = bPos;
+ result += input.substr(lastPos, pos - lastPos);
+ enum class FoundGenex
+ {
+ BuildInterface,
+ InstallInterface,
+ BuildLocalInterface,
+ } foundGenex = FoundGenex::BuildInterface;
+ if (pos == bPos) {
+ foundGenex = FoundGenex::BuildInterface;
+ pos += cmStrLen("$<BUILD_INTERFACE:");
+ } else if (pos == iPos) {
+ foundGenex = FoundGenex::InstallInterface;
+ pos += cmStrLen("$<INSTALL_INTERFACE:");
+ } else if (pos == lPos) {
+ foundGenex = FoundGenex::BuildLocalInterface;
+ pos += cmStrLen("$<BUILD_LOCAL_INTERFACE:");
} else {
- pos = (bPos < iPos) ? bPos : iPos;
+ assert(false && "Invalid position found");
}
-
- result += input.substr(lastPos, pos - lastPos);
- const bool gotInstallInterface = input[pos + 2] == 'I';
- pos += gotInstallInterface ? sizeof("$<INSTALL_INTERFACE:") - 1
- : sizeof("$<BUILD_INTERFACE:") - 1;
nestingLevel = 1;
const char* c = input.c_str() + pos;
const char* const cStart = c;
@@ -258,10 +269,10 @@ static std::string stripExportInterface(
continue;
}
if (context == cmGeneratorExpression::BuildInterface &&
- !gotInstallInterface) {
+ foundGenex == FoundGenex::BuildInterface) {
result += input.substr(pos, c - cStart);
} else if (context == cmGeneratorExpression::InstallInterface &&
- gotInstallInterface) {
+ foundGenex == FoundGenex::InstallInterface) {
const std::string content = input.substr(pos, c - cStart);
if (resolveRelative) {
prefixItems(content, result, "${_IMPORT_PREFIX}/");
@@ -274,9 +285,18 @@ static std::string stripExportInterface(
}
const std::string::size_type traversed = (c - cStart) + 1;
if (!*c) {
- result += std::string(gotInstallInterface ? "$<INSTALL_INTERFACE:"
- : "$<BUILD_INTERFACE:") +
- input.substr(pos, traversed);
+ auto remaining = input.substr(pos, traversed);
+ switch (foundGenex) {
+ case FoundGenex::BuildInterface:
+ result = cmStrCat(result, "$<BUILD_INTERFACE:", remaining);
+ break;
+ case FoundGenex::InstallInterface:
+ result = cmStrCat(result, "$<INSTALL_INTERFACE:", remaining);
+ break;
+ case FoundGenex::BuildLocalInterface:
+ result = cmStrCat(result, "$<BUILD_LOCAL_INTERFACE:", remaining);
+ break;
+ }
}
pos += traversed;
lastPos = pos;
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index 562c31e..c14012e 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -114,6 +114,8 @@ static const struct OneNode buildInterfaceNode;
static const struct ZeroNode installInterfaceNode;
+static const struct OneNode buildLocalInterfaceNode;
+
struct BooleanOpNode : public cmGeneratorExpressionNode
{
BooleanOpNode(const char* op_, const char* successVal_,
@@ -1970,7 +1972,10 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
}
return std::string();
}
- target = context->LG->FindGeneratorTargetToUse(targetName);
+ cmLocalGenerator const* lg = context->CurrentTarget
+ ? context->CurrentTarget->GetLocalGenerator()
+ : context->LG;
+ target = lg->FindGeneratorTargetToUse(targetName);
if (!target) {
std::ostringstream e;
@@ -3320,6 +3325,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
{ "GENEX_EVAL", &genexEvalNode },
{ "BUILD_INTERFACE", &buildInterfaceNode },
{ "INSTALL_INTERFACE", &installInterfaceNode },
+ { "BUILD_LOCAL_INTERFACE", &buildLocalInterfaceNode },
{ "INSTALL_PREFIX", &installPrefixNode },
{ "JOIN", &joinNode },
{ "LINK_ONLY", &linkOnlyNode },
diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx
index 776ee40..2fd7f8a 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.cxx
+++ b/Source/cmGlobalBorlandMakefileGenerator.cxx
@@ -60,11 +60,10 @@ cmGlobalBorlandMakefileGenerator::CreateLocalGenerator(cmMakefile* mf)
return std::unique_ptr<cmLocalGenerator>(std::move(lg));
}
-void cmGlobalBorlandMakefileGenerator::GetDocumentation(
- cmDocumentationEntry& entry)
+cmDocumentationEntry cmGlobalBorlandMakefileGenerator::GetDocumentation()
{
- entry.Name = cmGlobalBorlandMakefileGenerator::GetActualName();
- entry.Brief = "Generates Borland makefiles.";
+ return { cmGlobalBorlandMakefileGenerator::GetActualName(),
+ "Generates Borland makefiles." };
}
std::vector<cmGlobalGenerator::GeneratedMakeCommand>
diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h
index a280b81..049d6ba 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.h
+++ b/Source/cmGlobalBorlandMakefileGenerator.h
@@ -13,7 +13,6 @@
class cmLocalGenerator;
class cmMakefile;
class cmake;
-struct cmDocumentationEntry;
/** \class cmGlobalBorlandMakefileGenerator
* \brief Write a Borland makefiles.
@@ -38,7 +37,7 @@ public:
static std::string GetActualName() { return "Borland Makefiles"; }
/** Get the documentation entry for this generator. */
- static void GetDocumentation(cmDocumentationEntry& entry);
+ static cmDocumentationEntry GetDocumentation();
//! Create a local generator appropriate to this Global Generator
std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
diff --git a/Source/cmGlobalGeneratorFactory.h b/Source/cmGlobalGeneratorFactory.h
index d6ababb..a935079 100644
--- a/Source/cmGlobalGeneratorFactory.h
+++ b/Source/cmGlobalGeneratorFactory.h
@@ -4,6 +4,10 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmDocumentationEntry.h" // IWYU pragma: export
+
+// TODO The following headers are parts of the `cmGlobalGeneratorFactory`
+// public API, so could be defined as export to IWYU
#include <string>
#include <vector>
@@ -11,7 +15,6 @@
class cmGlobalGenerator;
class cmake;
-struct cmDocumentationEntry;
/** \class cmGlobalGeneratorFactory
* \brief Responable for creating cmGlobalGenerator instances
@@ -28,7 +31,7 @@ public:
const std::string& n, bool allowArch, cmake* cm) const = 0;
/** Get the documentation entry for this factory */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const = 0;
+ virtual cmDocumentationEntry GetDocumentation() const = 0;
/** Get the names of the current registered generators */
virtual std::vector<std::string> GetGeneratorNames() const = 0;
@@ -47,7 +50,7 @@ public:
virtual std::string GetDefaultPlatformName() const = 0;
};
-template <class T>
+template <typename T>
class cmGlobalGeneratorSimpleFactory : public cmGlobalGeneratorFactory
{
public:
@@ -62,21 +65,19 @@ public:
}
/** Get the documentation entry for this factory */
- void GetDocumentation(cmDocumentationEntry& entry) const override
+ cmDocumentationEntry GetDocumentation() const override
{
- T::GetDocumentation(entry);
+ return T::GetDocumentation();
}
/** Get the names of the current registered generators */
std::vector<std::string> GetGeneratorNames() const override
{
- std::vector<std::string> names;
- names.push_back(T::GetActualName());
- return names;
+ return { T::GetActualName() };
}
std::vector<std::string> GetGeneratorNamesWithPlatform() const override
{
- return std::vector<std::string>();
+ return {};
}
/** Determine whether or not this generator supports toolsets */
@@ -89,8 +90,8 @@ public:
std::vector<std::string> GetKnownPlatforms() const override
{
// default is no platform supported
- return std::vector<std::string>();
+ return {};
}
- std::string GetDefaultPlatformName() const override { return std::string(); }
+ std::string GetDefaultPlatformName() const override { return {}; }
};
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 9c334a5..18c48d7 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -15,7 +15,6 @@
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
-#include "cmDocumentationEntry.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGhsMultiGpj.h"
@@ -58,11 +57,12 @@ cmGlobalGhsMultiGenerator::CreateLocalGenerator(cmMakefile* mf)
cm::make_unique<cmLocalGhsMultiGenerator>(this, mf));
}
-void cmGlobalGhsMultiGenerator::GetDocumentation(cmDocumentationEntry& entry)
+cmDocumentationEntry cmGlobalGhsMultiGenerator::GetDocumentation()
{
- entry.Name = GetActualName();
- entry.Brief =
- "Generates Green Hills MULTI files (experimental, work-in-progress).";
+ return {
+ GetActualName(),
+ "Generates Green Hills MULTI files (experimental, work-in-progress)."
+ };
}
void cmGlobalGhsMultiGenerator::ComputeTargetObjectDirectory(
diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h
index aa68d3b..4a79610 100644
--- a/Source/cmGlobalGhsMultiGenerator.h
+++ b/Source/cmGlobalGhsMultiGenerator.h
@@ -18,7 +18,6 @@ class cmGeneratorTarget;
class cmLocalGenerator;
class cmMakefile;
class cmake;
-struct cmDocumentationEntry;
class cmGlobalGhsMultiGenerator : public cmGlobalGenerator
{
@@ -46,7 +45,7 @@ public:
std::string GetName() const override { return GetActualName(); }
/// Overloaded methods. @see cmGlobalGenerator::GetDocumentation()
- static void GetDocumentation(cmDocumentationEntry& entry);
+ static cmDocumentationEntry GetDocumentation();
/**
* Utilized by the generator factory to determine if this generator
diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx
index 1a625cc..f1d4d09 100644
--- a/Source/cmGlobalJOMMakefileGenerator.cxx
+++ b/Source/cmGlobalJOMMakefileGenerator.cxx
@@ -6,7 +6,6 @@
#include <cmext/algorithm>
-#include "cmDocumentationEntry.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmState.h"
@@ -36,11 +35,10 @@ void cmGlobalJOMMakefileGenerator::EnableLanguage(
this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
}
-void cmGlobalJOMMakefileGenerator::GetDocumentation(
- cmDocumentationEntry& entry)
+cmDocumentationEntry cmGlobalJOMMakefileGenerator::GetDocumentation()
{
- entry.Name = cmGlobalJOMMakefileGenerator::GetActualName();
- entry.Brief = "Generates JOM makefiles.";
+ return { cmGlobalJOMMakefileGenerator::GetActualName(),
+ "Generates JOM makefiles." };
}
void cmGlobalJOMMakefileGenerator::PrintCompilerAdvice(std::ostream& os,
diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h
index 332d1cf..5e74875 100644
--- a/Source/cmGlobalJOMMakefileGenerator.h
+++ b/Source/cmGlobalJOMMakefileGenerator.h
@@ -13,7 +13,6 @@
class cmMakefile;
class cmake;
-struct cmDocumentationEntry;
/** \class cmGlobalJOMMakefileGenerator
* \brief Write a JOM makefiles.
@@ -39,7 +38,7 @@ public:
static std::string GetActualName() { return "NMake Makefiles JOM"; }
/** Get the documentation entry for this generator. */
- static void GetDocumentation(cmDocumentationEntry& entry);
+ static cmDocumentationEntry GetDocumentation();
/**
* Try to determine system information such as shared library
diff --git a/Source/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx
index d4ff1e0..e543aea 100644
--- a/Source/cmGlobalMSYSMakefileGenerator.cxx
+++ b/Source/cmGlobalMSYSMakefileGenerator.cxx
@@ -4,7 +4,6 @@
#include "cmsys/FStream.hxx"
-#include "cmDocumentationEntry.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
@@ -53,9 +52,8 @@ void cmGlobalMSYSMakefileGenerator::EnableLanguage(
}
}
-void cmGlobalMSYSMakefileGenerator::GetDocumentation(
- cmDocumentationEntry& entry)
+cmDocumentationEntry cmGlobalMSYSMakefileGenerator::GetDocumentation()
{
- entry.Name = cmGlobalMSYSMakefileGenerator::GetActualName();
- entry.Brief = "Generates MSYS makefiles.";
+ return { cmGlobalMSYSMakefileGenerator::GetActualName(),
+ "Generates MSYS makefiles." };
}
diff --git a/Source/cmGlobalMSYSMakefileGenerator.h b/Source/cmGlobalMSYSMakefileGenerator.h
index 586487f..a8516a4 100644
--- a/Source/cmGlobalMSYSMakefileGenerator.h
+++ b/Source/cmGlobalMSYSMakefileGenerator.h
@@ -11,7 +11,6 @@
class cmMakefile;
class cmake;
-struct cmDocumentationEntry;
/** \class cmGlobalMSYSMakefileGenerator
* \brief Write a NMake makefiles.
@@ -36,7 +35,7 @@ public:
static std::string GetActualName() { return "MSYS Makefiles"; }
/** Get the documentation entry for this generator. */
- static void GetDocumentation(cmDocumentationEntry& entry);
+ static cmDocumentationEntry GetDocumentation();
/**
* Try to determine system information such as shared library
diff --git a/Source/cmGlobalMinGWMakefileGenerator.cxx b/Source/cmGlobalMinGWMakefileGenerator.cxx
index 5a7edae..a0a52d3 100644
--- a/Source/cmGlobalMinGWMakefileGenerator.cxx
+++ b/Source/cmGlobalMinGWMakefileGenerator.cxx
@@ -2,7 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalMinGWMakefileGenerator.h"
-#include "cmDocumentationEntry.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmSystemTools.h"
@@ -19,9 +18,8 @@ cmGlobalMinGWMakefileGenerator::cmGlobalMinGWMakefileGenerator(cmake* cm)
cm->GetState()->SetMinGWMake(true);
}
-void cmGlobalMinGWMakefileGenerator::GetDocumentation(
- cmDocumentationEntry& entry)
+cmDocumentationEntry cmGlobalMinGWMakefileGenerator::GetDocumentation()
{
- entry.Name = cmGlobalMinGWMakefileGenerator::GetActualName();
- entry.Brief = "Generates a make file for use with mingw32-make.";
+ return { cmGlobalMinGWMakefileGenerator::GetActualName(),
+ "Generates a make file for use with mingw32-make." };
}
diff --git a/Source/cmGlobalMinGWMakefileGenerator.h b/Source/cmGlobalMinGWMakefileGenerator.h
index 92d495c..b39db03 100644
--- a/Source/cmGlobalMinGWMakefileGenerator.h
+++ b/Source/cmGlobalMinGWMakefileGenerator.h
@@ -11,7 +11,6 @@
class cmMakefile;
class cmake;
-struct cmDocumentationEntry;
/** \class cmGlobalMinGWMakefileGenerator
* \brief Write a NMake makefiles.
@@ -35,5 +34,5 @@ public:
static std::string GetActualName() { return "MinGW Makefiles"; }
/** Get the documentation entry for this generator. */
- static void GetDocumentation(cmDocumentationEntry& entry);
+ static cmDocumentationEntry GetDocumentation();
};
diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx
index eabacf6..cb53850 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.cxx
+++ b/Source/cmGlobalNMakeMakefileGenerator.cxx
@@ -8,7 +8,6 @@
#include "cmsys/RegularExpression.hxx"
-#include "cmDocumentationEntry.h"
#include "cmDuration.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
@@ -80,11 +79,10 @@ void cmGlobalNMakeMakefileGenerator::CheckNMakeFeatures()
cmSystemTools::OP_LESS, this->NMakeVersion, "9");
}
-void cmGlobalNMakeMakefileGenerator::GetDocumentation(
- cmDocumentationEntry& entry)
+cmDocumentationEntry cmGlobalNMakeMakefileGenerator::GetDocumentation()
{
- entry.Name = cmGlobalNMakeMakefileGenerator::GetActualName();
- entry.Brief = "Generates NMake makefiles.";
+ return { cmGlobalNMakeMakefileGenerator::GetActualName(),
+ "Generates NMake makefiles." };
}
void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice(
@@ -128,12 +126,8 @@ void cmGlobalNMakeMakefileGenerator::PrintBuildCommandAdvice(std::ostream& os,
if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
// nmake does not support parallel build level
// see https://msdn.microsoft.com/en-us/library/afyyse50.aspx
-
- /* clang-format off */
- os <<
- "Warning: NMake does not support parallel builds. "
- "Ignoring parallel build command line option.\n";
- /* clang-format on */
+ os << "Warning: NMake does not support parallel builds. "
+ "Ignoring parallel build command line option.\n";
}
this->cmGlobalUnixMakefileGenerator3::PrintBuildCommandAdvice(
diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h
index b3574eb..436ebca 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.h
+++ b/Source/cmGlobalNMakeMakefileGenerator.h
@@ -15,7 +15,6 @@
class cmMakefile;
class cmake;
-struct cmDocumentationEntry;
/** \class cmGlobalNMakeMakefileGenerator
* \brief Write a NMake makefiles.
@@ -45,7 +44,7 @@ public:
}
/** Get the documentation entry for this generator. */
- static void GetDocumentation(cmDocumentationEntry& entry);
+ static cmDocumentationEntry GetDocumentation();
/**
* Try to determine system information such as shared library
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 395372b..aa1ded0 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -25,7 +25,6 @@
#include "cmsys/FStream.hxx"
#include "cmCxxModuleMapper.h"
-#include "cmDocumentationEntry.h"
#include "cmFileSet.h"
#include "cmFortranParser.h"
#include "cmGeneratedFileStream.h"
@@ -554,10 +553,10 @@ codecvt::Encoding cmGlobalNinjaGenerator::GetMakefileEncoding() const
return this->NinjaExpectedEncoding;
}
-void cmGlobalNinjaGenerator::GetDocumentation(cmDocumentationEntry& entry)
+cmDocumentationEntry cmGlobalNinjaGenerator::GetDocumentation()
{
- entry.Name = cmGlobalNinjaGenerator::GetActualName();
- entry.Brief = "Generates build.ninja files.";
+ return { cmGlobalNinjaGenerator::GetActualName(),
+ "Generates build.ninja files." };
}
// Implemented in all cmGlobaleGenerator sub-classes.
@@ -3211,10 +3210,10 @@ cmGlobalNinjaMultiGenerator::cmGlobalNinjaMultiGenerator(cmake* cm)
cm->GetState()->SetNinjaMulti(true);
}
-void cmGlobalNinjaMultiGenerator::GetDocumentation(cmDocumentationEntry& entry)
+cmDocumentationEntry cmGlobalNinjaMultiGenerator::GetDocumentation()
{
- entry.Name = cmGlobalNinjaMultiGenerator::GetActualName();
- entry.Brief = "Generates build-<Config>.ninja files.";
+ return { cmGlobalNinjaMultiGenerator::GetActualName(),
+ "Generates build-<Config>.ninja files." };
}
std::string cmGlobalNinjaMultiGenerator::ExpandCFGIntDir(
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index dac1c52..1628349 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -35,7 +35,6 @@ class cmMakefile;
class cmOutputConverter;
class cmStateDirectory;
class cmake;
-struct cmDocumentationEntry;
/**
* \class cmGlobalNinjaGenerator
@@ -193,7 +192,7 @@ public:
/** Get encoding used by generator for ninja files */
codecvt::Encoding GetMakefileEncoding() const override;
- static void GetDocumentation(cmDocumentationEntry& entry);
+ static cmDocumentationEntry GetDocumentation();
void EnableLanguage(std::vector<std::string> const& languages,
cmMakefile* mf, bool optional) override;
@@ -656,7 +655,7 @@ public:
new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaMultiGenerator>());
}
- static void GetDocumentation(cmDocumentationEntry& entry);
+ static cmDocumentationEntry GetDocumentation();
std::string GetName() const override
{
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index bf9e40e..70a9d3e 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -11,7 +11,6 @@
#include <cmext/algorithm>
#include <cmext/memory>
-#include "cmDocumentationEntry.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -71,11 +70,10 @@ cmGlobalUnixMakefileGenerator3::CreateLocalGenerator(cmMakefile* mf)
cm::make_unique<cmLocalUnixMakefileGenerator3>(this, mf));
}
-void cmGlobalUnixMakefileGenerator3::GetDocumentation(
- cmDocumentationEntry& entry)
+cmDocumentationEntry cmGlobalUnixMakefileGenerator3::GetDocumentation()
{
- entry.Name = cmGlobalUnixMakefileGenerator3::GetActualName();
- entry.Brief = "Generates standard UNIX makefiles.";
+ return { cmGlobalUnixMakefileGenerator3::GetActualName(),
+ "Generates standard UNIX makefiles." };
}
void cmGlobalUnixMakefileGenerator3::ComputeTargetObjectDirectory(
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 92e567a..214ba2a 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -24,7 +24,6 @@ class cmLocalUnixMakefileGenerator3;
class cmMakefile;
class cmMakefileTargetGenerator;
class cmake;
-struct cmDocumentationEntry;
/** \class cmGlobalUnixMakefileGenerator3
* \brief Write a Unix makefiles.
@@ -101,7 +100,7 @@ public:
bool SupportsCustomCommandDepfile() const override { return true; }
/** Get the documentation entry for this generator. */
- static void GetDocumentation(cmDocumentationEntry& entry);
+ static cmDocumentationEntry GetDocumentation();
std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
cmMakefile* mf) override;
diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx
index c53ddf5..75e3df8 100644
--- a/Source/cmGlobalVisualStudio11Generator.cxx
+++ b/Source/cmGlobalVisualStudio11Generator.cxx
@@ -7,7 +7,6 @@
#include <utility>
#include <vector>
-#include "cmDocumentationEntry.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalGeneratorFactory.h"
#include "cmGlobalVisualStudioGenerator.h"
@@ -74,11 +73,11 @@ public:
return std::unique_ptr<cmGlobalGenerator>(std::move(ret));
}
- void GetDocumentation(cmDocumentationEntry& entry) const override
+ cmDocumentationEntry GetDocumentation() const override
{
- entry.Name = std::string(vs11generatorName) + " [arch]";
- entry.Brief = "Deprecated. Generates Visual Studio 2012 project files. "
- "Optional [arch] can be \"Win64\" or \"ARM\".";
+ return { std::string(vs11generatorName) + " [arch]",
+ "Deprecated. Generates Visual Studio 2012 project files. "
+ "Optional [arch] can be \"Win64\" or \"ARM\"." };
}
std::vector<std::string> GetGeneratorNames() const override
diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx
index 600ee0a..7e56a78 100644
--- a/Source/cmGlobalVisualStudio12Generator.cxx
+++ b/Source/cmGlobalVisualStudio12Generator.cxx
@@ -6,7 +6,6 @@
#include <sstream>
#include <vector>
-#include "cmDocumentationEntry.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalGeneratorFactory.h"
#include "cmGlobalVisualStudioGenerator.h"
@@ -62,11 +61,11 @@ public:
return std::unique_ptr<cmGlobalGenerator>();
}
- void GetDocumentation(cmDocumentationEntry& entry) const override
+ cmDocumentationEntry GetDocumentation() const override
{
- entry.Name = std::string(vs12generatorName) + " [arch]";
- entry.Brief = "Generates Visual Studio 2013 project files. "
- "Optional [arch] can be \"Win64\" or \"ARM\".";
+ return { std::string(vs12generatorName) + " [arch]",
+ "Generates Visual Studio 2013 project files. "
+ "Optional [arch] can be \"Win64\" or \"ARM\"." };
}
std::vector<std::string> GetGeneratorNames() const override
diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx
index 9f94cca..0e05083 100644
--- a/Source/cmGlobalVisualStudio14Generator.cxx
+++ b/Source/cmGlobalVisualStudio14Generator.cxx
@@ -7,7 +7,6 @@
#include <cm/vector>
-#include "cmDocumentationEntry.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalGeneratorFactory.h"
#include "cmGlobalVisualStudioGenerator.h"
@@ -64,11 +63,11 @@ public:
return std::unique_ptr<cmGlobalGenerator>();
}
- void GetDocumentation(cmDocumentationEntry& entry) const override
+ cmDocumentationEntry GetDocumentation() const override
{
- entry.Name = std::string(vs14generatorName) + " [arch]";
- entry.Brief = "Generates Visual Studio 2015 project files. "
- "Optional [arch] can be \"Win64\" or \"ARM\".";
+ return { std::string(vs14generatorName) + " [arch]",
+ "Generates Visual Studio 2015 project files. "
+ "Optional [arch] can be \"Win64\" or \"ARM\"." };
}
std::vector<std::string> GetGeneratorNames() const override
diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx
index e03e665..cd0b114 100644
--- a/Source/cmGlobalVisualStudio9Generator.cxx
+++ b/Source/cmGlobalVisualStudio9Generator.cxx
@@ -6,7 +6,6 @@
#include <utility>
#include <vector>
-#include "cmDocumentationEntry.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalGeneratorFactory.h"
#include "cmGlobalVisualStudioGenerator.h"
@@ -62,11 +61,11 @@ public:
return std::unique_ptr<cmGlobalGenerator>(std::move(ret));
}
- void GetDocumentation(cmDocumentationEntry& entry) const override
+ cmDocumentationEntry GetDocumentation() const override
{
- entry.Name = std::string(vs9generatorName) + " [arch]";
- entry.Brief = "Generates Visual Studio 2008 project files. "
- "Optional [arch] can be \"Win64\" or \"IA64\".";
+ return { std::string(vs9generatorName) + " [arch]",
+ "Generates Visual Studio 2008 project files. "
+ "Optional [arch] can be \"Win64\" or \"IA64\"." };
}
std::vector<std::string> GetGeneratorNames() const override
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
index be318c1..ee24f05 100644
--- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
@@ -14,7 +14,6 @@
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"
-#include "cmDocumentationEntry.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalGeneratorFactory.h"
#include "cmMakefile.h"
@@ -255,11 +254,11 @@ public:
return std::unique_ptr<cmGlobalGenerator>();
}
- void GetDocumentation(cmDocumentationEntry& entry) const override
+ cmDocumentationEntry GetDocumentation() const override
{
- entry.Name = std::string(vs15generatorName) + " [arch]";
- entry.Brief = "Generates Visual Studio 2017 project files. "
- "Optional [arch] can be \"Win64\" or \"ARM\".";
+ return { std::string(vs15generatorName) + " [arch]",
+ "Generates Visual Studio 2017 project files. "
+ "Optional [arch] can be \"Win64\" or \"ARM\"." };
}
std::vector<std::string> GetGeneratorNames() const override
@@ -351,11 +350,11 @@ public:
return std::unique_ptr<cmGlobalGenerator>();
}
- void GetDocumentation(cmDocumentationEntry& entry) const override
+ cmDocumentationEntry GetDocumentation() const override
{
- entry.Name = std::string(vs16generatorName);
- entry.Brief = "Generates Visual Studio 2019 project files. "
- "Use -A option to specify architecture.";
+ return { std::string(vs16generatorName),
+ "Generates Visual Studio 2019 project files. "
+ "Use -A option to specify architecture." };
}
std::vector<std::string> GetGeneratorNames() const override
@@ -416,11 +415,11 @@ public:
return std::unique_ptr<cmGlobalGenerator>();
}
- void GetDocumentation(cmDocumentationEntry& entry) const override
+ cmDocumentationEntry GetDocumentation() const override
{
- entry.Name = std::string(vs17generatorName);
- entry.Brief = "Generates Visual Studio 2022 project files. "
- "Use -A option to specify architecture.";
+ return { std::string(vs17generatorName),
+ "Generates Visual Studio 2022 project files. "
+ "Use -A option to specify architecture." };
}
std::vector<std::string> GetGeneratorNames() const override
diff --git a/Source/cmGlobalWatcomWMakeGenerator.cxx b/Source/cmGlobalWatcomWMakeGenerator.cxx
index fb2a8b6..ed44e6b 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.cxx
+++ b/Source/cmGlobalWatcomWMakeGenerator.cxx
@@ -4,7 +4,6 @@
#include <ostream>
-#include "cmDocumentationEntry.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmState.h"
@@ -54,11 +53,10 @@ bool cmGlobalWatcomWMakeGenerator::SetSystemName(std::string const& s,
return this->cmGlobalUnixMakefileGenerator3::SetSystemName(s, mf);
}
-void cmGlobalWatcomWMakeGenerator::GetDocumentation(
- cmDocumentationEntry& entry)
+cmDocumentationEntry cmGlobalWatcomWMakeGenerator::GetDocumentation()
{
- entry.Name = cmGlobalWatcomWMakeGenerator::GetActualName();
- entry.Brief = "Generates Watcom WMake makefiles.";
+ return { cmGlobalWatcomWMakeGenerator::GetActualName(),
+ "Generates Watcom WMake makefiles." };
}
std::vector<cmGlobalGenerator::GeneratedMakeCommand>
diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h
index eb93934..5579120 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.h
+++ b/Source/cmGlobalWatcomWMakeGenerator.h
@@ -15,7 +15,6 @@
class cmMakefile;
class cmake;
-struct cmDocumentationEntry;
/** \class cmGlobalWatcomWMakeGenerator
* \brief Write a NMake makefiles.
@@ -39,7 +38,7 @@ public:
static std::string GetActualName() { return "Watcom WMake"; }
/** Get the documentation entry for this generator. */
- static void GetDocumentation(cmDocumentationEntry& entry);
+ static cmDocumentationEntry GetDocumentation();
/** Tell the generator about the target system. */
bool SetSystemName(std::string const& s, cmMakefile* mf) override;
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 62e5a1e..0e94de5 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -24,7 +24,6 @@
#include "cmCustomCommandGenerator.h"
#include "cmCustomCommandLines.h"
#include "cmCustomCommandTypes.h"
-#include "cmDocumentationEntry.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
@@ -149,9 +148,9 @@ public:
std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
const std::string& name, bool allowArch, cmake* cm) const override;
- void GetDocumentation(cmDocumentationEntry& entry) const override
+ cmDocumentationEntry GetDocumentation() const override
{
- cmGlobalXCodeGenerator::GetDocumentation(entry);
+ return cmGlobalXCodeGenerator::GetDocumentation();
}
std::vector<std::string> GetGeneratorNames() const override
@@ -4864,10 +4863,10 @@ std::string cmGlobalXCodeGenerator::ExpandCFGIntDir(
return tmp;
}
-void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry& entry)
+cmDocumentationEntry cmGlobalXCodeGenerator::GetDocumentation()
{
- entry.Name = cmGlobalXCodeGenerator::GetActualName();
- entry.Brief = "Generate Xcode project files.";
+ return { cmGlobalXCodeGenerator::GetActualName(),
+ "Generate Xcode project files." };
}
std::string cmGlobalXCodeGenerator::ConvertToRelativeForMake(
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 9ae75fb..856852b 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -14,6 +14,7 @@
#include <cm/optional>
#include <cm/string_view>
+#include "cmDocumentationEntry.h"
#include "cmGlobalGenerator.h"
#include "cmTransformDepfile.h"
#include "cmValue.h"
@@ -28,7 +29,6 @@ class cmMakefile;
class cmSourceFile;
class cmSourceGroup;
class cmake;
-struct cmDocumentationEntry;
/** \class cmGlobalXCodeGenerator
* \brief Write a Unix makefiles.
@@ -54,7 +54,7 @@ public:
static std::string GetActualName() { return "Xcode"; }
/** Get the documentation entry for this generator. */
- static void GetDocumentation(cmDocumentationEntry& entry);
+ static cmDocumentationEntry GetDocumentation();
//! Create a local generator appropriate to this Global Generator
std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx
index 333003b..ff513be 100644
--- a/Source/cmMessenger.cxx
+++ b/Source/cmMessenger.cxx
@@ -107,8 +107,8 @@ static void printMessageText(std::ostream& msg, std::string const& text)
{
msg << ":\n";
cmDocumentationFormatter formatter;
- formatter.SetIndent(" ");
- formatter.PrintFormatted(msg, text.c_str());
+ formatter.SetIndent(2u);
+ formatter.PrintFormatted(msg, text);
}
static void displayMessage(MessageType t, std::ostringstream& msg)
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 895a4c3..21409d7 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -1112,7 +1112,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
this->GetObjectFilePath(source, config));
}
}
- linkBuild.Outputs.push_back(vars["SWIFT_MODULE"]);
+ if (targetType != cmStateEnums::EXECUTABLE) {
+ linkBuild.Outputs.push_back(vars["SWIFT_MODULE"]);
+ }
} else {
linkBuild.ExplicitDeps = this->GetObjects(config);
}
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 78d230e..f94c4d3 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -1111,16 +1111,9 @@ bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname,
}
#endif
-bool cmSystemTools::CopySingleFile(const std::string& oldname,
- const std::string& newname)
-{
- return cmSystemTools::CopySingleFile(oldname, newname, CopyWhen::Always) ==
- CopyResult::Success;
-}
-
cmSystemTools::CopyResult cmSystemTools::CopySingleFile(
std::string const& oldname, std::string const& newname, CopyWhen when,
- std::string* err)
+ CopyInputRecent inputRecent, std::string* err)
{
switch (when) {
case CopyWhen::Always:
@@ -1144,7 +1137,24 @@ cmSystemTools::CopyResult cmSystemTools::CopySingleFile(
status = cmsys::SystemTools::CloneFileContent(oldname, newname);
if (!status) {
// if cloning did not succeed, fall back to blockwise copy
+#ifdef _WIN32
+ if (inputRecent == CopyInputRecent::Yes) {
+ // Windows sometimes locks a file immediately after creation.
+ // Retry a few times.
+ WindowsFileRetry retry = cmSystemTools::GetWindowsFileRetry();
+ while ((status =
+ cmsys::SystemTools::CopyFileContentBlockwise(oldname, newname),
+ status.Path == cmsys::SystemTools::CopyStatus::SourcePath &&
+ status.GetPOSIX() == EACCES && --retry.Count)) {
+ cmSystemTools::Delay(retry.Delay);
+ }
+ } else {
+ status = cmsys::SystemTools::CopyFileContentBlockwise(oldname, newname);
+ }
+#else
+ static_cast<void>(inputRecent);
status = cmsys::SystemTools::CopyFileContentBlockwise(oldname, newname);
+#endif
}
if (!status) {
if (err) {
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 87b354c..09f2bf0 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -149,6 +149,11 @@ public:
Always,
OnlyIfDifferent,
};
+ enum class CopyInputRecent
+ {
+ No,
+ Yes,
+ };
enum class CopyResult
{
Success,
@@ -177,10 +182,9 @@ public:
const mode_t* mode = nullptr);
/** Copy a file. */
- static bool CopySingleFile(const std::string& oldname,
- const std::string& newname);
static CopyResult CopySingleFile(std::string const& oldname,
std::string const& newname, CopyWhen when,
+ CopyInputRecent inputRecent,
std::string* err = nullptr);
enum class Replace
diff --git a/Source/cmVersionConfig.h.in b/Source/cmVersionConfig.h.in
index 06251f3..5d52950 100644
--- a/Source/cmVersionConfig.h.in
+++ b/Source/cmVersionConfig.h.in
@@ -1,5 +1,7 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
#define CMake_VERSION_MAJOR @CMake_VERSION_MAJOR@
#define CMake_VERSION_MINOR @CMake_VERSION_MINOR@
#define CMake_VERSION_PATCH @CMake_VERSION_PATCH@
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 36c0089..befcb55 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -40,7 +40,6 @@
#include "cmCommands.h"
#include "cmDocumentation.h"
#include "cmDocumentationEntry.h"
-#include "cmDocumentationFormatter.h"
#include "cmDuration.h"
#include "cmExternalMakefileProjectGenerator.h"
#include "cmFileTimeCache.h"
@@ -150,21 +149,136 @@ auto IgnoreAndTrueLambda = [](std::string const&, cmake*) -> bool {
using CommandArgument =
cmCommandLineArgument<bool(std::string const& value, cmake* state)>;
-} // namespace
-
-static bool cmakeCheckStampFile(const std::string& stampName);
-static bool cmakeCheckStampList(const std::string& stampList);
-
#ifndef CMAKE_BOOTSTRAP
-static void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/,
- void* ctx, const char* /*unused*/,
- const cmMakefile* /*unused*/)
+void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/,
+ void* ctx, const char* /*unused*/,
+ const cmMakefile* /*unused*/)
{
cmake* cm = reinterpret_cast<cmake*>(ctx);
cm->MarkCliAsUsed(variable);
}
#endif
+bool cmakeCheckStampFile(const std::string& stampName)
+{
+ // The stamp file does not exist. Use the stamp dependencies to
+ // determine whether it is really out of date. This works in
+ // conjunction with cmLocalVisualStudio7Generator to avoid
+ // repeatedly re-running CMake when the user rebuilds the entire
+ // solution.
+ std::string stampDepends = cmStrCat(stampName, ".depend");
+#if defined(_WIN32) || defined(__CYGWIN__)
+ cmsys::ifstream fin(stampDepends.c_str(), std::ios::in | std::ios::binary);
+#else
+ cmsys::ifstream fin(stampDepends.c_str());
+#endif
+ if (!fin) {
+ // The stamp dependencies file cannot be read. Just assume the
+ // build system is really out of date.
+ std::cout << "CMake is re-running because " << stampName
+ << " dependency file is missing.\n";
+ return false;
+ }
+
+ // Compare the stamp dependencies against the dependency file itself.
+ {
+ cmFileTimeCache ftc;
+ std::string dep;
+ while (cmSystemTools::GetLineFromStream(fin, dep)) {
+ int result;
+ if (!dep.empty() && dep[0] != '#' &&
+ (!ftc.Compare(stampDepends, dep, &result) || result < 0)) {
+ // The stamp depends file is older than this dependency. The
+ // build system is really out of date.
+ /* clang-format off */
+ std::cout << "CMake is re-running because " << stampName
+ << " is out-of-date.\n"
+ " the file '" << dep << "'\n"
+ " is newer than '" << stampDepends << "'\n"
+ " result='" << result << "'\n";
+ /* clang-format on */
+ return false;
+ }
+ }
+ }
+
+ // The build system is up to date. The stamp file has been removed
+ // by the VS IDE due to a "rebuild" request. Restore it atomically.
+ std::ostringstream stampTempStream;
+ stampTempStream << stampName << ".tmp" << cmSystemTools::RandomSeed();
+ std::string stampTemp = stampTempStream.str();
+ {
+ // TODO: Teach cmGeneratedFileStream to use a random temp file (with
+ // multiple tries in unlikely case of conflict) and use that here.
+ cmsys::ofstream stamp(stampTemp.c_str());
+ stamp << "# CMake generation timestamp file for this directory.\n";
+ }
+ std::string err;
+ if (cmSystemTools::RenameFile(stampTemp, stampName,
+ cmSystemTools::Replace::Yes, &err) ==
+ cmSystemTools::RenameResult::Success) {
+ // CMake does not need to re-run because the stamp file is up-to-date.
+ return true;
+ }
+ cmSystemTools::RemoveFile(stampTemp);
+ cmSystemTools::Error(
+ cmStrCat("Cannot restore timestamp \"", stampName, "\": ", err));
+ return false;
+}
+
+bool cmakeCheckStampList(const std::string& stampList)
+{
+ // If the stamp list does not exist CMake must rerun to generate it.
+ if (!cmSystemTools::FileExists(stampList)) {
+ std::cout << "CMake is re-running because generate.stamp.list "
+ "is missing.\n";
+ return false;
+ }
+ cmsys::ifstream fin(stampList.c_str());
+ if (!fin) {
+ std::cout << "CMake is re-running because generate.stamp.list "
+ "could not be read.\n";
+ return false;
+ }
+
+ // Check each stamp.
+ std::string stampName;
+ while (cmSystemTools::GetLineFromStream(fin, stampName)) {
+ if (!cmakeCheckStampFile(stampName)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace
+
+cmDocumentationEntry cmake::CMAKE_STANDARD_OPTIONS_TABLE[18] = {
+ { "-S <path-to-source>", "Explicitly specify a source directory." },
+ { "-B <path-to-build>", "Explicitly specify a build directory." },
+ { "-C <initial-cache>", "Pre-load a script to populate the cache." },
+ { "-D <var>[:<type>]=<value>", "Create or update a cmake cache entry." },
+ { "-U <globbing_expr>", "Remove matching entries from CMake cache." },
+ { "-G <generator-name>", "Specify a build system generator." },
+ { "-T <toolset-name>", "Specify toolset name if supported by generator." },
+ { "-A <platform-name>", "Specify platform name if supported by generator." },
+ { "--toolchain <file>", "Specify toolchain file [CMAKE_TOOLCHAIN_FILE]." },
+ { "--install-prefix <directory>",
+ "Specify install directory [CMAKE_INSTALL_PREFIX]." },
+ { "-Wdev", "Enable developer warnings." },
+ { "-Wno-dev", "Suppress developer warnings." },
+ { "-Werror=dev", "Make developer warnings errors." },
+ { "-Wno-error=dev", "Make developer warnings not errors." },
+ { "-Wdeprecated", "Enable deprecation warnings." },
+ { "-Wno-deprecated", "Suppress deprecation warnings." },
+ { "-Werror=deprecated",
+ "Make deprecated macro and function warnings "
+ "errors." },
+ { "-Wno-error=deprecated",
+ "Make deprecated macro and function warnings "
+ "not errors." }
+};
+
cmake::cmake(Role role, cmState::Mode mode, cmState::ProjectKind projectKind)
: CMakeWorkingDirectory(cmSystemTools::GetCurrentWorkingDirectory())
, FileTimeCache(cm::make_unique<cmFileTimeCache>())
@@ -1008,7 +1122,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
std::cout << "Running with debug output on for the 'find' commands "
"for package(s)";
for (auto const& v : find_pkgs) {
- std::cout << " " << v;
+ std::cout << ' ' << v;
state->SetDebugFindOutputPkgs(v);
}
std::cout << ".\n";
@@ -1021,7 +1135,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
std::vector<std::string> find_vars(cmTokenize(value, ","));
std::cout << "Running with debug output on for the variable(s)";
for (auto const& v : find_vars) {
- std::cout << " " << v;
+ std::cout << ' ' << v;
state->SetDebugFindOutputVars(v);
}
std::cout << ".\n";
@@ -1082,7 +1196,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
[](std::string const&, cmake* state) -> bool {
std::cout
<< "Not searching for unused variables given on the "
- << "command line.\n";
+ "command line.\n";
state->SetWarnUnusedCli(false);
return true;
} },
@@ -1090,7 +1204,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
"--check-system-vars", CommandArgument::Values::Zero,
[](std::string const&, cmake* state) -> bool {
std::cout << "Also check system files when warning about unused and "
- << "uninitialized variables.\n";
+ "uninitialized variables.\n";
state->SetCheckSystemVars(true);
return true;
} },
@@ -1098,7 +1212,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
"--compile-no-warning-as-error", CommandArgument::Values::Zero,
[](std::string const&, cmake* state) -> bool {
std::cout << "Ignoring COMPILE_WARNING_AS_ERROR target property and "
- << "CMAKE_COMPILE_WARNING_AS_ERROR variable.\n";
+ "CMAKE_COMPILE_WARNING_AS_ERROR variable.\n";
state->SetIgnoreWarningAsError(true);
return true;
} }
@@ -1497,7 +1611,7 @@ void cmake::SetTraceFile(const std::string& file)
cmSystemTools::Error(ss.str());
return;
}
- std::cout << "Trace will be written to " << file << "\n";
+ std::cout << "Trace will be written to " << file << '\n';
}
void cmake::PrintTraceFormatVersion()
@@ -2020,12 +2134,10 @@ int cmake::HandleDeleteCacheVariables(const std::string& var)
}
std::vector<SaveCacheEntry> saved;
std::ostringstream warning;
- /* clang-format off */
warning
<< "You have changed variables that require your cache to be deleted.\n"
- << "Configure will be re-run and you may have to reset some variables.\n"
- << "The following variables have changed:\n";
- /* clang-format on */
+ "Configure will be re-run and you may have to reset some variables.\n"
+ "The following variables have changed:\n";
for (auto i = argsSplit.begin(); i != argsSplit.end(); ++i) {
SaveCacheEntry save;
save.key = *i;
@@ -2033,9 +2145,9 @@ int cmake::HandleDeleteCacheVariables(const std::string& var)
i++;
if (i != argsSplit.end()) {
save.value = *i;
- warning << *i << "\n";
+ warning << *i << '\n';
} else {
- warning << "\n";
+ warning << '\n';
i -= 1;
}
cmValue existingValue = this->State->GetCacheEntryValue(save.key);
@@ -2437,7 +2549,7 @@ void cmake::CreateDefaultGlobalGenerator()
auto gen = this->EvaluateDefaultGlobalGenerator();
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
// This print could be unified for all platforms
- std::cout << "-- Building for: " << gen->GetName() << "\n";
+ std::cout << "-- Building for: " << gen->GetName() << '\n';
#endif
this->SetGlobalGenerator(std::move(gen));
}
@@ -2596,7 +2708,7 @@ int cmake::Generate()
}
this->GlobalGenerator->Generate();
if (!this->GraphVizFile.empty()) {
- std::cout << "Generate graphviz: " << this->GraphVizFile << std::endl;
+ std::cout << "Generate graphviz: " << this->GraphVizFile << '\n';
this->GenerateGraphViz(this->GraphVizFile);
}
if (this->WarnUnusedCli) {
@@ -2837,17 +2949,15 @@ void cmake::AppendGlobalGeneratorsDocumentation(
std::vector<cmDocumentationEntry>& v)
{
const auto defaultGenerator = this->EvaluateDefaultGlobalGenerator();
- const std::string defaultName = defaultGenerator->GetName();
- bool foundDefaultOne = false;
+ const auto defaultName = defaultGenerator->GetName();
+ auto foundDefaultOne = false;
for (const auto& g : this->Generators) {
- cmDocumentationEntry e;
- g->GetDocumentation(e);
- if (!foundDefaultOne && cmHasPrefix(e.Name, defaultName)) {
- e.CustomNamePrefix = '*';
+ v.emplace_back(g->GetDocumentation());
+ if (!foundDefaultOne && cmHasPrefix(v.back().Name, defaultName)) {
+ v.back().CustomNamePrefix = '*';
foundDefaultOne = true;
}
- v.push_back(std::move(e));
}
}
@@ -2860,21 +2970,14 @@ void cmake::AppendExtraGeneratorsDocumentation(
// Aliases:
for (std::string const& a : eg->Aliases) {
- cmDocumentationEntry e;
- e.Name = a;
- e.Brief = doc;
- v.push_back(std::move(e));
+ v.emplace_back(cmDocumentationEntry{ a, doc });
}
// Full names:
- const std::vector<std::string> generators =
- eg->GetSupportedGlobalGenerators();
- for (std::string const& g : generators) {
- cmDocumentationEntry e;
- e.Name =
- cmExternalMakefileProjectGenerator::CreateFullGeneratorName(g, name);
- e.Brief = doc;
- v.push_back(std::move(e));
+ for (std::string const& g : eg->GetSupportedGlobalGenerators()) {
+ v.emplace_back(cmDocumentationEntry{
+ cmExternalMakefileProjectGenerator::CreateFullGeneratorName(g, name),
+ doc });
}
}
}
@@ -2893,7 +2996,7 @@ void cmake::PrintGeneratorList()
cmDocumentation doc;
auto generators = this->GetGeneratorsDocumentation();
doc.AppendSection("Generators", generators);
- std::cerr << "\n";
+ std::cerr << '\n';
doc.PrintDocumentation(cmDocumentation::ListGenerators, std::cerr);
#endif
}
@@ -2945,7 +3048,7 @@ int cmake::CheckBuildSystem()
if (verbose) {
std::ostringstream msg;
msg << "Re-run cmake missing file: " << this->CheckBuildSystemArgument
- << "\n";
+ << '\n';
cmSystemTools::Stdout(msg.str());
}
return 1;
@@ -2965,7 +3068,7 @@ int cmake::CheckBuildSystem()
if (verbose) {
std::ostringstream msg;
msg << "Re-run cmake error reading : " << this->CheckBuildSystemArgument
- << "\n";
+ << '\n';
cmSystemTools::Stdout(msg.str());
}
// There was an error reading the file. Just rerun.
@@ -2996,9 +3099,8 @@ int cmake::CheckBuildSystem()
for (std::string const& p : products) {
if (!(cmSystemTools::FileExists(p) || cmSystemTools::FileIsSymlink(p))) {
if (verbose) {
- std::ostringstream msg;
- msg << "Re-run cmake, missing byproduct: " << p << "\n";
- cmSystemTools::Stdout(msg.str());
+ cmSystemTools::Stdout(
+ cmStrCat("Re-run cmake, missing byproduct: ", p, '\n'));
}
return 1;
}
@@ -3063,7 +3165,7 @@ int cmake::CheckBuildSystem()
if (verbose) {
std::ostringstream msg;
msg << "Re-run cmake file: " << out_oldest
- << " older than: " << dep_newest << "\n";
+ << " older than: " << dep_newest << '\n';
cmSystemTools::Stdout(msg.str());
}
return 1;
@@ -3239,7 +3341,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
// permissions are questionable or some other process has deleted the
// directory
std::cerr << "Failed to change to directory " << destPath << " : "
- << std::strerror(workdir.GetLastResult()) << std::endl;
+ << std::strerror(workdir.GetLastResult()) << '\n';
return 1;
}
std::vector<std::string> args2;
@@ -3276,96 +3378,6 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
return 0;
}
-static bool cmakeCheckStampFile(const std::string& stampName)
-{
- // The stamp file does not exist. Use the stamp dependencies to
- // determine whether it is really out of date. This works in
- // conjunction with cmLocalVisualStudio7Generator to avoid
- // repeatedly re-running CMake when the user rebuilds the entire
- // solution.
- std::string stampDepends = cmStrCat(stampName, ".depend");
-#if defined(_WIN32) || defined(__CYGWIN__)
- cmsys::ifstream fin(stampDepends.c_str(), std::ios::in | std::ios::binary);
-#else
- cmsys::ifstream fin(stampDepends.c_str());
-#endif
- if (!fin) {
- // The stamp dependencies file cannot be read. Just assume the
- // build system is really out of date.
- std::cout << "CMake is re-running because " << stampName
- << " dependency file is missing.\n";
- return false;
- }
-
- // Compare the stamp dependencies against the dependency file itself.
- {
- cmFileTimeCache ftc;
- std::string dep;
- while (cmSystemTools::GetLineFromStream(fin, dep)) {
- int result;
- if (!dep.empty() && dep[0] != '#' &&
- (!ftc.Compare(stampDepends, dep, &result) || result < 0)) {
- // The stamp depends file is older than this dependency. The
- // build system is really out of date.
- std::cout << "CMake is re-running because " << stampName
- << " is out-of-date.\n";
- std::cout << " the file '" << dep << "'\n";
- std::cout << " is newer than '" << stampDepends << "'\n";
- std::cout << " result='" << result << "'\n";
- return false;
- }
- }
- }
-
- // The build system is up to date. The stamp file has been removed
- // by the VS IDE due to a "rebuild" request. Restore it atomically.
- std::ostringstream stampTempStream;
- stampTempStream << stampName << ".tmp" << cmSystemTools::RandomSeed();
- std::string stampTemp = stampTempStream.str();
- {
- // TODO: Teach cmGeneratedFileStream to use a random temp file (with
- // multiple tries in unlikely case of conflict) and use that here.
- cmsys::ofstream stamp(stampTemp.c_str());
- stamp << "# CMake generation timestamp file for this directory.\n";
- }
- std::string err;
- if (cmSystemTools::RenameFile(stampTemp, stampName,
- cmSystemTools::Replace::Yes, &err) ==
- cmSystemTools::RenameResult::Success) {
- // CMake does not need to re-run because the stamp file is up-to-date.
- return true;
- }
- cmSystemTools::RemoveFile(stampTemp);
- cmSystemTools::Error(
- cmStrCat("Cannot restore timestamp \"", stampName, "\": ", err));
- return false;
-}
-
-static bool cmakeCheckStampList(const std::string& stampList)
-{
- // If the stamp list does not exist CMake must rerun to generate it.
- if (!cmSystemTools::FileExists(stampList)) {
- std::cout << "CMake is re-running because generate.stamp.list "
- << "is missing.\n";
- return false;
- }
- cmsys::ifstream fin(stampList.c_str());
- if (!fin) {
- std::cout << "CMake is re-running because generate.stamp.list "
- << "could not be read.\n";
- return false;
- }
-
- // Check each stamp.
- std::string stampName;
- while (cmSystemTools::GetLineFromStream(fin, stampName)) {
- if (!cmakeCheckStampFile(stampName)) {
- return false;
- }
- }
- return true;
-}
-
void cmake::IssueMessage(MessageType t, std::string const& text,
cmListFileBacktrace const& backtrace) const
{
diff --git a/Source/cmake.h b/Source/cmake.h
index 6b585a1..325c0c5 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -18,6 +18,7 @@
#include <cm/string_view>
#include <cmext/string_view>
+#include "cmDocumentationEntry.h"
#include "cmGeneratedFileStream.h"
#include "cmInstalledFile.h"
#include "cmListFileCache.h"
@@ -45,7 +46,6 @@ class cmMakefile;
class cmMessenger;
class cmVariableWatch;
struct cmBuildOptions;
-struct cmDocumentationEntry;
/** \brief Represents a cmake invocation.
*
@@ -793,37 +793,10 @@ private:
#if !defined(CMAKE_BOOTSTRAP)
std::unique_ptr<cmMakefileProfilingData> ProfilingOutput;
#endif
-};
-#define CMAKE_STANDARD_OPTIONS_TABLE \
- { "-S <path-to-source>", "Explicitly specify a source directory." }, \
- { "-B <path-to-build>", "Explicitly specify a build directory." }, \
- { "-C <initial-cache>", "Pre-load a script to populate the cache." }, \
- { "-D <var>[:<type>]=<value>", "Create or update a cmake cache entry." }, \
- { "-U <globbing_expr>", "Remove matching entries from CMake cache." }, \
- { "-G <generator-name>", "Specify a build system generator." }, \
- { "-T <toolset-name>", \
- "Specify toolset name if supported by generator." }, \
- { "-A <platform-name>", \
- "Specify platform name if supported by generator." }, \
- { "--toolchain <file>", \
- "Specify toolchain file [CMAKE_TOOLCHAIN_FILE]." }, \
- { "--install-prefix <directory>", \
- "Specify install directory [CMAKE_INSTALL_PREFIX]." }, \
- { "-Wdev", "Enable developer warnings." }, \
- { "-Wno-dev", "Suppress developer warnings." }, \
- { "-Werror=dev", "Make developer warnings errors." }, \
- { "-Wno-error=dev", "Make developer warnings not errors." }, \
- { "-Wdeprecated", "Enable deprecation warnings." }, \
- { "-Wno-deprecated", "Suppress deprecation warnings." }, \
- { "-Werror=deprecated", \
- "Make deprecated macro and function warnings " \
- "errors." }, \
- { \
- "-Wno-error=deprecated", \
- "Make deprecated macro and function warnings " \
- "not errors." \
- }
+public:
+ static cmDocumentationEntry CMAKE_STANDARD_OPTIONS_TABLE[18];
+};
#define FOR_EACH_C90_FEATURE(F) F(c_function_prototypes)
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 9f23667..a155787 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -24,7 +24,7 @@
#include "cmBuildOptions.h"
#include "cmCommandLineArgument.h"
#include "cmConsoleBuf.h"
-#include "cmDocumentationEntry.h" // IWYU pragma: keep
+#include "cmDocumentationEntry.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageMetadata.h"
@@ -46,30 +46,28 @@
namespace {
#ifndef CMAKE_BOOTSTRAP
-const char* cmDocumentationName[][2] = {
- { nullptr, " cmake - Cross-Platform Makefile Generator." },
- { nullptr, nullptr }
+const cmDocumentationEntry cmDocumentationName = {
+ {},
+ " cmake - Cross-Platform Makefile Generator."
};
-const char* cmDocumentationUsage[][2] = {
- { nullptr,
+const cmDocumentationEntry cmDocumentationUsage[2] = {
+ { {},
" cmake [options] <path-to-source>\n"
" cmake [options] <path-to-existing-build>\n"
" cmake [options] -S <path-to-source> -B <path-to-build>" },
- { nullptr,
+ { {},
"Specify a source directory to (re-)generate a build system for "
"it in the current working directory. Specify an existing build "
- "directory to re-generate its build system." },
- { nullptr, nullptr }
+ "directory to re-generate its build system." }
};
-const char* cmDocumentationUsageNote[][2] = {
- { nullptr, "Run 'cmake --help' for more information." },
- { nullptr, nullptr }
+const cmDocumentationEntry cmDocumentationUsageNote = {
+ {},
+ "Run 'cmake --help' for more information."
};
-const char* cmDocumentationOptions[][2] = {
- CMAKE_STANDARD_OPTIONS_TABLE,
+const cmDocumentationEntry cmDocumentationOptions[31] = {
{ "--preset <preset>,--preset=<preset>", "Specify a configure preset." },
{ "--list-presets[=<type>]", "List available presets." },
{ "-E", "CMake command mode." },
@@ -113,15 +111,12 @@ const char* cmDocumentationOptions[][2] = {
{ "--compile-no-warning-as-error",
"Ignore COMPILE_WARNING_AS_ERROR property and "
"CMAKE_COMPILE_WARNING_AS_ERROR variable." },
-# if !defined(CMAKE_BOOTSTRAP)
{ "--profiling-format=<fmt>",
"Output data for profiling CMake scripts. Supported formats: "
"google-trace" },
{ "--profiling-output=<file>",
"Select an output path for the profiling data enabled through "
- "--profiling-format." },
-# endif
- { nullptr, nullptr }
+ "--profiling-format." }
};
#endif
@@ -228,8 +223,9 @@ int do_cmake(int ac, char const* const* av)
}
doc.AppendSection("Generators", generators);
doc.PrependSection("Options", cmDocumentationOptions);
+ doc.PrependSection("Options", cmake::CMAKE_STANDARD_OPTIONS_TABLE);
- return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1;
+ return !doc.PrintRequestedDocumentation(std::cout);
}
#else
if (ac == 1) {
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index 363f473..fa38a65 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -11,21 +11,21 @@
#include "cmCTest.h"
#include "cmConsoleBuf.h"
#include "cmDocumentation.h"
+#include "cmDocumentationEntry.h"
#include "cmSystemTools.h"
#include "CTest/cmCTestLaunch.h"
#include "CTest/cmCTestScriptHandler.h"
-static const char* cmDocumentationName[][2] = {
- { nullptr, " ctest - Testing driver provided by CMake." },
- { nullptr, nullptr }
+namespace {
+const cmDocumentationEntry cmDocumentationName = {
+ {},
+ " ctest - Testing driver provided by CMake."
};
-static const char* cmDocumentationUsage[][2] = { { nullptr,
- " ctest [options]" },
- { nullptr, nullptr } };
+const cmDocumentationEntry cmDocumentationUsage = { {}, " ctest [options]" };
-static const char* cmDocumentationOptions[][2] = {
+const cmDocumentationEntry cmDocumentationOptions[74] = {
{ "--preset <preset>, --preset=<preset>",
"Read arguments from a test preset." },
{ "--list-presets", "List available test presets." },
@@ -155,9 +155,9 @@ static const char* cmDocumentationOptions[][2] = {
{ "--no-compress-output", "Do not compress test output when submitting." },
{ "--print-labels", "Print all available test labels." },
{ "--no-tests=<[error|ignore]>",
- "Regard no tests found either as 'error' or 'ignore' it." },
- { nullptr, nullptr }
+ "Regard no tests found either as 'error' or 'ignore' it." }
};
+} // anonymous namespace
// this is a test driver program for cmCTest.
int main(int argc, char const* const* argv)
@@ -186,8 +186,7 @@ int main(int argc, char const* const* argv)
if (cmSystemTools::GetCurrentWorkingDirectory().empty()) {
cmCTestLog(&inst, ERROR_MESSAGE,
- "Current working directory cannot be established."
- << std::endl);
+ "Current working directory cannot be established.\n");
return 1;
}
@@ -199,10 +198,9 @@ int main(int argc, char const* const* argv)
cmSystemTools::FileExists("DartTestfile.txt"))) {
if (argc == 1) {
cmCTestLog(&inst, ERROR_MESSAGE,
- "*********************************"
- << std::endl
- << "No test configuration file found!" << std::endl
- << "*********************************" << std::endl);
+ "*********************************\n"
+ "No test configuration file found!\n"
+ "*********************************\n");
}
cmDocumentation doc;
doc.addCTestStandardDocSections();
@@ -216,7 +214,7 @@ int main(int argc, char const* const* argv)
doc.SetSection("Name", cmDocumentationName);
doc.SetSection("Usage", cmDocumentationUsage);
doc.PrependSection("Options", cmDocumentationOptions);
- return doc.PrintRequestedDocumentation(std::cout) ? 0 : 1;
+ return !doc.PrintRequestedDocumentation(std::cout);
}
}
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
index 9ab565a..9ab565a 100644
--- a/Tests/CMakeTests/FileDownloadInput.png
+++ b/Tests/CMakeTests/FileUploadInput.png
Binary files differ
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/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/ExportImport/BuildInstallInterfaceGenex-export.cmake b/Tests/RunCMake/ExportImport/BuildInstallInterfaceGenex-export.cmake
new file mode 100644
index 0000000..94076bb
--- /dev/null
+++ b/Tests/RunCMake/ExportImport/BuildInstallInterfaceGenex-export.cmake
@@ -0,0 +1,14 @@
+enable_language(C)
+
+add_library(mainlib STATIC foo.c)
+target_compile_definitions(mainlib INTERFACE
+ $<BUILD_LOCAL_INTERFACE:BUILD_LOCAL_INTERFACE>
+ $<BUILD_INTERFACE:BUILD_INTERFACE>
+ $<INSTALL_INTERFACE:INSTALL_INTERFACE>
+ )
+add_library(locallib STATIC locallib.c)
+target_link_libraries(locallib PRIVATE mainlib)
+
+install(TARGETS mainlib EXPORT export)
+install(EXPORT export DESTINATION lib/cmake/install FILE install-config.cmake NAMESPACE install::)
+export(EXPORT export FILE build-config.cmake NAMESPACE build::)
diff --git a/Tests/RunCMake/ExportImport/BuildInstallInterfaceGenex-import.cmake b/Tests/RunCMake/ExportImport/BuildInstallInterfaceGenex-import.cmake
new file mode 100644
index 0000000..3fe5fae
--- /dev/null
+++ b/Tests/RunCMake/ExportImport/BuildInstallInterfaceGenex-import.cmake
@@ -0,0 +1,9 @@
+enable_language(C)
+
+find_package(build REQUIRED)
+find_package(install REQUIRED)
+
+add_library(buildlib STATIC buildlib.c)
+target_link_libraries(buildlib PRIVATE build::mainlib)
+add_library(installlib STATIC installlib.c)
+target_link_libraries(installlib PRIVATE install::mainlib)
diff --git a/Tests/RunCMake/ExportImport/RunCMakeTest.cmake b/Tests/RunCMake/ExportImport/RunCMakeTest.cmake
index d07fca2..b730047 100644
--- a/Tests/RunCMake/ExportImport/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ExportImport/RunCMakeTest.cmake
@@ -22,3 +22,28 @@ function(run_ExportImport_test case)
endfunction()
run_ExportImport_test(SharedDep)
+
+function(run_ExportImportBuildInstall_test case)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-export-build)
+ set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root)
+ if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
+ endif()
+ run_cmake(${case}-export)
+ unset(RunCMake_TEST_OPTIONS)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(${case}-export-build ${CMAKE_COMMAND} --build . --config Debug)
+ run_cmake_command(${case}-export-install ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DBUILD_TYPE=Debug -P cmake_install.cmake)
+ unset(RunCMake_TEST_NO_CLEAN)
+
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-import-build)
+ run_cmake_with_options(${case}-import
+ -Dbuild_DIR=${RunCMake_BINARY_DIR}/${case}-export-build
+ -Dinstall_DIR=${CMAKE_INSTALL_PREFIX}/lib/cmake/install
+ )
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(${case}-import-build ${CMAKE_COMMAND} --build . --config Debug)
+ unset(RunCMake_TEST_NO_CLEAN)
+endfunction()
+
+run_ExportImportBuildInstall_test(BuildInstallInterfaceGenex)
diff --git a/Tests/RunCMake/ExportImport/buildlib.c b/Tests/RunCMake/ExportImport/buildlib.c
new file mode 100644
index 0000000..ac19310
--- /dev/null
+++ b/Tests/RunCMake/ExportImport/buildlib.c
@@ -0,0 +1,8 @@
+#if !(!defined(BUILD_LOCAL_INTERFACE) && defined(BUILD_INTERFACE) && \
+ !defined(INSTALL_INTERFACE))
+# error "Incorrect compile definitions"
+#endif
+
+void buildlib(void)
+{
+}
diff --git a/Tests/RunCMake/ExportImport/installlib.c b/Tests/RunCMake/ExportImport/installlib.c
new file mode 100644
index 0000000..00d503c
--- /dev/null
+++ b/Tests/RunCMake/ExportImport/installlib.c
@@ -0,0 +1,8 @@
+#if !(!defined(BUILD_LOCAL_INTERFACE) && !defined(BUILD_INTERFACE) && \
+ defined(INSTALL_INTERFACE))
+# error "Incorrect compile definitions"
+#endif
+
+void installlib(void)
+{
+}
diff --git a/Tests/RunCMake/ExportImport/locallib.c b/Tests/RunCMake/ExportImport/locallib.c
new file mode 100644
index 0000000..f9e3d8d
--- /dev/null
+++ b/Tests/RunCMake/ExportImport/locallib.c
@@ -0,0 +1,8 @@
+#if !(defined(BUILD_LOCAL_INTERFACE) && defined(BUILD_INTERFACE) && \
+ !defined(INSTALL_INTERFACE))
+# error "Incorrect compile definitions"
+#endif
+
+void locallib(void)
+{
+}
diff --git a/Tests/RunCMake/GenEx-TARGET_PROPERTY/RunCMakeTest.cmake b/Tests/RunCMake/GenEx-TARGET_PROPERTY/RunCMakeTest.cmake
index ac0843e..b613ad1 100644
--- a/Tests/RunCMake/GenEx-TARGET_PROPERTY/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GenEx-TARGET_PROPERTY/RunCMakeTest.cmake
@@ -13,3 +13,10 @@ run_cmake(LinkImplementationCycle5)
run_cmake(LinkImplementationCycle6)
run_cmake(LOCATION)
run_cmake(SOURCES)
+
+block()
+ run_cmake(Scope)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Scope-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(Scope-build ${CMAKE_COMMAND} --build . --config Debug)
+endblock()
diff --git a/Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope-build-stdout.txt b/Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope-build-stdout.txt
new file mode 100644
index 0000000..fefad22
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope-build-stdout.txt
@@ -0,0 +1,6 @@
+.*iface scope1: 'SCOPED_A_1;SCOPED_B_1'
+.*iface scope2: 'SCOPED_A_2'
+.*iface scope2 in scope1: 'SCOPED_A_2'
+.*custom scope1: 'SCOPED_A_1;SCOPED_B_1'
+.*custom scope2: 'SCOPED_A_2'
+.*custom scope2 in scope1: 'SCOPED_A_1'
diff --git a/Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope.c b/Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope.c
new file mode 100644
index 0000000..a4bec6f
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope.c
@@ -0,0 +1,12 @@
+#ifndef SCOPED_A_1
+# error "SCOPED_A_1 not defined"
+#endif
+#ifndef SCOPED_B_1
+# error "SCOPED_B_1 not defined"
+#endif
+#ifndef SCOPED_A_2
+# error "SCOPED_A_2 not defined"
+#endif
+void Scope(void)
+{
+}
diff --git a/Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope.cmake b/Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope.cmake
new file mode 100644
index 0000000..48a878a
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope.cmake
@@ -0,0 +1,19 @@
+enable_language(C)
+
+add_subdirectory(Scope1)
+add_subdirectory(Scope2)
+
+add_library(Scope Scope.c)
+target_link_libraries(Scope PRIVATE
+ scope1_iface
+ scope2_iface
+ )
+
+add_custom_target(Custom ALL VERBATIM
+ COMMAND ${CMAKE_COMMAND} -E echo "iface scope1: '$<TARGET_PROPERTY:scope1_iface,INTERFACE_COMPILE_DEFINITIONS>'"
+ COMMAND ${CMAKE_COMMAND} -E echo "iface scope2: '$<TARGET_PROPERTY:scope2_iface,INTERFACE_COMPILE_DEFINITIONS>'"
+ COMMAND ${CMAKE_COMMAND} -E echo "iface scope2 in scope1: '$<TARGET_GENEX_EVAL:scope1_iface,$<TARGET_PROPERTY:scope2_iface,INTERFACE_COMPILE_DEFINITIONS>>'"
+ COMMAND ${CMAKE_COMMAND} -E echo "custom scope1: '$<TARGET_GENEX_EVAL:scope1_iface,$<TARGET_PROPERTY:scope1_iface,CUSTOM_PROP>>'"
+ COMMAND ${CMAKE_COMMAND} -E echo "custom scope2: '$<TARGET_GENEX_EVAL:scope2_iface,$<TARGET_PROPERTY:scope2_iface,CUSTOM_PROP>>'"
+ COMMAND ${CMAKE_COMMAND} -E echo "custom scope2 in scope1: '$<TARGET_GENEX_EVAL:scope1_iface,$<TARGET_PROPERTY:scope2_iface,CUSTOM_PROP>>'"
+ )
diff --git a/Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope1/CMakeLists.txt b/Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope1/CMakeLists.txt
new file mode 100644
index 0000000..d546267
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope1/CMakeLists.txt
@@ -0,0 +1,15 @@
+add_library(scopedA INTERFACE IMPORTED)
+set_property(TARGET scopedA PROPERTY INTERFACE_COMPILE_DEFINITIONS "SCOPED_A_1")
+
+add_library(scopedB INTERFACE IMPORTED)
+set_property(TARGET scopedB PROPERTY INTERFACE_COMPILE_DEFINITIONS "SCOPED_B_1")
+
+add_library(scope1_iface INTERFACE)
+set_property(TARGET scope1_iface PROPERTY INTERFACE_COMPILE_DEFINITIONS
+ "$<TARGET_PROPERTY:scopedA,INTERFACE_COMPILE_DEFINITIONS>"
+ "$<TARGET_PROPERTY:scopedB,INTERFACE_COMPILE_DEFINITIONS>"
+ )
+set_property(TARGET scope1_iface PROPERTY CUSTOM_PROP
+ "$<TARGET_PROPERTY:scopedA,INTERFACE_COMPILE_DEFINITIONS>"
+ "$<TARGET_PROPERTY:scopedB,INTERFACE_COMPILE_DEFINITIONS>"
+ )
diff --git a/Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope2/CMakeLists.txt b/Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope2/CMakeLists.txt
new file mode 100644
index 0000000..a6d7e6b
--- /dev/null
+++ b/Tests/RunCMake/GenEx-TARGET_PROPERTY/Scope2/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_library(scopedA INTERFACE IMPORTED)
+set_property(TARGET scopedA PROPERTY INTERFACE_COMPILE_DEFINITIONS "SCOPED_A_2")
+
+add_library(scope2_iface INTERFACE)
+set_property(TARGET scope2_iface PROPERTY INTERFACE_COMPILE_DEFINITIONS
+ "$<TARGET_PROPERTY:scopedA,INTERFACE_COMPILE_DEFINITIONS>"
+ )
+set_property(TARGET scope2_iface PROPERTY CUSTOM_PROP
+ "$<TARGET_PROPERTY:scopedA,INTERFACE_COMPILE_DEFINITIONS>"
+ )
diff --git a/Tests/RunCMake/Swift/NoWorkToDo-nowork-stdout.txt b/Tests/RunCMake/Swift/NoWorkToDo-nowork-stdout.txt
new file mode 100644
index 0000000..60a9228
--- /dev/null
+++ b/Tests/RunCMake/Swift/NoWorkToDo-nowork-stdout.txt
@@ -0,0 +1 @@
+^ninja: no work to do
diff --git a/Tests/RunCMake/Swift/NoWorkToDo.cmake b/Tests/RunCMake/Swift/NoWorkToDo.cmake
new file mode 100644
index 0000000..e86a861
--- /dev/null
+++ b/Tests/RunCMake/Swift/NoWorkToDo.cmake
@@ -0,0 +1,2 @@
+enable_language(Swift)
+add_executable(hello hello.swift)
diff --git a/Tests/RunCMake/Swift/RunCMakeTest.cmake b/Tests/RunCMake/Swift/RunCMakeTest.cmake
index 21d5a25..7f4464d 100644
--- a/Tests/RunCMake/Swift/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Swift/RunCMakeTest.cmake
@@ -14,6 +14,16 @@ elseif(RunCMake_GENERATOR STREQUAL Ninja)
run_cmake(SwiftMultiArch)
unset(RunCMake_TEST_OPTIONS)
endif()
+
+ # Test that a second build with no changes does nothing.
+ block()
+ run_cmake(NoWorkToDo)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/NoWorkToDo-build)
+ set(RunCMake_TEST_OUTPUT_MERGE 1)
+ run_cmake_command(NoWorkToDo-build ${CMAKE_COMMAND} --build .)
+ run_cmake_command(NoWorkToDo-nowork ${CMAKE_COMMAND} --build . -- -d explain)
+ endblock()
endif()
elseif(RunCMake_GENERATOR STREQUAL "Ninja Multi-Config")
if(CMAKE_Swift_COMPILER)
diff --git a/Tests/RunCMake/file/DOWNLOAD-unused-argument.txt b/Tests/RunCMake/Swift/hello.swift
index e69de29..e69de29 100644
--- a/Tests/RunCMake/file/DOWNLOAD-unused-argument.txt
+++ b/Tests/RunCMake/Swift/hello.swift
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
new file mode 100644
index 0000000..9ab565a
--- /dev/null
+++ b/Tests/RunCMake/file-DOWNLOAD/input.png
Binary files differ
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-result.txt b/Tests/RunCMake/file-DOWNLOAD/netrc-bad.txt
index e69de29..e69de29 100644
--- a/Tests/RunCMake/file/DOWNLOAD-unused-argument-result.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-no-save-hash.txt b/Tests/RunCMake/file-DOWNLOAD/no-save-hash.txt
index e69de29..e69de29 100644
--- a/Tests/RunCMake/file/DOWNLOAD-no-save-hash.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-netrc-bad.txt b/Tests/RunCMake/file-DOWNLOAD/unused-argument-result.txt
index e69de29..e69de29 100644
--- a/Tests/RunCMake/file/DOWNLOAD-netrc-bad.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/COPY_FILE-file-INPUT_MAY_BE_RECENT.cmake b/Tests/RunCMake/file/COPY_FILE-file-INPUT_MAY_BE_RECENT.cmake
new file mode 100644
index 0000000..88bf448
--- /dev/null
+++ b/Tests/RunCMake/file/COPY_FILE-file-INPUT_MAY_BE_RECENT.cmake
@@ -0,0 +1,10 @@
+set(oldname "${CMAKE_CURRENT_BINARY_DIR}/input")
+set(newname "${CMAKE_CURRENT_BINARY_DIR}/output")
+file(WRITE "${oldname}" "")
+file(COPY_FILE "${oldname}" "${newname}" INPUT_MAY_BE_RECENT)
+if(NOT EXISTS "${oldname}")
+ message(FATAL_ERROR "The old name does not exist:\n ${oldname}")
+endif()
+if(NOT EXISTS "${newname}")
+ message(FATAL_ERROR "The new name does not exist:\n ${newname}")
+endif()
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-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 4ad00ff..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)
@@ -59,6 +51,7 @@ run_cmake_script(COPY_FILE-dirlink-to-file-fail)
run_cmake_script(COPY_FILE-file-to-file)
run_cmake_script(COPY_FILE-file-to-dir-capture)
run_cmake_script(COPY_FILE-file-to-dir-fail)
+run_cmake_script(COPY_FILE-file-INPUT_MAY_BE_RECENT)
run_cmake_script(COPY_FILE-file-ONLY_IF_DIFFERENT-capture)
run_cmake_script(COPY_FILE-file-ONLY_IF_DIFFERENT-fail)
run_cmake_script(COPY_FILE-file-ONLY_IF_DIFFERENT-no-overwrite)
diff --git a/Utilities/ClangTidyModule/CMakeLists.txt b/Utilities/ClangTidyModule/CMakeLists.txt
index c51f43a..6fc54b1 100644
--- a/Utilities/ClangTidyModule/CMakeLists.txt
+++ b/Utilities/ClangTidyModule/CMakeLists.txt
@@ -22,6 +22,8 @@ add_library(cmake-clang-tidy-module MODULE
UseCmstrlenCheck.h
UseCmsysFstreamCheck.cxx
UseCmsysFstreamCheck.h
+ UsePragmaOnceCheck.cxx
+ UsePragmaOnceCheck.h
)
target_include_directories(cmake-clang-tidy-module PRIVATE ${CLANG_INCLUDE_DIRS})
target_link_libraries(cmake-clang-tidy-module PRIVATE clang-tidy)
diff --git a/Utilities/ClangTidyModule/Module.cxx b/Utilities/ClangTidyModule/Module.cxx
index 7ef8e7d..c747cee 100644
--- a/Utilities/ClangTidyModule/Module.cxx
+++ b/Utilities/ClangTidyModule/Module.cxx
@@ -7,6 +7,7 @@
#include "UseBespokeEnumClassCheck.h"
#include "UseCmstrlenCheck.h"
#include "UseCmsysFstreamCheck.h"
+#include "UsePragmaOnceCheck.h"
namespace clang {
namespace tidy {
@@ -23,6 +24,7 @@ public:
"cmake-use-bespoke-enum-class");
CheckFactories.registerCheck<OstringstreamUseCmstrcatCheck>(
"cmake-ostringstream-use-cmstrcat");
+ CheckFactories.registerCheck<UsePragmaOnceCheck>("cmake-use-pragma-once");
}
};
diff --git a/Utilities/ClangTidyModule/Tests/CMakeLists.txt b/Utilities/ClangTidyModule/Tests/CMakeLists.txt
index 5bf0e89..b53d5d2 100644
--- a/Utilities/ClangTidyModule/Tests/CMakeLists.txt
+++ b/Utilities/ClangTidyModule/Tests/CMakeLists.txt
@@ -14,3 +14,4 @@ add_run_clang_tidy_test(cmake-use-cmstrlen)
add_run_clang_tidy_test(cmake-use-cmsys-fstream)
add_run_clang_tidy_test(cmake-use-bespoke-enum-class)
add_run_clang_tidy_test(cmake-ostringstream-use-cmstrcat)
+add_run_clang_tidy_test(cmake-use-pragma-once)
diff --git a/Utilities/ClangTidyModule/Tests/RunClangTidy.cmake b/Utilities/ClangTidyModule/Tests/RunClangTidy.cmake
index 7fd7cdd..98770d7 100644
--- a/Utilities/ClangTidyModule/Tests/RunClangTidy.cmake
+++ b/Utilities/ClangTidyModule/Tests/RunClangTidy.cmake
@@ -13,12 +13,22 @@ endif()
set(source_file "${RunClangTidy_BINARY_DIR}/${CHECK_NAME}.cxx")
configure_file("${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}.cxx" "${source_file}" COPYONLY)
+file(GLOB header_files RELATIVE "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}" "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}/*")
+file(REMOVE_RECURSE "${RunClangTiy_BINARY_DIR}/${CHECK_NAME}")
+foreach(header_file IN LISTS header_files)
+ if(NOT header_file MATCHES "-fixit\\.h\$")
+ file(MAKE_DIRECTORY "${RunClangTidy_BINARY_DIR}/${CHECK_NAME}")
+ configure_file("${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}/${header_file}" "${RunClangTidy_BINARY_DIR}/${CHECK_NAME}/${header_file}" COPYONLY)
+ endif()
+endforeach()
+
set(command
"${CLANG_TIDY_COMMAND}"
"--load=${CLANG_TIDY_MODULE}"
"--checks=-*,${CHECK_NAME}"
"--fix"
"--format-style=file"
+ "--header-filter=/${CHECK_NAME}/"
${config_arg}
"${source_file}"
--
@@ -44,18 +54,38 @@ if(NOT actual_stdout STREQUAL expect_stdout)
string(APPEND RunClangTidy_TEST_FAILED "Expected stdout:\n${expect_stdout_formatted}\nActual stdout:\n${actual_stdout_formatted}\n")
endif()
-if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}-fixit.cxx")
- set(expect_fixit_file "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}-fixit.cxx")
-else()
- set(expect_fixit_file "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}.cxx")
-endif()
-file(READ "${expect_fixit_file}" expect_fixit)
-file(READ "${source_file}" actual_fixit)
-if(NOT expect_fixit STREQUAL actual_fixit)
- string(REPLACE "\n" "\n " expect_fixit_formatted " ${expect_fixit}")
- string(REPLACE "\n" "\n " actual_fixit_formatted " ${actual_fixit}")
- string(APPEND RunClangTidy_TEST_FAILED "Expected fixit:\n${expect_fixit_formatted}\nActual fixit:\n${actual_fixit_formatted}\n")
-endif()
+function(check_fixit expected fallback_expected actual)
+ if(EXISTS "${expected}")
+ set(expect_fixit_file "${expected}")
+ else()
+ set(expect_fixit_file "${fallback_expected}")
+ endif()
+ file(READ "${expect_fixit_file}" expect_fixit)
+ file(READ "${actual}" actual_fixit)
+ if(NOT expect_fixit STREQUAL actual_fixit)
+ string(REPLACE "\n" "\n " expect_fixit_formatted " ${expect_fixit}")
+ string(REPLACE "\n" "\n " actual_fixit_formatted " ${actual_fixit}")
+ string(APPEND RunClangTidy_TEST_FAILED "Expected fixit for ${actual}:\n${expect_fixit_formatted}\nActual fixit:\n${actual_fixit_formatted}\n")
+ set(RunClangTidy_TEST_FAILED "${RunClangTidy_TEST_FAILED}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+check_fixit(
+ "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}-fixit.cxx"
+ "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}.cxx"
+ "${source_file}"
+ )
+
+foreach(header_file IN LISTS header_files)
+ if(NOT header_file MATCHES "-fixit\\.h\$")
+ string(REGEX REPLACE "\\.h\$" "-fixit.h" header_fixit "${header_file}")
+ check_fixit(
+ "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}/${header_fixit}"
+ "${CMAKE_CURRENT_LIST_DIR}/${CHECK_NAME}/${header_file}"
+ "${RunClangTidy_BINARY_DIR}/${CHECK_NAME}/${header_file}"
+ )
+ endif()
+endforeach()
if(RunClangTidy_TEST_FAILED)
string(REPLACE ";" " " command_formatted "${command}")
diff --git a/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once-stdout.txt b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once-stdout.txt
new file mode 100644
index 0000000..e80e4a4
--- /dev/null
+++ b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once-stdout.txt
@@ -0,0 +1,25 @@
+cmake-use-pragma-once/cmake-use-pragma-once-both.h:1:1: warning: use #pragma once [cmake-use-pragma-once]
+#ifndef BOTH_H
+^~~~~~~~~~~~~~
+cmake-use-pragma-once/cmake-use-pragma-once-both.h:1:1: note: FIX-IT applied suggested code changes
+cmake-use-pragma-once/cmake-use-pragma-once-both.h:2:1: note: FIX-IT applied suggested code changes
+#define BOTH_H
+^
+cmake-use-pragma-once/cmake-use-pragma-once-both.h:10:1: note: FIX-IT applied suggested code changes
+#endif
+^
+cmake-use-pragma-once/cmake-use-pragma-once-include-guards.h:1:1: warning: use #pragma once [cmake-use-pragma-once]
+#ifndef INCLUDE_GUARDS_H
+^~~~~~~~~~~~~~~~~~~~~~~~
+#pragma once
+cmake-use-pragma-once/cmake-use-pragma-once-include-guards.h:1:1: note: FIX-IT applied suggested code changes
+cmake-use-pragma-once/cmake-use-pragma-once-include-guards.h:2:1: note: FIX-IT applied suggested code changes
+#define INCLUDE_GUARDS_H
+^
+cmake-use-pragma-once/cmake-use-pragma-once-include-guards.h:9:1: note: FIX-IT applied suggested code changes
+#endif
+^
+cmake-use-pragma-once/cmake-use-pragma-once-neither.h:1:1: warning: use #pragma once [cmake-use-pragma-once]
+int neither()
+^
+cmake-use-pragma-once/cmake-use-pragma-once-neither.h:1:1: note: FIX-IT applied suggested code changes
diff --git a/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once.cxx b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once.cxx
new file mode 100644
index 0000000..a571bc1
--- /dev/null
+++ b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once.cxx
@@ -0,0 +1,5 @@
+#include "cmake-use-pragma-once/cmake-use-pragma-once.h"
+
+#include "cmake-use-pragma-once/cmake-use-pragma-once-both.h"
+#include "cmake-use-pragma-once/cmake-use-pragma-once-include-guards.h"
+#include "cmake-use-pragma-once/cmake-use-pragma-once-neither.h"
diff --git a/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-both-fixit.h b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-both-fixit.h
new file mode 100644
index 0000000..73c9720
--- /dev/null
+++ b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-both-fixit.h
@@ -0,0 +1,8 @@
+
+
+#pragma once
+
+int both()
+{
+ return 0;
+}
diff --git a/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-both.h b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-both.h
new file mode 100644
index 0000000..fdf3cd3
--- /dev/null
+++ b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-both.h
@@ -0,0 +1,10 @@
+#ifndef BOTH_H
+#define BOTH_H
+#pragma once
+
+int both()
+{
+ return 0;
+}
+
+#endif
diff --git a/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-include-guards-fixit.h b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-include-guards-fixit.h
new file mode 100644
index 0000000..36461c2
--- /dev/null
+++ b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-include-guards-fixit.h
@@ -0,0 +1,6 @@
+#pragma once
+
+int includeGuards()
+{
+ return 0;
+}
diff --git a/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-include-guards.h b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-include-guards.h
new file mode 100644
index 0000000..687306d
--- /dev/null
+++ b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-include-guards.h
@@ -0,0 +1,9 @@
+#ifndef INCLUDE_GUARDS_H
+#define INCLUDE_GUARDS_H
+
+int includeGuards()
+{
+ return 0;
+}
+
+#endif
diff --git a/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-neither-fixit.h b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-neither-fixit.h
new file mode 100644
index 0000000..eb5c6dd
--- /dev/null
+++ b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-neither-fixit.h
@@ -0,0 +1,5 @@
+#pragma once
+int neither()
+{
+ return 0;
+}
diff --git a/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-neither.h b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-neither.h
new file mode 100644
index 0000000..c779ca0
--- /dev/null
+++ b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once-neither.h
@@ -0,0 +1,4 @@
+int neither()
+{
+ return 0;
+}
diff --git a/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once.h b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once.h
new file mode 100644
index 0000000..b0b2ea2
--- /dev/null
+++ b/Utilities/ClangTidyModule/Tests/cmake-use-pragma-once/cmake-use-pragma-once.h
@@ -0,0 +1,6 @@
+#pragma once
+
+int once()
+{
+ return 0;
+}
diff --git a/Utilities/ClangTidyModule/UsePragmaOnceCheck.cxx b/Utilities/ClangTidyModule/UsePragmaOnceCheck.cxx
new file mode 100644
index 0000000..7a42798
--- /dev/null
+++ b/Utilities/ClangTidyModule/UsePragmaOnceCheck.cxx
@@ -0,0 +1,325 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+/* This code was originally taken from part of the Clang-Tidy LLVM project and
+ * modified for use with CMake under the following original license: */
+
+//===--- HeaderGuard.cpp - clang-tidy
+//-------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
+// Exceptions. See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "UsePragmaOnceCheck.h"
+
+#include <algorithm>
+#include <cassert>
+
+#include <clang/Frontend/CompilerInstance.h>
+#include <clang/Lex/PPCallbacks.h>
+#include <clang/Lex/Preprocessor.h>
+#include <clang/Tooling/Tooling.h>
+#include <llvm/Support/Path.h>
+
+namespace clang {
+namespace tidy {
+namespace cmake {
+
+/// canonicalize a path by removing ./ and ../ components.
+static std::string cleanPath(StringRef Path)
+{
+ SmallString<256> Result = Path;
+ llvm::sys::path::remove_dots(Result, true);
+ return std::string(Result.str());
+}
+
+namespace {
+// This class is a workaround for the fact that PPCallbacks doesn't give us the
+// location of the hash for an #ifndef, #define, or #endif, so we have to find
+// it ourselves. We can't lex backwards, and attempting to turn on the
+// preprocessor's backtracking functionality wreaks havoc, so we have to
+// instantiate a second lexer and lex all the way from the beginning of the
+// file. Cache the results of this lexing so that we don't have to do it more
+// times than needed.
+//
+// TODO: Upstream a change to LLVM to give us the location of the hash in
+// PPCallbacks so we don't have to do this workaround.
+class DirectiveCache
+{
+public:
+ DirectiveCache(Preprocessor* PP, FileID FID)
+ : PP(PP)
+ , FID(FID)
+ {
+ SourceManager& SM = this->PP->getSourceManager();
+ const FileEntry* Entry = SM.getFileEntryForID(FID);
+ assert(Entry && "Invalid FileID given");
+
+ Lexer MyLexer(FID, SM.getMemoryBufferForFileOrFake(Entry), SM,
+ this->PP->getLangOpts());
+ Token Tok;
+
+ while (!MyLexer.LexFromRawLexer(Tok)) {
+ if (Tok.getKind() == tok::hash) {
+ assert(SM.getFileID(Tok.getLocation()) == this->FID &&
+ "Token FileID does not match passed FileID");
+ if (!this->HashLocs.empty()) {
+ assert(SM.getFileOffset(this->HashLocs.back()) <
+ SM.getFileOffset(Tok.getLocation()) &&
+ "Tokens in file are not in order");
+ }
+
+ this->HashLocs.push_back(Tok.getLocation());
+ }
+ }
+ }
+
+ SourceRange createRangeForIfndef(SourceLocation IfndefMacroTokLoc)
+ {
+ // The #ifndef of an include guard is likely near the beginning of the
+ // file, so search from the front.
+ return SourceRange(this->findPreviousHashFromFront(IfndefMacroTokLoc),
+ IfndefMacroTokLoc);
+ }
+
+ SourceRange createRangeForDefine(SourceLocation DefineMacroTokLoc)
+ {
+ // The #define of an include guard is likely near the beginning of the
+ // file, so search from the front.
+ return SourceRange(this->findPreviousHashFromFront(DefineMacroTokLoc),
+ DefineMacroTokLoc);
+ }
+
+ SourceRange createRangeForEndif(SourceLocation EndifLoc)
+ {
+ // The #endif of an include guard is likely near the end of the file, so
+ // search from the back.
+ return SourceRange(this->findPreviousHashFromBack(EndifLoc), EndifLoc);
+ }
+
+private:
+ Preprocessor* PP;
+ FileID FID;
+ SmallVector<SourceLocation> HashLocs;
+
+ SourceLocation findPreviousHashFromFront(SourceLocation Loc)
+ {
+ SourceManager& SM = this->PP->getSourceManager();
+ Loc = SM.getExpansionLoc(Loc);
+ assert(SM.getFileID(Loc) == this->FID &&
+ "Loc FileID does not match our FileID");
+
+ auto It = std::find_if(
+ this->HashLocs.begin(), this->HashLocs.end(),
+ [&SM, &Loc](const SourceLocation& OtherLoc) -> bool {
+ return SM.getFileOffset(OtherLoc) >= SM.getFileOffset(Loc);
+ });
+ assert(It != this->HashLocs.begin() &&
+ "No hash associated with passed Loc");
+ return *--It;
+ }
+
+ SourceLocation findPreviousHashFromBack(SourceLocation Loc)
+ {
+ SourceManager& SM = this->PP->getSourceManager();
+ Loc = SM.getExpansionLoc(Loc);
+ assert(SM.getFileID(Loc) == this->FID &&
+ "Loc FileID does not match our FileID");
+
+ auto It =
+ std::find_if(this->HashLocs.rbegin(), this->HashLocs.rend(),
+ [&SM, &Loc](const SourceLocation& OtherLoc) -> bool {
+ return SM.getFileOffset(OtherLoc) < SM.getFileOffset(Loc);
+ });
+ assert(It != this->HashLocs.rend() &&
+ "No hash associated with passed Loc");
+ return *It;
+ }
+};
+
+class UsePragmaOncePPCallbacks : public PPCallbacks
+{
+public:
+ UsePragmaOncePPCallbacks(Preprocessor* PP, UsePragmaOnceCheck* Check)
+ : PP(PP)
+ , Check(Check)
+ {
+ }
+
+ void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID) override
+ {
+ // Record all files we enter. We'll need them to diagnose headers without
+ // guards.
+ SourceManager& SM = this->PP->getSourceManager();
+ if (Reason == EnterFile && FileType == SrcMgr::C_User) {
+ if (const FileEntry* FE = SM.getFileEntryForID(SM.getFileID(Loc))) {
+ std::string FileName = cleanPath(FE->getName());
+ this->Files[FileName] = FE;
+ }
+ }
+ }
+
+ void Ifndef(SourceLocation Loc, const Token& MacroNameTok,
+ const MacroDefinition& MD) override
+ {
+ if (MD) {
+ return;
+ }
+
+ // Record #ifndefs that succeeded. We also need the Location of the Name.
+ this->Ifndefs[MacroNameTok.getIdentifierInfo()] =
+ std::make_pair(Loc, MacroNameTok.getLocation());
+ }
+
+ void MacroDefined(const Token& MacroNameTok,
+ const MacroDirective* MD) override
+ {
+ // Record all defined macros. We store the whole token to get info on the
+ // name later.
+ this->Macros.emplace_back(MacroNameTok, MD->getMacroInfo());
+ }
+
+ void Endif(SourceLocation Loc, SourceLocation IfLoc) override
+ {
+ // Record all #endif and the corresponding #ifs (including #ifndefs).
+ this->EndIfs[IfLoc] = Loc;
+ }
+
+ void EndOfMainFile() override
+ {
+ // Now that we have all this information from the preprocessor, use it!
+ SourceManager& SM = this->PP->getSourceManager();
+
+ for (const auto& MacroEntry : this->Macros) {
+ const MacroInfo* MI = MacroEntry.second;
+
+ // We use clang's header guard detection. This has the advantage of also
+ // emitting a warning for cases where a pseudo header guard is found but
+ // preceded by something blocking the header guard optimization.
+ if (!MI->isUsedForHeaderGuard()) {
+ continue;
+ }
+
+ const FileEntry* FE =
+ SM.getFileEntryForID(SM.getFileID(MI->getDefinitionLoc()));
+ std::string FileName = cleanPath(FE->getName());
+ this->Files.erase(FileName);
+
+ // Look up Locations for this guard.
+ SourceLocation Ifndef =
+ this->Ifndefs[MacroEntry.first.getIdentifierInfo()].second;
+ SourceLocation Define = MacroEntry.first.getLocation();
+ SourceLocation EndIf =
+ this
+ ->EndIfs[this->Ifndefs[MacroEntry.first.getIdentifierInfo()].first];
+
+ StringRef CurHeaderGuard =
+ MacroEntry.first.getIdentifierInfo()->getName();
+ std::vector<FixItHint> FixIts;
+
+ HeaderSearch& HeaderInfo = this->PP->getHeaderSearchInfo();
+
+ HeaderFileInfo& Info = HeaderInfo.getFileInfo(FE);
+
+ DirectiveCache Cache(this->PP, SM.getFileID(MI->getDefinitionLoc()));
+ SourceRange IfndefSrcRange = Cache.createRangeForIfndef(Ifndef);
+ SourceRange DefineSrcRange = Cache.createRangeForDefine(Define);
+ SourceRange EndifSrcRange = Cache.createRangeForEndif(EndIf);
+
+ if (Info.isPragmaOnce) {
+ FixIts.push_back(FixItHint::CreateRemoval(IfndefSrcRange));
+ } else {
+ FixIts.push_back(
+ FixItHint::CreateReplacement(IfndefSrcRange, "#pragma once"));
+ }
+
+ FixIts.push_back(FixItHint::CreateRemoval(DefineSrcRange));
+ FixIts.push_back(FixItHint::CreateRemoval(EndifSrcRange));
+
+ this->Check->diag(IfndefSrcRange.getBegin(), "use #pragma once")
+ << FixIts;
+ }
+
+ // Emit warnings for headers that are missing guards.
+ checkGuardlessHeaders();
+ clearAllState();
+ }
+
+ /// Looks for files that were visited but didn't have a header guard.
+ /// Emits a warning with fixits suggesting adding one.
+ void checkGuardlessHeaders()
+ {
+ // Look for header files that didn't have a header guard. Emit a warning
+ // and fix-its to add the guard.
+ // TODO: Insert the guard after top comments.
+ for (const auto& FE : this->Files) {
+ StringRef FileName = FE.getKey();
+ if (!Check->shouldSuggestToAddPragmaOnce(FileName)) {
+ continue;
+ }
+
+ SourceManager& SM = this->PP->getSourceManager();
+ FileID FID = SM.translateFile(FE.getValue());
+ SourceLocation StartLoc = SM.getLocForStartOfFile(FID);
+ if (StartLoc.isInvalid()) {
+ continue;
+ }
+
+ HeaderSearch& HeaderInfo = this->PP->getHeaderSearchInfo();
+
+ HeaderFileInfo& Info = HeaderInfo.getFileInfo(FE.second);
+ if (Info.isPragmaOnce) {
+ continue;
+ }
+
+ this->Check->diag(StartLoc, "use #pragma once")
+ << FixItHint::CreateInsertion(StartLoc, "#pragma once\n");
+ }
+ }
+
+private:
+ void clearAllState()
+ {
+ this->Macros.clear();
+ this->Files.clear();
+ this->Ifndefs.clear();
+ this->EndIfs.clear();
+ }
+
+ std::vector<std::pair<Token, const MacroInfo*>> Macros;
+ llvm::StringMap<const FileEntry*> Files;
+ std::map<const IdentifierInfo*, std::pair<SourceLocation, SourceLocation>>
+ Ifndefs;
+ std::map<SourceLocation, SourceLocation> EndIfs;
+
+ Preprocessor* PP;
+ UsePragmaOnceCheck* Check;
+};
+} // namespace
+
+void UsePragmaOnceCheck::storeOptions(ClangTidyOptions::OptionMap& Opts)
+{
+ this->Options.store(Opts, "HeaderFileExtensions",
+ RawStringHeaderFileExtensions);
+}
+
+void UsePragmaOnceCheck::registerPPCallbacks(const SourceManager& SM,
+ Preprocessor* PP,
+ Preprocessor* ModuleExpanderPP)
+{
+ PP->addPPCallbacks(std::make_unique<UsePragmaOncePPCallbacks>(PP, this));
+}
+
+bool UsePragmaOnceCheck::shouldSuggestToAddPragmaOnce(StringRef FileName)
+{
+ return utils::isFileExtension(FileName, this->HeaderFileExtensions);
+}
+
+} // namespace cmake
+} // namespace tidy
+} // namespace clang
diff --git a/Utilities/ClangTidyModule/UsePragmaOnceCheck.h b/Utilities/ClangTidyModule/UsePragmaOnceCheck.h
new file mode 100644
index 0000000..08c2099
--- /dev/null
+++ b/Utilities/ClangTidyModule/UsePragmaOnceCheck.h
@@ -0,0 +1,60 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+/* This code was originally taken from part of the Clang-Tidy LLVM project and
+ * modified for use with CMake under the following original license: */
+
+//===--- HeaderGuard.h - clang-tidy -----------------------------*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
+// Exceptions. See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include <clang-tidy/ClangTidyCheck.h>
+#include <clang-tidy/utils/FileExtensionsUtils.h>
+
+namespace clang {
+namespace tidy {
+namespace cmake {
+
+/// Finds and replaces header guards with pragma once.
+/// The check supports these options:
+/// - `HeaderFileExtensions`: a semicolon-separated list of filename
+/// extensions of header files (The filename extension should not contain
+/// "." prefix). ";h;hh;hpp;hxx" by default.
+///
+/// For extension-less header files, using an empty string or leaving an
+/// empty string between ";" if there are other filename extensions.
+class UsePragmaOnceCheck : public ClangTidyCheck
+{
+public:
+ UsePragmaOnceCheck(StringRef Name, ClangTidyContext* Context)
+ : ClangTidyCheck(Name, Context)
+ , RawStringHeaderFileExtensions(Options.getLocalOrGlobal(
+ "HeaderFileExtensions", utils::defaultHeaderFileExtensions()))
+ {
+ utils::parseFileExtensions(RawStringHeaderFileExtensions,
+ HeaderFileExtensions,
+ utils::defaultFileExtensionDelimiters());
+ }
+ void storeOptions(ClangTidyOptions::OptionMap& Opts) override;
+ void registerPPCallbacks(const SourceManager& SM, Preprocessor* PP,
+ Preprocessor* ModuleExpanderPP) override;
+
+ /// Returns ``true`` if the check should add pragma once to the file
+ /// if it has none.
+ virtual bool shouldSuggestToAddPragmaOnce(StringRef Filename);
+
+private:
+ std::string RawStringHeaderFileExtensions;
+ utils::FileExtensionsSet HeaderFileExtensions;
+};
+
+} // namespace cmake
+} // namespace tidy
+} // namespace clang